【熔断基础】

内部逻辑:
Hystrix使用命令模式(继承HystrixCommand类)来包裹具体的服务调用逻辑(run方法), 并在命令模式中添加了服务调用失败后的降级逻辑(getFallback).
同时我们在Command的构造方法中可以定义当前服务线程池和熔断器的相关参数.

下图为Hystrix服务调用的内部逻辑:
在这里插入图片描述

1.构建Hystrix的Command对象, 调用执行方法.
2.Hystrix检查当前服务的熔断器开关是否开启, 若开启, 则执行降级服务getFallback方法.
3.若熔断器开关关闭, 则Hystrix检查当前服务的线程池是否能接收新的请求, 若超过线程池已满, 则执行降级服务getFallback方法.
4.若线程池接受请求, 则Hystrix开始执行服务调用具体逻辑run方法.
5.若服务执行失败, 则执行降级服务getFallback方法, 并将执行结果上报Metrics更新服务健康状况.
6.若服务执行超时, 则执行降级服务getFallback方法, 并将执行结果上报Metrics更新服务健康状况.
7.若服务执行成功, 返回正常结果.
8.若服务降级方法getFallback执行成功, 则返回降级结果.
9.若服务降级方法getFallback执行失败, 则抛出异常.

在这里插入图片描述

服务的健康状况= 请求失败数 / 请求总数.
熔断器开关由关闭到打开的状态转换是通过当前服务健康状况和设定阈值比较决定的:
1.当熔断器开关关闭时, 请求被允许通过熔断器. 如果当前健康状况高于设定阈值, 开关继续保持关闭. 如果当前健康状况低于设定阈值, 开关则切换为打开状态.
2.当熔断器开关打开时, 请求被禁止通过.
3.当熔断器开关处于打开状态, 经过一段时间后, 熔断器会自动进入半开状态, 这时熔断器只允许一个请求通过. 当该请求调用成功时, 熔断器恢复到关闭状态. 若该请求失败, 熔断器继续保持打开状态, 接下来的请求被禁止通过.
熔断器的开关能保证服务调用者在调用异常服务时, 快速返回结果, 避免大量的同步等待. 并且熔断器能在一段时间后继续侦测请求执行结果, 提供恢复服务调用的可能.

部分参数设置方法与作用:
1.RequestVolumeThreshold
HystrixCommandProperties.Setter().withCircuitBreakerRequestVolumeThreshold(int n)
表示在滑动窗口中,至少有多少个请求,才可能触发断路。
Hystrix 经过断路器的流量超过了一定的阈值,才有可能触发断路。比如说,要求在 10s 内经过断路器的流量必须达到 20 个,而实际经过断路器的流量才 10 个,那么根本不会去判断要不要断路。
2.ErrorThresholdPercentage
HystrixCommandProperties.Setter().withCircuitBreakerErrorThresholdPercentage(int n)
表示异常比例达到多少,才会触发断路,默认值是50(%)。
如果断路器统计到的异常调用的占比超过了一定的阈值,比如说在10s 内,经过断路器的流量达到了 30 个,同时其中异常访问的数量也达到了一定的比例,比如 60% 的请求都是异常(报错 / 超时 / reject),就会开启断路。
3.SleepWindowInMilliseconds
HystrixCommandProperties.Setter().withCircuitBreakerSleepWindowInMilliseconds(int n)

断路开启,也就是由close 转换到 open 状态(close -> open)。那么之后在 SleepWindowInMilliseconds 时间内,所有经过该断路器的请求全部都会被断路,不调用后端服务,直接走 fallback 降级机制。
而在该参数时间过后,断路器会变为 half-open 半开闭状态,尝试让一条请求经过断路器,看能不能正常调用。如果调用成功了,那么就自动恢复,断路器转为 close 状态。
4.Enabled
HystrixCommandProperties.Setter().withCircuitBreakerEnabled(boolean)
控制是否允许断路器工作,包括跟踪依赖服务调用的健康状况,以及对异常情况过多时是否允许触发断路。默认值是 true。
5.ForceOpen
HystrixCommandProperties.Setter().withCircuitBreakerForceOpen(boolean)
如果设置为true 的话,直接强迫打开断路器,相当于是手动断路了,手动降级,默认值是 false。

