Spring Cloud Hystrix也是spring团队对netflix的Hystrix的封装,主要提供了服务熔断和降级,同时还兼顾了限流的功能.
Hystrix的最核心功能是服务熔断,那么为什么需要服务熔断呢?
在微服务架构下,往往一个前端的请求对应了后端的多个服务,而且有时服务的调用链会很深(这也是微服务架构单来的一个副作用),服务与服务之间的依赖错综复杂,如果某一个服务不可用,可能会导致所有的服务瘫痪,造成服务的雪崩,而Hystrix可以将出现问题的服务从调用链中剔除,但是剔除以后,用户的请求怎么办呢?就需要服务降级来处理,不能说直接把有问题的服务剔除了保证了服务不会出现雪崩,但是给用户抛了一个异常回去,所以Hystrix还提供了两种服务降级策略:
- fallback method
- fallback factory
下面我们来看一下Hystrix的总体的执行逻辑
首先明确一下Hystrix的隔离策略,Hystrix提供了两种隔离策略,一种是线程隔离,一种是信号量隔离,线程隔离策略简单理解,就是将用户请求线程和服务调用线程分离,采用线程池+Future的方式,而信号量隔离实际上是用用户请求线程来进行服务调用,信号量个人理解就是一个限流工具,它规定了同一时刻能够通过的请求数量,一般都是使用线程隔离策略,原因在于,这种策略可以利用多线程加快处理速度,另外还能够进行更加精细的控制,例如配置服务调用的超时时间等,可以通过如下的参数来修改隔离策略
hystrix.command.default.execution.isolation.strategy=thread
hystrix.command.default.execution.isolation.strategy=semaphore
对于这两种策略,根据他们的特点可以总结一下他们适用的场景,对于线程隔离,由于采用多线程技术,所以执行效率会比较高,同时利用线程池的特点支持超时机制,一般在高并发场景下都会适用线程隔离策略,但也会造成一定的线程上下文切换的开销
信号量隔离的最大特点的一个用户线程怼到底,所以不支持超时机制,比较适合并发量不大的并且服务提供者能够快速返回的场景。
下面罗列一下常见的配置项
#配置隔离策略
hystrix.command.default.execution.isolation.strategy=thread/semaphore
#信号量隔离级别下的信号量个数
hystrix.command.default.execution.isolation.semaphore.maxConcurrentRequests=10
#线程隔离级别下开启调用超时功能
hystrix.command.default.execution.timeout.enabled=true/false
#指定服务调用线程执行的超时时间
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=
#是否开启中断,也就是当服务调用线程执行超时后,是否还让它继续执行,true=中断其执行
hystrix.command.default.execution.isolation.thread.interruptOnTimeout=true/false
#当服务调用线程被主动取消时,是否中断其执行
hystrix.command.default.execution.isolation.thread.interruptOnCancel=true/false
#是否开启熔断器
hystrix.command.default.circuitBreaker.enabled=true/false
#当滑动窗口内的请求失败率达到指定的阈值时开启熔断器
hystrix.command.default.circuitBreaker.errorThresholdPercentage=
#当滑动窗口内的请求数量达到阈值时,开启熔断器
hystrix.command.default.circuitBreaker.requestVolumeThreshold=n
#当熔断器开启后,在指定的时间后会尝试检查相关的指标数据,如果符合配置,则关闭熔断器
hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds=
另外,关于线程池的配置我们是在@HystrixCommand注解中配置的,来看一个简单的例子
@HystrixCommand(fallbackMethod = "error", commandProperties = {
//线程隔离模式 or 信号量隔离模式
@HystrixProperty(name = "execution.isolation.strategy", value = "THREAD"),
//如果请求超过5秒没有返回,则进入熔断降级
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000"),
//接口调用失败次数如果超过10次,则进入熔断降级
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10")
},
threadPoolProperties = {
@HystrixProperty(name="coreSize", value = "10"),
@HystrixProperty(name = "maxQueueSize", value = "10"),
@HystrixProperty(name = "keepAliveTimeMinutes", value = "1000"),
@HystrixProperty(name = "queueSizeRejectionThreshold", value = "10")
}
)
关于Hystrix源码,由于底层大量使用了响应式编程,跟踪起来非常麻烦,本人也没有捋的很清楚,这里简单看一下它的基本实现原理。
按照spring boot的脾气,想找到hystrix的初始化的逻辑,就应该看看spring.factories
从名字上看,可以看到有两个可能有关的类,但是本人在HystrixAutoConfiguration中并没有找到什么有用的信息,却在HystrixCircuitBreakerConfiguration这个类中找到了一点蛛丝马迹,从名字上看,这个类的熔断器的配置,点进去可以看到一个关于Aop的Aspect切面
是不是感觉很熟悉了,一句话解释:对@HystrixCommand注解进行拦截,利用Spring Aop返回给IoC容器代理对象,对于具体的逻辑,我尝试用语言来描述一下(对各种东拼西凑的信息的理解),再深入进去,Hystrix使用了Command设计模式和RxJava的响应式编程,非常难跟踪,目前为止还没搞明白,所以只能到这里了。