Hystrix—请求合并
发布日期:2022-02-14 16:09:32 浏览次数:25 分类:技术文章

本文共 2530 字,大约阅读时间需要 8 分钟。

通常微服务架构中的依赖通过远程调用实现,**而远程调用中最常见的问题就是通信消耗与连接数占用。**在高并发的情况下,因为通信次数的增加,总的通信时间消耗会变得不那个理想。同时,因为对依赖服务线程池资源有限,将出现排队等待与响应延迟的情况。为了优化这两个问题,Hystrix提供了HystrixCollapser来实现请求的合并,以减少通信消耗和线程数的占用。

1. 理论

1. 请求合并的优点

把重复的请求批量的用一个HystrixCommand命令去执行,以减少通信消耗和线程数的占用,默认合并10ms之内的请求,可以减少通信开销

2. 请求合并的缺点

虽然请求合并可以减少请求数量以缓解依赖服务线程池的资源,但是在使用的过程中也需要注意他所带来的额外的性能开销:用于请求合并的延迟时间窗会使得依赖服务的请求延迟增高。

**例如:**某个请求在不通过请求合并器访问的平均耗时为5ms,请求合并的延迟时间窗为10ms(默认值),那么当该请求的设置了请求合并器之后,最坏情况下(在延迟时间窗结束时才发起请求)该请求需要15ms才能完成。

3. 请求合并适用场景

服务提供者提供了**“返回单个对象”“返回多个对象”**的查询接口,并且单个对象查询并发很高,服务提供者负载很高的时候,我们就可以使用请求合并来降低服务提供者的负载。

由于请求合并器的延迟时间窗会带来额外开销,所以我们是否使用请求合并器需要根据依赖服务调用的实际情况来选择,主要考虑下面两个方面:

  1. **【请求命令本身就是高延迟命令】**请求命令本身的延迟。如果依赖服务的请求命令本身是一个高延迟的命令,那么可以使用请求合并器,因为延迟时间窗的时间消耗就显得莫不足道了。
  2. **【延迟时间窗的并发量】**延迟时间窗内的并发量。如果一个时间窗内只有1-2个请求,那么这样的依赖服务不适合使用请求合并器,这种情况下不但不能提升系统性能,反而会成为系统瓶颈,因为每个请求都需要多消耗一个时间窗才响应。**相反,如果一个时间窗内具有很高的并发量,并且服务提供方也实现了批量处理接口,**那么使用请求合并器可以有效的减少网络连接数量并极大地提升系统吞吐量,此时延迟时间窗所增加的消耗就可以忽略不计了。

请求合并原理.png

2. 实践

@HystrixCollapser(batchMethod = "findAll",            collapserProperties = {                    @HystrixProperty(name = "timerDelayInMilliseconds", value = "3000")  //请求之间的延迟            })    public Future
findAcc(String id) { //你会发现根本不会进入这个方法体 log.info("findAcc方法,ids= " + id); return null; } @HystrixCommand public List
findAll(List
ids) { log.info("合并请求线程操作:{}", Thread.currentThread().getName()); String url = "http://localhost:8001/getInfos"; List
accounts = null; try { accounts = HttpClientUtils.doPost(url, ids, new TypeReference
>() { }); } catch (IOException e) { e.printStackTrace(); } return accounts; }

调用请求

@RequestMapping("findAcc")    @ResponseBody    public String findCollapser() throws ExecutionException, InterruptedException {        //开启context        HystrixRequestContext context = HystrixRequestContext.initializeContext();        Future
acc1 = accountServiceImpl.findAcc("001"); Future
acc2 = accountServiceImpl.findAcc("002"); Account account1 = acc1.get(); Account account2 = acc2.get(); List
accounts = new ArrayList<>(); accounts.add(account1); accounts.add(account2); context.shutdown(); return JSON.toJSONString(accounts); }

1. 这里单个请求的service返回的是Future对象,若是返回原对象,则是同步请求,不会进行请求合并的。

2. @HystrixCollapser中有scope属性,scope的取值为REQUEST, GLOBAL。

REQUEST范围只对一个request请求内的多次服务请求进行合并,GLOBAL是多单个应用中的所有线程的请求中的多次服务请求进行合并。

文章参考

转载地址:https://blog.csdn.net/qq_29595463/article/details/100544742 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:【SpringBoot2.x-2】Hystrix项目熔断
下一篇:【SpringBoot2.x-1】初始化方法汇总

发表评论

最新留言

哈哈,博客排版真的漂亮呢~
[***.90.31.176]2024年04月01日 15时54分41秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章