因爲依賴服務的線程池有限,將出現排隊等待與響應延遲的情況,爲了優化這些問題,Hystrix提供了HystrixCollapser來實現請求的合併,以減少 通信消耗和線程數的佔用。
HystrixCollapser實現了在HystrixCommand之前放置一個合併處理器,將處於一個很短的時間窗(默認10毫秒)內對同一依賴服務的多個請求進行整合並以批量方式發起請求的功能(服務提供方也需要提供相應的批量實現接口)。
這裏我們只講解使用註解實現請求合併器。
首先服務提供者,需要包含一個批量處理的服務。
@RequestMapping("/getbook6")
public List<String> book6(String ids) {
System.out.println("ids>>>>>>>>>>>>>>>>>>>>>" + ids);
ArrayList<String> books = new ArrayList<>();
books.add("哈哈2");
books.add("哈哈3");
books.add("哈哈4");
books.add("哈哈5");
books.add("哈哈6");
return books;
}
@RequestMapping("/getbook6/{id}")
public String book61(@PathVariable Integer id) {
return "哈哈1";
}
服務消費者service:
@Service
public class HelloService2 {
@Autowired
private RestTemplate restTemplate;
@HystrixCollapser(batchMethod = "test11",collapserProperties = {@HystrixProperty(name ="timerDelayInMilliseconds",value = "1000")})
public Future<String> test10(Long id) {
return null;
}
@HystrixCommand
public List<String> test11(List<Long> ids) {
System.out.println("test9---------"+ids+"Thread.currentThread().getName():" + Thread.currentThread().getName());
String[] books = restTemplate.getForObject("http://HELLOSERVICE-1/getbook6?ids={1}", String[].class, StringUtils.join(ids, ","));
return Arrays.asList(books);
}
}
服務消費者controller:
@RequestMapping("/test8")
@ResponseBody
public void test8() throws ExecutionException, InterruptedException {
// HystrixRequestContext context = HystrixRequestContext.initializeContext();
Future<String> f1 = helloService2.test10(1l);
Future<String> f2 = helloService2.test10(2l);
Future<String> f3 = helloService2.test10(3l);
String b1 = f1.get();
String b2 = f2.get();
String b3 = f3.get();
Thread.sleep(3000);
Future<String> f4 = helloService2.test10(4l);
String b4 = f4.get();
System.out.println("b1>>>"+b1);
System.out.println("b2>>>"+b2);
System.out.println("b3>>>"+b3);
System.out.println("b4>>>"+b4);
// context.close();
}
結果:
前三個請求和合並,因爲時間窗的時間是1秒,睡眠3秒後,最後一個請求單獨執行,ok。
請求合併的優點小夥伴們已經看到了,多個請求被合併爲一個請求進行一次性處理,可以有效節省網絡帶寬和線程池資源,但是,有優點必然也有缺點,設置請求合併之後,本來一個請求可能5ms就搞定了,但是現在必須再等10ms看看還有沒有其他的請求一起的,這樣一個請求的耗時就從5ms增加到15ms了,不過,如果我們要發起的命令本身就是一個高延遲的命令,那麼這個時候就可以使用請求合併了,因爲這個時候時間窗的時間消耗就顯得微不足道了,另外高併發也是請求合併的一個非常重要的場景。
請求合併的時間窗會帶來額外開銷,所以時候使用請求合併器需要根據依賴服務調用的實際情況,主要參考以下兩個方面:
1.請求本身的延遲
2、延遲時間窗內的併發量