栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

详解spring cloud hystrix 请求合并collapsing

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

详解spring cloud hystrix 请求合并collapsing

在HystrixCommand之前可以使用请求合并器(HystrixCollapser就是一个抽象的父类)来把多个请求合并成一个然后对后端依赖系统发起调用。

下图显示了两种情况下线程的数量和网络的连接数的情况:第一种是不使用合并器,第二种是使用请求合并器(假设所有的链接都是在一个短的时间窗口内并行的,比如10ms内)。

为什么要使用请求合并?

使用请求合并来减少执行并发HystrixCommand执行所需的线程数和网络连接数,请求合并是自动执行的,不会强制开发人员手动协调批处理请求。

全局上下文-global context(跨越所有Tomcat线程)

这种合并类型是在全局应用级别上完成的,因此任何Tomcat线程上的任何用户的请求都可以一起合并。

例如,如果您配置一个HystrixCommand支持任何用户请求依赖关系来检索电影评级,那么当同一个JVM中的任何用户线程发出这样的请求时,Hystrix会将其请求与任何其他请求一起添加到同一个已折叠网络通话。

用户请求上下文-request context(单个Tomcat线程)

如果你配置一个HystrixCommand仅仅为一个单个用户处理批量请求,Hystrix可以在一个Tomcat线程(请求)中合并请求。

例如,一个用户想要加载300个视频对象的书签,不是去执行300次网络请求,Hystrix能够将他们合并成为一个。

Hystrix默认是的就是request-scope,要使用request-scoped的功能(request caching,request collapsing, request log)你必须管理HystrixRequestContext的生命周期(或者实现一个可替代的HystrixConcurrencyStrategy)
这就意味你在执行一个请求之前需要执行以下的代码:

复制代码 代码如下:HystrixRequestContext  context=HystrixRequestContext.initializeContext();

并且在请求的结束位置执行:

context.shutdown();

在标准的JavaWeb应用中,你也可以使用一个Servlet过滤器来初始化这个生命周期

public class HystrixRequestContextServletFilter implements Filter {

 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
  throws IOException, ServletException {
  HystrixRequestContext context = HystrixRequestContext.initializeContext();
  try {
   chain.doFilter(request, response);
  } finally {
   context.shutdown();
  }
 }
}

然后将它配置在web.xml中

 
  HystrixRequestContextServletFilter
  HystrixRequestContextServletFilter
  com.netflix.hystrix.contrib.requestservlet.HystrixRequestContextServletFilter
 
 
  HystrixRequestContextServletFilter
  
 @RequestMapping(value = "user/getUser.json",method = RequestMethod.GET)
 User findUserById(@RequestParam("id") Integer id);


 
 @RequestMapping(value = "user/getAllUser.json",method = RequestMethod.GET)
 List findAllUser(@RequestParam("ids") String ids);
}

UserService(设置为全局上下文)

@Service
public class UserService {
 @Autowired
 private UserFeignClient userFeignClient;



 
 @HystrixCollapser(collapserKey = "findCollapserKey",scope = com.netflix.hystrix.HystrixCollapser.Scope.GLOBAL,batchMethod = "findAllUser",collapserProperties = {
   @HystrixProperty(name = "timerDelayInMilliseconds",value = "5000" ),
   @HystrixProperty(name = "maxRequestsInBatch",value = "5" )
 })
 public Future find(Integer id){
  return null;
 }

 @HystrixCommand(commandKey = "findAllUser")
 public List findAllUser(List ids){
  return userFeignClient.findAllUser(StringUtils.join(ids,","));
 }
}

FeignCollapserController

@RequestMapping("user")
@RestController
public class FeignCollapserController {
 @Autowired
 private UserService userService;
 @RequestMapping("findUser")
 public User getUser(Integer id) throws ExecutionException, InterruptedException {
  return userService.find(id).get();
 }

上面的代码我们这是的是全局上下文(所有tomcat的线程的请求都可以合并),合并的时间窗口为5s(每一次请求都得等5s才发起请求),最大合并数为5。我们在postman中,5s之内发起两次请求,用户id不一样。

localhost:8082/user/findUser.json?id=123189891

localhost:8082/user/findUser.json?id=222222

结果如下图所示,两次请求合并为一次请求批量请求。

我们再来测试一下请求上下文(Request-Scope)的情况,加入上面所提到的HystrixRequestContextServletFilter,并修改UserService

HystrixRequestContextServletFilter


@WebFilter(filterName = "hystrixRequestContextServletFilter",urlPatterns = "
 @HystrixCollapser(collapserKey = "findCollapserKey",scope = com.netflix.hystrix.HystrixCollapser.Scope.REQUEST,batchMethod = "findAllUser",collapserProperties = {
   @HystrixProperty(name = "timerDelayInMilliseconds",value = "5000" ),
   @HystrixProperty(name = "maxRequestsInBatch",value = "5" )
 })
 public Future find(Integer id){
  return null;
 }

 @HystrixCommand(commandKey = "findAllUser")
 public List findAllUser(List ids){
  return userFeignClient.findAllUser(StringUtils.join(ids,","));
 }
}

FeignCollapser2Controller

@RequestMapping("user")
@RestController
public class FeignCollapser2Controller {
 @Autowired
 private UserService userService;

 @RequestMapping("findUser2")
 public List getUser() throws ExecutionException, InterruptedException {
  Future user1 = userService.find(1989);
  Future user2= userService.find(1990);
  List users = new ArrayList<>();
  users.add(user1.get());
  users.add(user2.get());
  return users;
 }
}

我们在postman中输入:localhost:8082/user/findUser2.json

 

可以看到一个请求内的两次连续调用被合并了。这个地方要注意,不能直接使用userServer.find(1989).get(),否则直接按同步执行处理,不会合并。如果两个tab页同时调用上述地址,发现发起了两次批量请求,说明作用域是request范围。

参考资料如下:

https://github.com/Netflix/Hystrix/wiki/How-To-Use
https://www.jb51.net/article/140530.htm

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持考高分网。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/140846.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号