目录
概况
Git:https://github.com/Netflix/Hystrix
为保护服务的稳定性,作为的客户端熔断和断路器
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
核心注解
- @EnableHystrix 启动类注解控制熔断功能。
- @HystrixCommand 方法注解,熔断控制配置。
基于Feign服务熔断
配置:
feign:
hystrix:
enabled: true
接口
@FeignClient(value = "服务名",fallback = FallbackService.class)
public interface 接口Service {
@RequestMapping(value = "/接口名/{参数}",method = RequestMethod.GET)
String 接口 (@PathVariable("参数") String 参数) ;
}
熔断接口
@Component
public class FallbackService implements 接口Service {
@Override
public String 接口(String 参数) {
return "服务被熔断"+参数;
}
}
模型基础
- 命令设计模式。将客户端对服务直接调用,封装成一个待执行的请求,客户端和请求被封装为一个对象,对于服务方而言,每个不同的请求就是不同的参数,从而让我们可用不同的请求对客户进行参数化;命令模式的最大特征就是把客户端和服务端直接关系,通过命令对象进行解耦,在执行上,可以对请求排队或者记录请求日志,以及支持可撤销的操作。
- 线程池和信号量隔离。对系统资源进行分离,具备资源限定的能力,进而保护系统
工作原理
- 会对依赖服务的调用请求封装成命令对象,Hystrix 对 命令对象抽象了两个抽象类:HystrixCommand(命令对象会返回一个唯一返回值) 和HystrixObservableCommand (命令对象 会返回多个返回值)。
- 执行命令。执行方式:
- execute():用于HystrixCommand,阻塞式同步执行,返回依赖服务的单一返回结果(或者抛出异常)
- queue():用于HystrixCommand,基于Future的异步方式执行,返回依赖服务的单一返回结果(或者抛出异常)
- observe():用于HystrixObservableCommand,基于Rxjava的Observable方式,返回通过Observable表示的依赖服务返回结果,代调用代码先执行(Hot Obserable)
- toObbsebable():用于HystrixObservableCommand,基于Rxjava的Observable方式,返回通过Observable表示的依赖服务返回结果,执行代码等到真正订阅的时候才会执行(cold observable)
- 返回结果缓存判断。可配置
- 断路器打开判断。当第3步没有缓存没有命中,则判断一下当前断路器的断路状态是否打开。如果断路器状态为打开状态,则Hystrix将不会执行此Command命令,直接执行步骤8 调用Fallback;如果断路器状态是关闭,则执行 步骤5 检查是否有足够的资源运行 Command命令
- 资源(线程池/队列 /信号量)满足检查。当资源已满时,不会运行Command命令,直接执行步骤8。
- 执行HystrixObservableCommand.construct() 或者HystrixCommand.run()。如果run() 或者construct()方法 的真实执行时间超过了Command设置的超时时间阈值, 则当前则执行线程(或者是独立的定时器线程)将会抛出TimeoutException。抛出超时异常TimeoutException,后,将执行步骤8的Fallback降级处理。即使run()或者construct()执行没有被取消或中断,最终能够处理返回结果,但在降级处理逻辑中,将会抛弃run()或construct()方法的返回结果,而返回Fallback降级处理结果。
- 计算断路健康状况。Hystrix 会统计Command命令执行执行过程中的成功数、失败数、拒绝数和超时数,将这些信息记录到断路器(Circuit Breaker)中。断路器将上述统计按照时间窗的形式记录到一个定长数组中。断路器根据时间窗内的统计数据去判定请求什么时候可以被熔断,熔断后,在接下来一段恢复周期内,相同的请求过来后会直接被熔断。当再次校验,如果健康监测通过后,熔断开关将会被关闭。
- 获取Fallback。触发场景:
- 步骤4 断路器已经被打开
- 步骤5 执行命令的线程池、队列或者信号量资源已满
- 步骤6 Command执行时抛出了任何异常;
- 命令执行的时间超过阈值
- 返回结果
断路器
工作原理
- 断路器时间窗内的请求数 是否超过了请求数断路器生效阈值circuitBreaker.requestVolumeThreshold,如果超过了阈值,则将会触发断路,断路状态为开启。例如,如果当前阈值设置的是20,则当时间窗内统计的请求数共计19个,即使19个全部失败了,都不会触发断路器。
- 并且请求错误率超过了请求错误率阈值errorThresholdPercentage
- 如果两个都满足,则将断路器由关闭迁移到开启
- 如果断路器开启,则后续的所有相同请求将会被断路掉;
- 直到过了沉睡时间窗sleepWindowInMilliseconds后,再发起请求时,允许其通过(此时的状态为半开起状态)。如果请求失败了,则保持断路器状态为开启状态,并更新沉睡时间窗。如果请求成功了,则将断路器状态改为关闭状态;
key值 | 说明 | 默认值 |
circuitBreaker.enabled | 是否开启断路器 | true |
circuitBreaker.requestVolumeThreshold | 断路器启用请求数阈值 | 20 |
circuitBreaker.sleepWindowInMilliseconds | 断路器启用后的睡眠时间窗 | 5000(ms) |
circuitBreaker.errorThresholdPercentage | 断路器启用失败率阈值 | 50(%) |
circuitBreaker.forceOpen | 是否强制将断路器设置成开启状态 | false |
circuitBreaker.forceClosed | 是否强制将断路器设置成关闭状态 | false |
注:
默认配置:上述Key值之前要加上hystrix.command.default.前缀拼接
实例配置:上述Key值之前要加上hystrix.command.<command-key>. 前缀拼接
系统指标
Hystrix对系统指标的统计是基于时间窗模式的。
时间窗会随着系统的运行逐渐向前移动,而时间窗的长度和桶的数量是固定不变的,那么随着时间的移动,会出现较久的过期的桶被移除出去,新的桶被添加进来,如下图所示:
key值 | 说明 | 默认值 |
metrics.rollingStats.timeInMilliseconds | 时间窗的长度 | 10000(ms) |
metrics.rollingStats.numBuckets | 桶的数量,需要保证timeInMilliseconds % numBuckets =0 | 10 |
metrics.rollingPercentile.enabled | 是否统计运行延迟的占比 | true |
metrics.rollingPercentile.timeInMilliseconds | 运行延迟占比统计的时间窗 | 60000(ms) |
metrics.rollingPercentile.numBuckets | 运行延迟占比统计的桶数 | 6 |
metrics.rollingPercentile.bucketSize | 百分比统计桶的容量,桶内最多保存的运行时间统计 | 100 |
metrics.healthSnapshot.intervalInMilliseconds | 统计快照刷新间隔 | 500 (ms) |
资源隔离技术
TODO