深入 Hystrix 断路器执行原理
2019-05-28 11:11
148 查看
版权声明:~转载请标注,谢谢~如果侵权了请私信我,我会立刻删除~ https://blog.csdn.net/baidu_26954625/article/details/90635574
而在该参数时间过后,断路器会变为 half-open 半开闭状态,尝试让一条请求经过断路器,看能不能正常调用。如果调用成功了,那么就自动恢复,断路器转为 close 状态。
• 滑动窗口中,最少 20 个请求,才可能触发断路。
• 异常比例达到 40% 时,才触发断路。
• 断路后 3000ms 内,所有请求都被 reject,直接走 fallback 降级,不会调用 run() 方法。3000ms 过后,变为 half-open 状态。
run() 方法中,我们判断一下
在降级逻辑中,我们直接给它返回降级商品就好了。
之后的 9 次请求,都不会执行 run() 方法,也就不会打印以下信息。
调用接口查询商品数据,
而是直接走降级逻辑,调用
休眠了 3s 后,我们在之后的 70 次请求中,都传入
本系列内容转载自git项目advancejava
RequestVolumeThreshold
HystrixCommandProperties.Setter().withCircuitBreakerRequestVolumeThreshold(int)
表示在滑动窗口中,至少有多少个请求,才可能触发断路。
Hystrix 经过断路器的流量超过了一定的阈值,才有可能触发断路。比如说,要求在 10s 内经过断路器的流量必须达到 20 个,而实际经过断路器的流量才 10 个,那么根本不会去判断要不要断路。
ErrorThresholdPercentage
HystrixCommandProperties.Setter().withCircuitBreakerErrorThresholdPercentage(int)
表示异常比例达到多少,才会触发断路,默认值是 50(%)。
如果断路器统计到的异常调用的占比超过了一定的阈值,比如说在 10s 内,经过断路器的流量达到了 30 个,同时其中异常访问的数量也达到了一定的比例,比如 60% 的请求都是异常(报错 / 超时 / reject),就会开启断路。
SleepWindowInMilliseconds
HystrixCommandProperties.Setter().withCircuitBreakerSleepWindowInMilliseconds(int)
断路开启,也就是由 close 转换到 open 状态(close -> open)。那么之后在
SleepWindowInMilliseconds时间内,所有经过该断路器的请求全部都会被断路,不调用后端服务,直接走 fallback 降级机制。
而在该参数时间过后,断路器会变为 half-open 半开闭状态,尝试让一条请求经过断路器,看能不能正常调用。如果调用成功了,那么就自动恢复,断路器转为 close 状态。
Enabled
HystrixCommandProperties.Setter().withCircuitBreakerEnabled(boolean)
控制是否允许断路器工作,包括跟踪依赖服务调用的健康状况,以及对异常情况过多时是否允许触发断路。默认值是 true。
ForceOpen
HystrixCommandProperties.Setter().withCircuitBreakerForceOpen(boolean)
如果设置为 true 的话,直接强迫打开断路器,相当于是手动断路了,手动降级,默认值是 false。
ForceClosed
HystrixCommandProperties.Setter().withCircuitBreakerForceClosed(boolean)
如果设置为 true,直接强迫关闭断路器,相当于手动停止断路了,手动升级,默认值是 false。
在
GetProductInfoCommand中配置 Setter 断路器相关参数。
• 滑动窗口中,最少 20 个请求,才可能触发断路。
• 异常比例达到 40% 时,才触发断路。
• 断路后 3000ms 内,所有请求都被 reject,直接走 fallback 降级,不会调用 run() 方法。3000ms 过后,变为 half-open 状态。
run() 方法中,我们判断一下
productId是否为 -1,是的话,直接抛出异常。这么写,我们之后测试的时候就可以传入
productId=-1,模拟服务执行异常了。
在降级逻辑中,我们直接给它返回降级商品就好了。
public class GetProductInfoCommand extends HystrixCommand<ProductInfo> { private Long productId; private static final HystrixCommandKey KEY = HystrixCommandKey.Factory.asKey("GetProductInfoCommand"); public GetProductInfoCommand(Long productId) { super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ProductInfoService")) .andCommandKey(KEY) .andCommandPropertiesDefaults(HystrixCommandProperties.Setter() // 是否允许断路器工作 .withCircuitBreakerEnabled(true) // 滑动窗口中,最少有多少个请求,才可能触发断路 .withCircuitBreakerRequestVolumeThreshold(20) // 异常比例达到多少,才触发断路,默认50% .withCircuitBreakerErrorThresholdPercentage(40) // 断路后多少时间内直接reject请求,之后进入half-open状态,默认5000ms .withCircuitBreakerSleepWindowInMilliseconds(3000))); this.productId = productId; } @Override protected ProductInfo run() throws Exception { System.out.println("调用接口查询商品数据,productId=" + productId); if (productId == -1L) { throw new Exception(); } String url = "http://localhost:8081/getProductInfo?productId=" + productId; String response = HttpClientUtils.sendGetRequest(url); return JSONObject.parseObject(response, ProductInfo.class); } @Override protected ProductInfo getFallback() { ProductInfo productInfo = new ProductInfo(); productInfo.setName("降级商品"); return productInfo; } }
断路测试类
我们在测试类中,前 30 次请求,传入
productId=-1,然后休眠 3s,之后 70 次请求,传入
productId=1。
@SpringBootTest @RunWith(SpringRunner.class) public class CircuitBreakerTest { @Test public void testCircuitBreaker() { String baseURL = "http://localhost:8080/getProductInfo?productId="; for (int i = 0; i < 30; ++i) { // 传入-1,会抛出异常,然后走降级逻辑 HttpClientUtils.sendGetRequest(baseURL + "-1"); } TimeUtils.sleep(3); System.out.println("After sleeping..."); for (int i = 31; i < 100; ++i) { // 传入1,走服务正常调用 HttpClientUtils.sendGetRequest(baseURL + "1"); } } }
测试结果
测试结果,我们可以明显看出系统断路与恢复的整个过程。
调用接口查询商品数据,
productId=-1
ProductInfo(id=null, name=降级商品, price=null, pictureList=null, specification=null, service=null, color=null, size=null, shopId=null, modifiedTime=null, cityId=null, cityName=null, brandId=null, brandName=null) // ... // 这里重复打印了 20 次上面的结果 ProductInfo(id=null, name=降级商品, price=null, pictureList=null, specification=null, service=null, color=null, size=null, shopId=null, modifiedTime=null, cityId=null, cityName=null, brandId=null, brandName=null) // ... // 这里重复打印了 8 次上面的结果 // 休眠 3s 后 调用接口查询商品数据,productId=1 ProductInfo(id=1, name=iphone7手机, price=5599.0, pictureList=a.jpg,b.jpg, specification=iphone7的规格, service=iphone7的售后服务, color=红色,白色,黑色, size=5.5, shopId=1, modifiedTime=2017-01-01 12:00:00, cityId=1, cityName=null, brandId=1, brandName=null) // ... // 这里重复打印了 69 次上面的结果
前 30 次请求,我们传入的
productId为 -1,所以服务执行过程中会抛出异常。我们设置了最少 20 次请求通过断路器并且异常比例超出 40% 就触发断路。因此执行了 21 次接口调用,每次都抛异常并且走降级,21 次过后,断路器就被打开了。
之后的 9 次请求,都不会执行 run() 方法,也就不会打印以下信息。
调用接口查询商品数据,
productId=-1
而是直接走降级逻辑,调用
getFallback()执行。
休眠了 3s 后,我们在之后的 70 次请求中,都传入
productId为 1。由于我们前面设置了 3000ms 过后断路器变为 half-open 状态。因此 Hystrix 会尝试执行请求,发现成功了,那么断路器关闭,之后的所有请求也都能正常调用了。
相关文章推荐
- 深入理解PHP原理之PHP脚本执行原理(1)
- 深入理解JavaScript内部原理(1): 执行上下文
- 断路器hystrix原理及使用
- 深入分析HBase-Phoenix执行机制与原理
- 深入理解PHP原理之执行周期分析
- 深入理解PHP原理之PHP脚本执行原理(2)
- 深入理解Spark 2.1 Core (七):Standalone模式任务执行的原理与源码分析
- 深入理解PHP原理之执行周期分析
- 【夯实Spring Cloud】Spring Cloud中使用Hystrix实现断路器原理详解(下)
- 深入理解Spark 2.1 Core (七):任务执行的原理与源码分析
- 深入理解JavaScript内部原理(1): 执行上下文
- 【夯实Spring Cloud】Spring Cloud中使用Hystrix实现断路器原理详解(上)
- 《spring cloud微服务实战》读书笔记——Spring Cloud Hystrix(三)断路器的原理
- 断路器-Hystrix的深入了解
- 深入解析SQL Server并行执行原理及实践
- 深入剖析php执行原理(2):函数的编译
- 深入解析SQL Server并行执行原理及实践(上) ---高继伟
- 深入理解JavaScript内部原理(1): 执行上下文
- 分布式熔断、限流与服务保护:深入 Hystrix 原理及使用
- [Binospace] 深入分析HBase-Phoenix执行机制与原理