目录
1. 请求合并HystrixCollapserService
一、介绍
Hysrix利用一个合并处理器,将对同一个服务发起的连续请求合并成一个请求批量处理,即:多个单个请求转换为单个批量请求,实际是批量请求模式。
核心类com.netflix.hystrix.HystrixCollapser,默认连续10ms(timerDelayInMilliseconds
)多次请求转一个单批量请求,超出该时间则批次请求。配置合并范围scope。使用时必须HystrixRequestContext开启上下文,即:使用ThreadLocal初始化一个上下文对象。
二、代码示例
1. 请求合并HystrixCollapserService
package com.common.instance.test.service.requestMerge;
import com.common.instance.test.entity.WcPendantTab;
import com.common.instance.test.service.WcPendantTabService;
import com.netflix.hystrix.HystrixCollapser;
import com.netflix.hystrix.HystrixCollapserKey;
import com.netflix.hystrix.HystrixCollapserProperties;
import com.netflix.hystrix.HystrixCommand;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @description Hystrix合并请求处理
* @author tcm
* @version 1.0.0
* @date 2021/12/8 9:45
**/
public class HystrixCollapserService extends HystrixCollapser<List<WcPendantTab>, WcPendantTab, String> {
// 业务处理
private WcPendantTabService wcPendantTabService;
// 查询参数
private String mgdbId;
public HystrixCollapserService(WcPendantTabService wcPendantTabService, String mgdbId){
super(setter());
this.wcPendantTabService = wcPendantTabService;
this.mgdbId = mgdbId;
}
// 请求合并设置
private static HystrixCollapser.Setter setter(){
return HystrixCollapser.Setter
// 全局唯一标识合并名称,名称相同的请求进行合并
.withCollapserKey(HystrixCollapserKey.Factory.asKey("price"))
// 配置合并参数
.andCollapserPropertiesDefaults(HystrixCollapserProperties.Setter()
// 每个请求的最大请求数,超出时分批次请求
.withMaxRequestsInBatch(2)
// 批处理等待超时时间,默认10ms
.withTimerDelayInMilliseconds(5)
// 多请求请求合并,避免重复请求,默认true
.withRequestCacheEnabled(true))
// 请求合并范围,REQUEST:当前上下文;GLOBAL,跨多个请求上下文
.andScope(Scope.REQUEST);
}
// 获取请求参数
@Override
public String getRequestArgument() {
return mgdbId;
}
// 创建可批量执行的HystrixCommand
@Override
protected HystrixCommand<List<WcPendantTab>> createCommand(Collection<CollapsedRequest<WcPendantTab, String>> collapsedRequests) {
return new BatchCommandService(wcPendantTabService, collapsedRequests);
}
// 执行结果映射到请求
@Override
protected void mapResponseToRequests(List<WcPendantTab> batchResponse, Collection<CollapsedRequest<WcPendantTab, String>> collapsedRequests) {
final AtomicInteger count = new AtomicInteger();
collapsedRequests.forEach((collapsedRequest -> {
if (!batchResponse.isEmpty()){
collapsedRequest.setResponse(batchResponse.get(count.getAndIncrement()));
} else {
collapsedRequest.setResponse(null);
}
}));
}
}
2. 批量请求BatchCommandService
package com.common.instance.test.service.requestMerge;
import com.common.instance.test.entity.WcPendantTab;
import com.common.instance.test.service.WcPendantTabService;
import com.google.common.collect.Lists;
import com.netflix.hystrix.HystrixCollapser;
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
/**
* @description Hystrix批处理请求
* @author tcm
* @version 1.0.0
* @date 2021/12/8 10:28
**/
public class BatchCommandService extends HystrixCommand<List<WcPendantTab>> {
private WcPendantTabService wcPendantTabService;
private Collection<HystrixCollapser.CollapsedRequest<WcPendantTab, String>> requests;
public BatchCommandService(WcPendantTabService wcPendantTabService, Collection<HystrixCollapser.CollapsedRequest<WcPendantTab, String>> requests){
super(setter());
this.wcPendantTabService = wcPendantTabService;
this.requests = requests;
}
public static Setter setter(){
return Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("price"));
}
@Override
protected List<WcPendantTab> run() throws Exception {
// 获取所有请求的查询参数
List<String> mgdbIds = requests.stream().map(request -> {
return request.getArgument();
}).collect(Collectors.toList());
// 批量查询
return wcPendantTabService.batchQueryByMgdbId(mgdbIds);
}
@Override
protected List<WcPendantTab> getFallback() {
return Lists.newArrayList();
}
}
3. 调用
package com.common.instance.test.controller;
import com.common.instance.test.core.Response;
import com.common.instance.test.entity.WcPendantTab;
import com.common.instance.test.service.WcPendantTabService;
import com.common.instance.test.service.requestMerge.HystrixCollapserService;
import com.google.common.collect.Lists;
import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.Future;
/**
* Tab菜单(WcPendantTab)表控制层
*
* @author tcm
* @since 2021-01-14 15:02:08
*/
@Slf4j
@RestController
@RequestMapping("/tab")
@Api(tags = "活动tab测试")
public class WcPendantTabController {
@Resource
private WcPendantTabService wcPendantTabService;
@GetMapping("/testRequestMerge")
@ApiOperation("测试请求合并")
public Response<List<WcPendantTab>> testRequestMerge(String mgdbId1, String mgdbId2, String mgdbId3){
// 返回结果
List<WcPendantTab> result = Lists.newArrayList();
// 开启上下文对象,即:使用ThreadLocal初始化一个上下文对象
HystrixRequestContext context = HystrixRequestContext.initializeContext();
try {
// 业务查询
HystrixCollapserService hystrixCollapserService1 = new HystrixCollapserService(wcPendantTabService, mgdbId1);
HystrixCollapserService hystrixCollapserService2 = new HystrixCollapserService(wcPendantTabService, mgdbId2);
HystrixCollapserService hystrixCollapserService3 = new HystrixCollapserService(wcPendantTabService, mgdbId3);
// 异步非阻塞
Future<WcPendantTab> future1 = hystrixCollapserService1.queue();
Future<WcPendantTab> future2 = hystrixCollapserService2.queue();
Future<WcPendantTab> future3 = hystrixCollapserService3.queue();
// 获取合并结果
result.add(future1.get());
result.add(future2.get());
result.add(future3.get());
} catch (Exception e) {
e.printStackTrace();
return Response.error();
} finally {
// 关闭上下文
context.close();
}
return Response.success(result);
}
}
三、参考资料
https://segmentfault.com/a/1190000012256788