使用步骤:
1、继承HystrixCommand 或者HystrixObservableCommand
要想使用hystrix,只需要继承HystrixCommand或HystrixObservableCommand,简单用法见上面例子。两者主要区别是:
前者的命令逻辑写在run();后者的命令逻辑写在construct()
前者的run()是由新创建的线程执行;后者的construct()是由调用程序线程执行。
2.调用命令执行方法:
命令执行方法有以下四种:
(1) execute():以同步堵塞方式执行run()。调用execute()后,hystrix先创建一个新线程运行run(),接着调用程序要在execute()调用处一直堵塞着,直到run()运行完成
(2)queue():以异步非堵塞方式执行run()。一调用queue()就直接返回一个Future对象,同时hystrix创建一个新线程运行run(),调用程序通过Future.get()拿到run()的返回结果,而Future.get()是堵塞执行的。
(3)observe():事件注册前执行run()/construct()。
第一步是事件注册前,先调用observe()自动触发执行run()/construct()(如果继承的是HystrixCommand,hystrix将创建新线程非堵塞执行run();如果继承的是HystrixObservableCommand,将以调用程序线程堵塞执行construct()),
第二步是从observe()返回后调用程序调用subscribe()完成事件注册,如果run()/construct()执行成功则触发onNext()和onCompleted(),如果执行异常则触发onError()
(4)toObservable():事件注册后执行run()/construct()。
第一步是事件注册前,一调用toObservable()就直接返回一个Observable对象。
第二步调用subscribe()完成事件注册后自动触发执行run()/construct()(如果继承的是HystrixCommand,hystrix将创建新线程非堵塞执行run(),调用程序不必等待run();如果继承的是HystrixObservableCommand,将以调用程序线程堵塞执行construct(),调用程序等待construct()执行完才能继续往下走),如果run()/construct()执行成功则触发onNext()和onCompleted(),如果执行异常则触发onError()。

方法 同步/异步 返回值
execute 同步 T
queue 异步 Future
observe 异步 Observable
toObservable 未执行 Observable

3、重写熔断降级方法
使用fallback机制很简单,继承HystrixCommand只需重写getFallback(),继承HystrixObservableCommand只需重写resumeWithFallback(),比如继承HystrixCommand:
@Override
protected String getFallback() {
return "fallback: " + name;
}
fallback实际流程是当run()/construct()被触发执行时或执行中发生错误时,将转向执行getFallback()/resumeWithFallback()。以下4种错误情况将触发fallback:
(1)非HystrixBadRequestException异常:当抛出HystrixBadRequestException时,调用程序可以捕获异常,没有触发getFallback(),而其他异常则会触发getFallback(),调用程序将获得getFallback()的返回
(2)run()/construct()运行超时:使用无限while循环或sleep模拟超时,触发getFallback()
(3)熔断器启动:比如配置10s内请求数大于3个时就启动熔断器,请求错误率大于50%时就熔断,然后通过for循环发起请求,当请求符合熔断条件时将触发getFallback(),后续请求会直接走getFallback()方法,不会再执行run()方法。
(4)线程池/信号量已满:比如配置线程池数目为3,然后先用一个for循环执行queue(),触发的run()sleep 2s,然后再用第2个for循环执行execute(),发现所有execute()都触发了fallback,这是因为第1个for的线程还在sleep,占用着线程池所有线程,导致第2个for的所有命令都无法获取到线程

4、隔离策略
hystrix提供了两种隔离策略:线程池隔离和信号量隔离。hystrix默认采用线程池隔离。
线程池隔离:不同服务通过使用不同线程池,彼此间将不受影响,达到隔离效果。通过andThreadPoolKey配置使用命名线程池,实现与其他命名的线程池天然隔离,如果不配置andThreadPoolKey则使用withGroupKey配置来命名线程池
信号量隔离:线程隔离会带来线程开销,有些场景(比如无网络请求场景)可能会因为用开销换隔离得不偿失,为此hystrix提供了信号量隔离,当服务的并发数大于信号量阈值时将进入fallback。通过withExecutionIsolationStrategy(ExecutionIsolationStrategy.SEMAPHORE)配置为信号量隔离,通过withExecutionIsolationSemaphoreMaxConcurrentRequests配置执行并发数不能大于3,由于信号量隔离下无论调用哪种命令执行方法,hystrix都不会创建新线程执行run()/construct(),所以调用程序需要自己创建多个线程来模拟并发调用execute(),最后看到一旦并发线程>3,后续请求都进入fallback
5、熔断机制
熔断机制相当于电路的跳闸功能,举个栗子,我们可以配置熔断策略为当请求错误比例在10s内>50%时,该服务将进入熔断状态,后续请求都会进入fallback。
比如:通过withCircuitBreakerRequestVolumeThreshold配置10s内请求数超过3个时熔断器开始生效,通过withCircuitBreakerErrorThresholdPercentage配置错误比例>80%时开始熔断,超时请求占所有请求的比例大于80%之后,就会看到后续请求都不进入run()而是进入getFallback()。

四种触发fallback情况:
(1)非HystrixBadRequestException异常:
当抛出HystrixBadRequestException时,调用程序可以捕获异常,此时不会触发fallback,而其他异常则会触发fallback,调用程序将获得fallback逻辑的返回结果。
(2)run()/construct()运行超时:
执行命令的方法超时,将会触发fallback。
(3)熔断器开启:
当熔断器处于开启的状态,将会触发fallback。
(4)线程池/信号量已满:
当线程池/信号量已满的状态,将会触发fallback。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值