1、背景
调用链路:A》B》C,如果C不可用,将影响B,进而影响A,形成雪崩效应。
2、熔断机制
Hystrix Command请求后端服务失败数量超过一定比例(默认50%)且10秒内超过20个请求, 断路器会切换到开路状态(Open). 这时所有请求会直接失败而不会发送到后端服务. 断路器保持在开路状态一段时间后(默认5秒,每隔5s允许一个请求通过), 自动切换到半开路状态(HALF-OPEN). 这时会判断下一次请求的返回情况, 如果请求成功(请求都是健康的(RT<250ms)), 断路器切回闭路状态(CLOSED), 否则重新切换到开路状态(OPEN). Hystrix的断路器就像我们家庭电路中的保险丝, 一旦后端服务不可用, 断路器会直接切断请求链, 避免发送大量无效请求影响系统吞吐量, 并且断路器有自我检测并恢复的能力.
熔断针对方法级别,A服务调用B服务的B1接口熔断,此时A服务依旧能调用B服务的B2接口。虽不直接影响调用B2接口,但由于熔断被触发,必然请求频率及错误比例会较高,这将导致单实例性能受到影响,从而间接影响A服务调用B服务的B2接口,表现通常为超时。
Note:测试发现,服务抛出的异常也会引发熔断。
HystrixBadRequestException异常将不会触发熔断。
Hystrix如何解决依赖隔离
- Hystrix使用命令模式HystrixCommand(Command)包装依赖调用逻辑,每个命令在单独线程中/信号授权下执行。
- 可配置依赖调用超时时间,超时时间一般设为比99.5%平均时间略高即可.当调用超时时,直接返回或执行fallback逻辑。
- 为每个依赖提供一个小的线程池(或信号),如果线程池已满调用将被立即拒绝,默认不采用排队,加速失败判定时间。
- 依赖调用结果分:成功,失败(抛出异常),超时,线程拒绝,短路。 请求失败(异常,拒绝,超时,短路)时执行fallback(降级)逻辑。
- 提供熔断器组件,可以自动运行或手动调用,停止当前依赖一段时间(10秒),熔断器默认错误率阈值为50%,超过将自动运行。
- 提供近实时依赖的统计和监控。
3、添加熔断机制
Note:
以demo中提到的SpringCloudConsumer项目为例,该服务将通过SpringCloudProducerFeignClient接口调用SpringCloudProducer服务。
3.1、application.properties配置
#开启熔断机制
feign.hystrix.enabled=true
# 设置hystrix超时时间,默认1000ms
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=60000
# 是否开启超时,默认false,不建议开启
# hystrix.command.default.execution.isolation.thread.interruptOnTimeout=false
# 最大线程数量,默认10,Fast Fail 应用,建议使用默认值。
# hystrix.threadpool.default.coreSize=20
# 允许在队列中的等待的任务数量,默认5,Fast Fail 应用,建议使用默认值。
# hystrix.threadpool.default.queueSizeRejectionThreshold=10
# queueSizeRejectionThreshold默认值是5,允许在队列中的等待的任务数量。maxQueueSize默认值是-1,队列大小。如果是Fast Fail 应用,建议使用默认值。线程池饱满后直接拒绝后续的任务,不再进行等待。即使maxQueueSize没有达到,达到queueSizeRejectionThreshold该值后,请求也会被拒绝。
3.2、创建熔断回调类
在feignClient同级目录创建目录fallback,在hystrix目录新建回调类。回调类分为含异常信息的回调类(以FallbackFactory为后缀),以及不含异常信息的回调类(以Fallback为后缀),二选一即可。
3.2.1、创建含异常信息的回调类
@Component
public class SpringCloudProducerFallbackFactory implements FallbackFactory<SpringCloudProducerFeignClient> {
/**
* 可获取熔断异常,重写接口中的各个方法分别返回带异常信息的熔断信息.
*
* @param cause 异常信息(可用于记录日志)
* @return FeignClient
*/
@Override
public SpringCloudProducerFeignClient create(Throwable cause) {
return new SpringCloudProducerFeignClient() {
@Override
public String testTrackID(String param) {
return "testTrackID:" + cause.getMessage();
}
@Override
public RoomRelationBo getRoomRelationByKeyID(String KeyID) {
return null;
}
};
}
}
3.2.2、创建不含异常信息的回调类
@Component
public class SpringCloudProducer2Fallback implements SpringCloudProducerFeignClient {
@Override
public String testTrackID(String param) {
return "[Hystrix]testTrackID"; // 自定义熔断返回信息
}
@Override
public RoomRelationBo getRoomRelationByKeyID(String KeyID) {
return null;
}
}
3.3、为FeignClient指定fallback或fallbackFactory
//@FeignClient(name = "spring-cloud-producer",fallback= SpringCloudProducerFallback.class)
@FeignClient(name = "spring-cloud-producer",fallbackFactory= SpringCloudProducerFallbackFactory.class)
public interface SpringCloudProducerFeignClient {
@PostMapping(value = "/api/testTrackID")
public String testTrackID(@RequestParam(value = "param") String param);
@GetMapping(value = "/api/getRoomRelationByKeyID")
public RoomRelationBo getRoomRelationByKeyID(@RequestParam("keyID") String KeyID);
}
3.4、依赖配置
引入依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
注解:
应用主类Application上加上@EnableCircuitBreaker或@EnableHystrix注解开启Hystrix的使用。
4、Hystrix配置说明
- 统计滚动的时间窗口 default 10000 ten seconds
withMetricsRollingStatisticalWindowInMilliseconds(10000) - 滚动时间窗口 bucket 数量 default
withMetricsRollingStatisticalWindowBuckets(10) - 采样时间间隔 default 500
withMetricsHealthSnapshotIntervalInMilliseconds(1) - 熔断器在整个统计时间内是否开启的阀值,默认20。也就是10秒钟内至少请求20次,熔断器才发挥起作用
withCircuitBreakerRequestVolumeThreshold(20) - 默认:50。当出错率超过50%后熔断器启动.
withCircuitBreakerErrorThresholdPercentage(30) - 熔断器默认工作时间,默认:5秒.熔断器中断请求5秒后会关闭重试,如果请求仍然失败,继续打开熔断器5秒,如此循环
withCircuitBreakerSleepWindowInMilliseconds(1000) - 隔离策略
withExecutionIsolationStrategy(ExecutionIsolationStrategy.SEMAPHORE) - 信号量隔离时最大并发请求数
withExecutionIsolationSemaphoreMaxConcurrentRequests(2) - 命令组名,该命令属于哪一个组,可以帮助我们更好的组织命令。
withGroupKey(HystrixCommandGroupKey.Factory.asKey(“HelloGroup”)) - 命令名称,每个CommandKey代表一个依赖抽象,相同的依赖要使用相同的CommandKey名称。依赖隔离的根本就是对相同CommandKey的依赖做隔离。
andCommandKey(HystrixCommandKey.Factory.asKey(“Hello”) - 所属线程池的名称,同样配置的命令会共享同一线程池,若不配置,会默认使用GroupKey作为线程池名称。
andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey(“HelloThreadPool”)) - 命令属性,设置包括断路器的配置,隔离策略,降级设置,以及一些监控指标等。
- 线程池属性,配置包括线程池大小,排队队列的大小等。
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=1000
超时时间,默认1000ms
execution.timeout.enabled
是否开启超时,默认true
execution.isolation.thread.interruptOnTimeout
当超时的时候是否中断(interrupt) HystrixCommand.run()执行
配置说明官方文档:https://github.com/Netflix/Hystrix/wiki/Configuration