
这篇我们说说Springcloud的第三个组件——Hystrix。Hystrix类似于电路上的“保险丝”。我们知道,如果短时间内用电量过大,保险丝会“自杀”,从而断电,起到保护电路安全的作用。这也就是常说的“跳闸”。
Hystrix就是系统的保险丝,至于具体是如何保护的,请接着看。
Hystrix是什么? |
Hystrix是用于服务保护的,当某个服务单元发生故障后,通过断路器的故障监控,向调用方返回一个错误响应,而不是长时间的等待。这样就不会使得线程因调用故障服务被长时间占用不释放,避免了故障在分布式系统中的蔓延。
其具备服务降级、服务熔断、线程和信号隔离、请求缓存、请求合并、服务监控等功能。
原理分析 |
这部分我们来看看当一个请求调用了相关服务依赖之后,Hystrix是如何工作的。
工作流程
- (1)创建HystrixCommand或HystrixObservableCommand对象
采用“命令设计模式”来实现对服务调用操作的封装。这两个Command对象分别对应于返回单个操作结果和多个操作结果的场景。
- (2)命令执行
一共有4种命令的执行方式,其中HystrixCommand实现了execute()和queue()。HystrixObservableCommand实现了observe()和toObservable()。此部分使用了“观察者-订阅者”模式。
- (3)结果是否被缓存
如果缓存功能是启用的,且命令缓存命中,则结果会以Observable对象的形式立即返回。
- (4)断路器是否打开
如果没有缓存命中,则Hystrix在执行命令前,会检查断路器是否为打开状态。如果为打开状态,则直接到fallback处理。也就是跳到第8步。如果是关闭状态,会接着往下执行,去检查是否有可用资源来执行命令。
- (5)线程池/请求队列/信号量是否占满
如果请求队列、信号量或每个依赖服务的专有线程池已经被占满,那么Hystrix会转到执行fallback。
- (6)请求依赖服务
此时有两个备选方法:HystrixCommand.run()是返回一个单一的结果,或者抛出异常。HystrixObservableCommand.construct()是返回一个Observable对象来发射多个结果,或通过onError发送错误通知。
- (7)计算断路器的健康度
Hystrix会将“成功”、“失败”、“拒绝”、“超时”等信息报告给断路器,断路器会对这些数据进行统计。这些统计数据用于决定是否要将断路器打开或恢复期结束后,如果还是没有达到健康指标,再次“熔断/短路”。
- (8)fallback处理
fallback处理又叫做“服务降级”。当命令执行失败的时候,Hystrix会进入fallback尝试回退处理。
- (9)返回成功的响应
当命令执行成功之后,Hystrix会将处理结果直接返回或是以Observable的形式返回。
断路器原理
关于断路器是如何决策熔断和记录信息的,其涉及到了3个抽象方法。
- allowRequest():每个Hystrix命令的请求都通过它判断是否被执行
- isOpen():返回当前断路器是否打开
- markSuccess():用来闭合断路器
依赖隔离
依赖隔离就是为每一个依赖服务创建一个独立的线程池,这样就算某个依赖服务出现延迟过高的情况,也只是对该依赖服务的调用产生影响,而不会拖慢其它的依赖服务。
使用 |
(1)创建请求命令
- 同步或异步执行:@HystrixCommand
- 立即执行或当所有订阅者都订阅它后才会执行:observe()、toObservable()
- 发射一次数据或多次:Observable、HystrixObservableCommand
(2)定义服务降级
使用如下注解实现:
@HystrixCommand(fallbackMethod="defaultUser")
可以不去实现降级逻辑的情况:
- 执行写操作命令
当写操作失败后,只需通知调用者即可,不用实现服务降级。
- 执行批处理或离线计算的命令
如果出现问题,只需将错误传给调用者,让调用者稍后重试即可。
(3)异常处理
异常处理分为异常传播和异常获取。
异常传播:
@HystrixCommand(ignoreExceptions={BadRequestException.class})
异常获取:
User fallback(String id,Throwable e){}
(4)命令名称、分组以及线程池划分
可以使用注解的方式分别对命令名称、分组、线程池划分进行设置。
@HystrixCommand(commandKey=“getUserById”,groupKey=“UserGroup”,threadPoolKey=“getUserByIdThread”)
(5)请求缓存
请求缓存分为开启请求缓存和清理失效缓存。
- 请求缓存,此注解需和@HystrixCommand结合使用
@HystrixCommand
@CacheResult
public User getUserById(Long id){}
- 让缓存失效
@CacheRemove(commandKey=“getUserById”)
(6)请求合并
请求合并就是将N个通信请求合并为一个,以减少通信消耗和线程池的占用。使用的是@HystrixCollapser注解。
合并前:
合并后:
性能监控 |
Hystrix 仪表盘:用来实时监控单个实例的Hystrix的各项指标信息。
Turbine:对集群进行监控
小结 |
本文的思维导图: