Spring Cloud Hystrix 学习(三)请求合并
什么是请求合并?我们先来看两张图:
上方的两张图中,第二张可以看出服务端只执行了一次响应,这就是请求合并。客户端新增的请求合并模块,内部存在一个等待的时间窗口,将一定时间段内满足条件的请求进行合并,以此降低服务端的请求响应压力。
可以看出,请求合并是在客户端中实现的,接下来我们通过代码来实践一下。
首先给出服务端的代码,这里打印了入参ids,后续我们将通过这个入参打印的情况来对请求合并的情况进行观察。
@RequestMapping(value = "/mergeTest", method = RequestMethod.GET)
public List<Test> mergeTest(String ids) { System.out.println("ids:{" + ids + "}");
String[] strs = ids.split(","); List<Test> lstResult = new ArrayList<Test>();
for (int i = 0; i < strs.length; i++) {
lstResult.add(new Test(i, Integer.parseInt(strs[i])));
}
return lstResult;
}
这里补充说明一点,对于测试用的Test类必须存在空构造函数,否则在客户端收到应答后反序列化时可能会抛出如下异常:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `hystrix.dto.Test` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
at [Source: (PushbackInputStream); line: 1, column: 3] (through reference chain: java.lang.Object[][0])
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67) ~[jackson-databind-2.9.10.6.jar:2.9.10.6]
at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1452) ~[jackson-databind-2.9.10.6.jar:2.9.10.6]
at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1028) ~[jackson-databind-2.9.10.6.jar:2.9.10.6]
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1297) ~[jackson-databind-2.9.10.6.jar:2.9.10.6]
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:326) ~[jackson-databind-2.9.10.6.jar:2.9.10.6]
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159) ~[jackson-databind-2.9.10.6.jar:2.9.10.6]
at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:195) ~[jackson-databind-2.9.10.6.jar:2.9.10.6]
at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:21) ~[jackson-databind-2.9.10.6.jar:2.9.10.6]
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4014) ~[jackson-databind-2.9.10.6.jar:2.9.10.6]
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3085) ~[jackson-databind-2.9.10.6.jar:2.9.10.6]
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:271) ~[spring-web-5.1.19.RELEASE.jar:5.1.19.RELEASE]
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:240) ~[spring-web-5.1.19.RELEASE.jar:5.1.19.RELEASE]
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:102) ~[spring-web-5.1.19.RELEASE.jar:5.1.19.RELEASE]
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:733) ~[spring-web-5.1.19.RELEASE.jar:5.1.19.RELEASE]
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:666) ~[spring-web-5.1.19.RELEASE.jar:5.1.19.RELEASE]
at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:307) ~[spring-web-5.1.19.RELEASE.jar:5.1.19.RELEASE]
at hystrix.service.TestService.mergeTest(TestService.java:53) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_181]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_181]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_181]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_181]
接下来再看下客户端请求合并逻辑的实现,这里我们采用注解的方式来完成:
@Service
public class TestService { @Autowired
private RestTemplate restTemplate; @Autowired
private DiscoveryClient discoveryClient; @HystrixCollapser(batchMethod = "mergeTest", collapserProperties = {
@HystrixProperty(name = "timerDelayInMilliseconds", value = "3000")
})
public Future<Test> singleTest(Integer id) {
return null;
} @HystrixCommand
public List<Test> mergeTest(List<Integer> ids) { ServiceInstance instance = discoveryClient.getInstances("spring-cloud-service-provider").get(0);
String url = "http://" + instance.getHost() + ":" + instance.getPort() + "/mergeTest";
Test[] tests = restTemplate.getForObject(url + "?ids={1}", Test[].class, StringUtils.join(ids, ","));
return Arrays.asList(tests);
}
}
singleTest通过@HystrixCollapser注解实现请求合并,并指定了合并后调用的方法为mergeTest(),同时设置了时间窗口的大小为3000毫秒。
最后就是测试代码:
@GetMapping("/hystrix/test")
public String helloHystrix() throws ExecutionException, InterruptedException { HystrixRequestContext context = HystrixRequestContext.initializeContext();
Future<Test> f1 = service.singleTest(101);
Future<Test> f2 = service.singleTest(102);
Future<Test> f3 = service.singleTest(103);
Test t1 = f1.get();
Test t2 = f2.get();
Test t3 = f3.get();
Thread.sleep(3000);
Future<Test> f4 = service.singleTest(104);
Test t4 = f4.get();
context.close(); return t1.getIndex() + ", " + t2.getIndex() + ", " + t3.getIndex() + ", " + t4.getIndex();
}
通过postman进行请求后,服务端打印信息如下:
可以看到前三条请求合并为一条汇总请求调用到服务端,由于第四条请求是在sleep(3000)之后进行发起,并未和前三条请求进入同一个时间窗口,因此单独调用到了服务端。
参考资料:
https://segmentfault.com/a/1190000011468804
https://www.cnblogs.com/yb-ken/p/15068392.html
Spring Cloud Hystrix 学习(三)请求合并的更多相关文章
- spring cloud: Hystrix(三):健康指数 health Indicator
spring cloud: Hystrix(三):健康指数 health Indicator ribbon+hystrix 当使用Hystrix时(spring-cloud-starter-hystr ...
- Spring Cloud Hystrix 学习(一)
在学习Hystrix之前,首先引入一个问题场景,服务雪崩.如下图所示: 可以看到,三个入口服务A.B.C最终都会请求到服务T.当服务T的请求过载,打满CPU都无法匹配请求的频率时,同步调用的上级服务就 ...
- spring cloud深入学习(三)-----服务消费
在上一篇博文中简单实现了eureka-server以及eureka-provider,后面会实现eureka-cosumer,现在针对eureka做进一步的详解. 微服务整体架构 文字再美也没有图片直 ...
- Spring Cloud Hystrix 学习(二)熔断与降级
今天来看下Hystrix的熔断与降级. 首先什么是降级?当请求超时.资源不足等情况发生时进行服务降级处理,不调用真实服务逻辑,而是使用快速失败(fallback)方式直接返回一个托底数据,保证服务链条 ...
- spring cloud深入学习(四)-----eureka源码解析、ribbon解析、声明式调用feign
基本概念 1.Registe 一一服务注册当eureka Client向Eureka Server注册时,Eureka Client提供自身的元数据,比如IP地址.端口.运行状况指标的Uri.主页地址 ...
- 笔记:Spring Cloud Hystrix 异常处理、缓存和请求合并
异常处理 在 HystrixCommand 实现的run方法中抛出异常,除了 HystrixBadRequestException之外,其他异常均会被Hystrix 认为命令执行失败并触发服务降级处理 ...
- 《Spring Cloud》学习(三) 容错保护!
在微服务架构中,我们将系统拆分成了很多服务单元,各单元的应用间互相依赖.由于每个单元都在不同的进程中运行,依赖通过远程调用的方式执行,这样就有可能因为网络原因或是依赖服务自身间题出现调用故障或延迟,而 ...
- Spring Cloud学习 之 Spring Cloud Hystrix(基础知识铺垫)
Spring Boot版本:2.1.4.RELEASE Spring Cloud版本:Greenwich.SR1 文章目录 前述: 快速入门: 命令模式: RxJava: 前述: 在微服务架构中, ...
- 第五章 服务容错保护:Spring Cloud Hystrix
在微服务架构中,我们将系统拆分为很多个服务,各个服务之间通过注册与订阅的方式相互依赖,由于各个服务都是在各自的进程中运行,就有可能由于网络原因或者服务自身的问题导致调用故障或延迟,随着服务的积压,可能 ...
随机推荐
- NOIP 模拟 $34\; \rm Equation$
题解 \(by\;zj\varphi\) 发现每个点的权值都可以表示成 \(\rm k\pm x\). 那么对于新增的方程,\(\rm x_u+x_v=k\pm x/0\) 且 \(\rm x_u+x ...
- Javaweb学习——request&response
request对象的作用 request是服务器对浏览器访问请求的封装 访问请求参数,通过getParameter()方法获取传递参数的值. 在进行转发请求时,需要把一些参数传递到转发后的页面进行处理 ...
- 6、二进制安装K8s之部署kubectl
二进制安装K8s之部署kubectl 我们把k8s-master 也设置成node,所以先master上面部署node,在其他机器上部署node也适用,更换名称即可. 1.在所有worker node ...
- 【springcloud】客户端负载均衡(Ribbon)
转自:https://blog.csdn.net/pengjunlee/article/details/86594934 服务器端负载均衡负载均衡是我们处理高并发.缓解网络压力和进行服务器扩容的重要手 ...
- CentOS7部署SSH服务
1 ssh服务部署 输入命令 yum list | grep ssh 查看可安装的软件包,选择openssh-service.x86_64 输入下面命令进行安装openssh服务 yum instal ...
- SpEL表达式注入漏洞学习和回显poc研究
目录 前言 环境 基础学习和回显实验 语法基础 回显实验 BufferedReader Scanner SpEL漏洞复现 低版本SpringBoot中IllegalStateException CVE ...
- 用vue的抽象组件来做一个防止img标签url为空或url地址出错的验证
看了网上文章学习了下vue的抽象组件,感觉就跟react的高阶组件一样的使用场景,只是更加面向vue的底层编程 ,网上介绍的抽象组件一般有2种用法,1 用来加防抖和节流 2 用来控制按钮是否允许点击做 ...
- Vue.JS快速上手(Vue-router 实现SPA 开发)
一.什么是路由 URL -> 映射 -> 组件 Hash+onhashchange History.pushstate+replaceState+onpopstate 二.准备工作 组件 ...
- 新东方APP技术团队建设
作者:张建鑫, 曾任IBM高级软件架构师, 滴滴高级技术专家, 现任新东方集团高级技术总监 2019年注定是不平凡的一年,在俞敏洪老师对科技条线的密切关注下, 吴强老师亲自操盘了对产品技术条线的改革, ...
- Windows-MacOSX-Ubuntu·不同平台文件互传文件共享
时间:2018-11-23 整理:byzqy 标题:Mac下的virtual box 安装的Ubuntu虚拟机互传文件问题 地址:https://blog.csdn.net/qq_20044689/a ...