一、请求合并的原理 NetFlix在Hystrix为我们提供了应对高并发的解决方案----请求合并,如下图 通过请求合并器设置延迟时间,将时间内的,多个请求单个的对象的方法中的参数(id)取出来,拼成符合服务提供者的多个对象返回接口(getUsersByIds方法)的参数,指定调用这个接口(getUsersByIds方法),返回的对象List再通过一个方法(mapResponseToRequests方法),按照请求的次序将结果对象对应的装到Request对应的Response中返回结果。

一、请求合并的原理
NetFlix在Hystrix为我们提供了应对高并发的解决方案----请求合并,如下图 

h

通过请求合并器设置延迟时间,将时间内的,多个请求单个的对象的方法中的参数(id)取出来,拼成符合服务提供者的多个对象返回接口(getUsersByIds方法)的参数,指定调用这个接口(getUsersByIds方法),返回的对象List再通过一个方法(mapResponseToRequests方法),按照请求的次序将结果对象对应的装到Request对应的Response中返回结果。 需要JAVA Spring Cloud大型企业分布式微服务云构建的B2B2C电子商务平台源码一零三八七七四六二六

二、请求合并适用的场景

在服务提供者提供了返回单个对象和多个对象的查询接口,并且单个对象的查询并发数很高,服务提供者负载较高的时候,我们就可以使用请求合并来降低服务提供者的负载。
实现请求合并
1、传统方式
首先在服务提供者的GetRequestController中添加两个接口,用于打印是哪个方法被调用

/** * 为Hystrix请求合并提供的接口 */ @GetMapping("/users/{id}") public User getUserById(@PathVariable Long id){ logger.info("=========getUserById方法:入参ids:"+id); return new User("one"+id, "女", "110-"+id); } @GetMapping("/users") public List getUsersByIds(@RequestParam("ids") List ids){ List userList = new ArrayList<>(); User user; logger.info("=========getUsersByIds方法:入参ids:"+ids); for(Long id : ids){ user = new User("person"+id ,"男","123-"+id); userList.add(user); } System.out.println(userList); return userList; }

在消费者(RibbonConsumHystrix)项目中的RibbonController中实现简单的调用上边的两个接口

/** * 单个请求处理 * @param id */ @GetMapping("/users/{id}") public User findOne(@PathVariable Long id){ LOGGER.debug("=============/hystrix/users/{} 执行了", id); User user = service.findOne(id); return user; } /** * 多个请求处理 * @param ids id串,使用逗号分隔 */ @GetMapping("/users") public List findAll(@RequestParam List ids){ LOGGER.debug("=============/hystrix/usersids={} 执行了", ids); return service.findAll(ids); }

扩充RibbonService,添加两个方法,分别调用上述两个接口,主要是为了分层明确

/**请求合并使用到的测试方法**/ /** * 查一个User对象 */ public User findOne(Long id){ LOGGER.info("findOne方法执行了,id= "+id); return restTemplate.getForObject("{1}", User.class, id); } /** * 查多个对象 * * 注意: 这里用的是数组,作为结果的接收,因为restTemplate.getForObject方法在这里受限 * 如果尽如《SpringCloud微服务实战》一书中指定类型为List.class,会返回一个List类型的集合 * 为了避坑这里我们使用数组的方式接收结果 */ public List findAll(List ids){ LOGGER.info("findAll方法执行了,ids= "+ids); User[] users = restTemplate.getForObject("={1}", User[].class, StringUtils.join(ids, ",")); return Arrays.asList(users); }

我们还需要一个将请求合并的类,在hystrix包下创建UserCollapseCommand

package com.cnblogs.hellxz.hystrix;import com.cnblogs.hellxz.entity.User;import com.cnblogs.hellxz.servcie.RibbonService;import com.netflix.hystrix.HystrixCollapser;import com.netflix.hystrix.HystrixCollapserProperties;import com.netflix.hystrix.HystrixCommand;import java.util.ArrayList;import java.util.Collection;import java.util.List;import java.util.stream.Collectors;//注意这个asKey方法不是HystrixCommandKey.Factory.asKeyimport static com.netflix.hystrix.HystrixCollapserKey.Factory.asKey;/** * @Author : Hellxz * @Description: 继承HystrixCollapser的请求合并器 * @Date : 2018/5/5 11:42 */public class UserCollapseCommand extends HystrixCollapser

,User,Long> { private RibbonService service; private Long userId; /** * 构造方法,主要用来设置这个合并器的时间,意为每多少毫秒就会合并一次 * @param ribbonService 调用的服务 * @param userId 单个请求传入的参数 */ public UserCollapseCommand(RibbonService ribbonService, Long userId){ super(Setter.withCollapserKey(asKey("userCollapseCommand")).andCollapserPropertiesDefaults(HystrixCollapserProperties.Setter().withTimerDelayInMilliseconds(100))); this.service = ribbonService; this.userId = userId; } /** * 获取请求中的参数 */ @Override public Long getRequestArgument() { return userId; } /** * 创建命令,执行批量操作 */ @Override public HystrixCommand

> createCommand(Collection