Hystrix面试 - 深入 Hystrix 断路器执行原理

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

实例 Demo

HystrixCommand 配置参数

在 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;}@Overrideprotected 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);}@Overrideprotected ProductInfo getFallback() {ProductInfo productInfo = new ProductInfo();productInfo.setName("降级商品");return productInfo;}
}

断路测试类

我们在测试类中,前 30 次请求,传入 productId=-1,然后休眠 3s,之后 70 次请求,传入 productId=1。

@SpringBootTest
@RunWith(SpringRunner.class)
public class CircuitBreakerTest {@Testpublic 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 会尝试执行请求,发现成功了,那么断路器关闭,之后的所有请求也都能正常调用了。

Hystrix面试 - 深入 Hystrix 断路器执行原理相关推荐

  1. Hystrix面试 - 深入 Hystrix 执行时内部原理

    Hystrix面试 - 深入 Hystrix 执行时内部原理 前面我们了解了 Hystrix 最基本的支持高可用的技术:资源隔离 + 限流. 创建 command: 执行这个 command: 配置这 ...

  2. Hystrix断路器执行原理

    深入 Hystrix 断路器执行原理 Hystrix熔断机制,用于监控微服务调用情况,当失败的情况达到预定的阈值(5秒失败20次),会打开断路器,拒绝所有请求,直到服务恢复正常为止. circuitB ...

  3. Hystrix面试 - 深入 Hystrix 线程池隔离与接口限流

    Hystrix面试 - 深入 Hystrix 线程池隔离与接口限流 前面讲了 Hystrix 的 request cache 请求缓存.fallback 优雅降级.circuit breaker 断路 ...

  4. Hystrix面试 - 基于 Hystrix 信号量机制实现资源隔离

    Hystrix面试 - 基于 Hystrix 信号量机制实现资源隔离 Hystrix 里面核心的一项功能,其实就是所谓的资源隔离,要解决的最最核心的问题,就是将多个依赖服务的调用分别隔离到各自的资源池 ...

  5. Hystrix面试 - 基于 Hystrix 线程池技术实现资源隔离

    Hystrix面试 - 基于 Hystrix 线程池技术实现资源隔离 上一讲提到,如果从 Nginx 开始,缓存都失效了,Nginx 会直接通过缓存服务调用商品服务获取最新商品数据(我们基于电商项目做 ...

  6. Hystrix面试 - 用 Hystrix 构建高可用服务架构

    Hystrix面试 - 用 Hystrix 构建高可用服务架构 Hystrix 是什么? 在分布式系统中,每个服务都可能会调用很多其他服务,被调用的那些服务就是依赖服务,有的时候某些依赖服务出现故障也 ...

  7. Hystrix流程分析及断路器工作原理

    上一篇转载的文章主要讲了Hystrix的应用场景.基础组件概念以及从源码的角度阐述了基本应用.本篇文章主要借鉴官方文档介绍Hystrix的工作流程及断路器的原理,最后说一下与SpringCloud的简 ...

  8. 深入 Hystrix 断路器执行原理

    本系列内容转载自git项目advancejava RequestVolumeThreshold HystrixCommandProperties.Setter().withCircuitBreaker ...

  9. Hystrix(6) 深入 Hystrix 执行时内部原理

    深入 Hystrix 执行时内部原理 前面我们了解了 Hystrix 最基本的支持高可用的技术:资源隔离 + 限流. 创建 command: 执行这个 command: 配置这个 command 对应 ...

最新文章

  1. react-antd项目中重新npm  install  导致自动升级antd版本,引发的样式问题
  2. hihocoder #1055 : 刷油漆(树形dp)
  3. Python练习题14
  4. 安装telnet_Flask干货:Memcached缓存系统——Memcached的安装
  5. jQuery标题文字淡入淡出显示效果
  6. java工具类书写规范
  7. Java初学笔记30-【MiniQQ聊天部分代码】
  8. 直男福利!手把手教你做一只口红色号识别器,秒变李佳琦
  9. 【C++错误处理】no matching function for call to transform
  10. 无法同步因计算机未授权,iTunes无法授权和同步解决办法教程
  11. “泰迪杯”挑战赛 - 通过聚类方法对航空客运的客户进行细分
  12. MarkdownPad2自动生成侧边导航栏目录
  13. Js模拟重力场【Js动效】
  14. su组件在什么窗口_su家具组件 SU中的组件与群组有什么不同
  15. Git:schannel: next InitializeSecurityContext failed: SEC_E_UNTRUSTED_ROOT
  16. Java - 谷歌邮箱发送邮件详解
  17. 淘宝API 淘宝链接获取解析获取商品id
  18. 【8.23模拟赛T1.1296】城墙【贪心】
  19. 七大排序算法大汇总(上)
  20. 基于ubuntu使用ovs实现容器网络隔离

热门文章

  1. 深入理解JavaScript系列:闭包(Closures)
  2. PHP中的CURL函数库
  3. android 安装内核module,提示Required key not available
  4. numpy+pandas+matplotlib画箱形图
  5. 【AI视野·今日CV 计算机视觉论文速览 第190期】Fri, 9 Apr 2021
  6. 【今日CV 视觉论文速览】 13 Feb 2019
  7. Python列出文件夹下某类文件名的方法
  8. 将数据导出到文本文档 mysql
  9. python-字符串的切片操作
  10. Android的图片叠加