摘要: 原创出处 http://www.iocoder.cn/Hystrix/command-execute-fourth-fallback/ 「芋道源码」欢迎转载,保留摘要,谢谢!
本文主要基于 Hystrix 1.5.X 版本
- 1. 概述
- 2. handleFallback
- 3. #handleShortCircuitViaFallback()
- 4. #handleSemaphoreRejectionViaFallback()
- 5. #handleThreadPoolRejectionViaFallback()
- 6. #handleTimeoutViaFallback()
- 7. #handleFailureViaFallback()
- 8. #getFallbackOrThrowException(…)
- 666. 彩蛋
1. 概述
本文主要分享 Hystrix 命令执行(四)之失败回退逻辑。
建议 :对 RxJava 已经有一定的了解的基础上阅读本文。
Hystrix 执行命令整体流程如下图:
- 红圈 :Hystrix 命令执行失败,执行回退逻辑。也就是大家经常在文章中看到的“服务降级”。
- 绿圈 :四种情况会触发失败回退逻辑( fallback )。
- 第一种 :
short-circuit
,处理链路处于熔断的回退逻辑,在 「3. #handleShortCircuitViaFallback()」 详细解析。 - 第二种 :
semaphore-rejection
,处理信号量获得失败的回退逻辑,在 「4. #handleShortCircuitViaFallback()」 详细解析。 - 第三种 :
thread-pool-rejection
,处理线程池提交任务拒绝的回退逻辑,在 「5. #handleThreadPoolRejectionViaFallback()」 详细解析。 - 第四种 :
execution-timeout
,处理命令执行超时的回退逻辑,在 「6. #handleTimeoutViaFallback()」 详细解析。 - 第五种 :
execution-failure
,处理命令执行异常的回退逻辑,在 「7. #handleFailureViaFallback()」 详细解析。 - 第六种 :
bad-request
,TODO 【2014】【HystrixBadRequestException】,和hystrix-javanica
子项目相关。
- 第一种 :
另外,#handleXXXX()
方法,整体代码比较类似,最终都是调用 #getFallbackOrThrowException()
方法,获得【回退逻辑 Observable】或者【异常 Observable】,在 「8. #getFallbackOrThrowException(…)」 详细解析。
推荐 Spring Cloud 书籍:
- 请支持正版。下载盗版,等于主动编写低级 BUG 。
- 程序猿DD —— 《Spring Cloud微服务实战》
- 周立 —— 《Spring Cloud与Docker微服务架构实战》
- 两书齐买,京东包邮。
2. handleFallback
在 《Hystrix 源码解析 —— 命令执行(一)之正常执行逻辑》「4. #executeCommandAndObserve(…)」 中,#executeCommandAndObserve(...)
的第 82 行 onErrorResumeNext(handleFallback)
代码,通过调用 Observable#onErrorResumeNext(...)
方法,实现【执行命令 Observable】执行异常时,返回【回退逻辑 Observable】,执行失败回退逻辑。
FROM 《ReactiveX文档中文翻译》「onErrorResumeNext」
onErrorResumeNext 方法返回一个镜像原有 Observable 行为的新 Observable ,后者会忽略前者的 onError 调用,不会将错误传递给观察者,作为替代,它会开始镜像另一个,备用的 Observable 。
- Javadoc: onErrorResumeNext(Func1))
- Javadoc: onErrorResumeNext(Observable))
handleFallback
变量,代码如下 :
|
- 第 5 行 :标记断路器尝试成功。在 《Hystrix 源码解析 —— 断路器 HystrixCircuitBreaker》 有详细解析。
- 第 7 至 8 行 :标记
executionResult
执行异常。 - 第 10 至 11 行 :
thread-pool-rejection
,处理线程池提交任务拒绝的回退逻辑,在 「5. #handleThreadPoolRejectionViaFallback()」 详细解析。 - 第 12 至 13 行 :
execution-timeout
,处理命令执行超时的回退逻辑,在 「6. #handleTimeoutViaFallback()」 详细解析。 - 第 14 至 23 行 :,
bad-request
,TODO 【2014】【HystrixBadRequestException】,和hystrix-javanica
子项目相关。 - 第 25 行 :
execution-failure
处理命令执行异常的回退逻辑,在 「7. #handleFailureViaFallback()」 详细解析。
3. #handleShortCircuitViaFallback()
#handleShortCircuitViaFallback()
方法,short-circuit
,处理链路处于熔断的回退逻辑,在 此处 被调用,代码如下 :
|
- 第 4 行 :TODO 【2011】【Hystrix 事件机制】
- 第 7 至 8 行 :标记
executionResult
执行异常。 - 第 11 至 12 行 :调用
#getFallbackOrThrowException()
方法,获得【回退逻辑 Observable】或者【异常 Observable】,在 「8. #getFallbackOrThrowException(…)」 详细解析。 - 第 14 行 :返回【异常 Observable】。
4. #handleSemaphoreRejectionViaFallback()
#handleSemaphoreRejectionViaFallback()
方法,semaphore-rejection
,处理信号量获得失败的回退逻辑,在 此处 被调用,代码如下 :
|
- 第 3 至 4 行 :标记
executionResult
执行异常。 - 第 6 至 7 行 :TODO 【2011】【Hystrix 事件机制】
- 第 10 至 11 行 :调用
#getFallbackOrThrowException()
方法,获得【回退逻辑 Observable】或者【异常 Observable】,在 「8. #getFallbackOrThrowException(…)」 详细解析。
5. #handleThreadPoolRejectionViaFallback()
#handleThreadPoolRejectionViaFallback()
方法,thread-pool-rejection
,处理线程池提交任务拒绝的回退逻辑,在 此处 被调用,代码如下:
|
- 第 3 行 :TODO 【2011】【Hystrix 事件机制】
- 第 5 行 :TODO 【2002】【metrics】
- 第 8 至 9 行 :调用
#getFallbackOrThrowException()
方法,获得【回退逻辑 Observable】或者【异常 Observable】,在 「8. #getFallbackOrThrowException(…)」 详细解析。
6. #handleTimeoutViaFallback()
#handleTimeoutViaFallback()
方法,execution-timeout
,处理命令执行超时的回退逻辑,在 此处 被调用,代码如下:
|
- 第 3 至 4 行 :调用
#getFallbackOrThrowException()
方法,获得【回退逻辑 Observable】或者【异常 Observable】,在 「8. #getFallbackOrThrowException(…)」 详细解析。
7. #handleFailureViaFallback()
#handleFailureViaFallback()
方法,execution-failure
,处理命令执行异常的回退逻辑,在 此处 被调用,代码如下:
|
- 第 2 至 9 行 :TODO 【2011】【Hystrix 事件机制】
- 第 13 行 :标记
executionResult
异常。 - 第 15 行 :调用
#getFallbackOrThrowException()
方法,获得【回退逻辑 Observable】或者【异常 Observable】,在 「8. #getFallbackOrThrowException(…)」 详细解析。
8. #getFallbackOrThrowException(…)
#getFallbackOrThrowException()
方法,获得【回退逻辑 Observable】或者【异常 Observable】,代码如下 :
|
- 耐心,这个方法看起来灰常长,也仅限于长,理解成难度很小。
- 第 3 行 :记录 HystrixRequestContext 。
- 第 5 至 8 行 :标记
executionResult
添加( 记录 )事件。 - 第 10 至 17 行 :调用
#isUnrecoverable(Exception)
方法,若异常不可恢复,直接返回【异常 Observable】。点击 链接 查看该方法。 - 第 19 至 21 行 :调用
#isRecoverableError(Exception)
方法,若异常可恢复,打印WARN
日志。点击 链接 查看该方法。主要针对java.lang.Error
情况,打印#isUnrecoverable(Exception)
排除掉的 Error。 - 【反向】第 141 至 143 行 :当配置
HystrixCommandProperties.fallbackEnabled = false
( 默认值 :true
) ,即失败回退功能关闭,调用#handleFallbackDisabledByEmittingError()
,返回【异常 Observable】。点击 链接 查看该方法。 - 【反向】第 138 至 140 行 :失败回退信号量( TryableSemaphore )【注意,不是正常执行信号量】使用失败,调用
#handleFallbackRejectionByEmittingError()
,返回【异常 Observable】。点击 链接 查看该方法。 - 第 23 行 :当配置
HystrixCommandProperties.fallbackEnabled = true
( 默认值 :true
) ,即失败回退功能开启。 - 第 27 至 32 行 :设置 HystrixRequestContext 的 Action ,使用第 3 行记录的 HystrixRequestContext 。
- 第 35 至 43 行 :TODO 【2007】【executionResult】用途
- 第 46 至 53 行 :TODO 【2007】【executionResult】用途
第 56 至 95 行 :处理回退逻辑执行发生异常的 Func1 ,返回【异常 Observable】。
- 第 61 行 :TODO 【2003】【HOOK】
- 第 63 行 :调用
#getExceptionFromThrowable(Throwable)
方法,获得 Exception 。若t
的类型为 Throwable 时,包装成 Exception 。点击 链接 查看该方法代码。 - 第 68 至 76 行 :当
fe
的类型为 UnsupportedOperationException 时,使用e
+fe
创建 HystrixRuntimeException 。该异常发生于HystrixCommand#getFallback()
抽象方法未被覆写。 - 第 77 至 86 行 :当
fe
的类型为其他异常时,使用e
+fe
创建 HystrixRuntimeException 。该异常发生于HystrixCommand#getFallback()
执行发生异常。 - 第 89 至 91 行 :调用
#shouldNotBeWrapped()
方法,判断originalException
是 ExceptionNotWrappedByHystrix 的实现时,即要求返回的【异常 Observable】不使用 HystrixRuntimeException 包装。点击 链接 查看该方法代码。 - 第 93 行 :返回【异常 Observable】,使用
toEmit
( HystrixRuntimeException ) 为异常。
第 98 行 :调用
#getFallbackSemaphore()
方法,获得失败回退信号量( TryableSemaphore )对象,点击 链接 查看该方法代码。TryableSemaphore 在 《Hystrix 源码解析 —— 命令执行(一)之正常执行逻辑》「3. TryableSemaphore」 有详细解析。
- 第 100 至 109 行 :信号量释放的 Action。
- 第 114 至 137 行 :失败回退信号量( TryableSemaphore )使用成功,返回【回退逻辑 Observable】。
- 【重要】第 116 至 122 行 :调用
#getFallbackObservable()
方法,创建【回退逻辑 Observable】。将子类对HystrixCommand#getFallback()
抽象方法的执行结果,使用Observable#just(...)
包装返回。点击 链接 查看该方法的代码。
- 第 116 行 :调用
#isFallbackUserDefined()
方法,返回命令子类是否实现HystrixCommand#getFallback()
抽象方法。只有已实现(true
) 的情况下,调用 HOOK TODO 【2003】【HOOK】。
- 第 129 至 137 行 :获得 【回退逻辑 Observable】。
- 第 131 行 :// TODO 【2003】【HOOK】
- 第 135 行 :调用
Observable#onErrorResumeNext(...)
方法,实现【失败回退 Observable】执行异常时,返回【异常 Observable】。
有两个注意点:
- 当命令执行超时时,失败回退逻辑使用的是 HystrixTimer 的线程池。
- 失败回退逻辑,无超时时间,使用要小心。