Hystrix 服务熔断降级
引言
Hystrix
属于Spring Cloud Netflix
中的套件之一,Spring Cloud Netflix
其中还包括Eureka
,Feign
,Ribbon
,Zuul
,Bus
。本文仅简单讲一下Hystrix
这个熔断降级框架。
为什么不讲sentinel
呢,因为sentinel
的官方文档全中文,并且使用也很方便,只要是个正常人,我觉得不需要单写一篇文章来讲,所以我只写过alibaba
的seata
的文章。
基本概念
- 区分上下游服务
下游服务
为请求方
,上游服务
为接受请求
,并返回响应
的一方。(很多人把上下游搞混,在王夕宁
Istio那本书中有明确定义,且Nginx之类中upstream
也代表的是接收请求
的一方。)- 什么是
服务熔断
?
服务熔断
机制是为了保证当服务产生调用链后,避免上游服务出现问题导致下游服务跟着受罪,致使整个应用中的服务发生雪崩
。- 什么是
服务降级
?
在触发熔断
机制后,服务就会被降级
,说人话就是断路器打开时,当下游服务请求上游服务,直接返回失败内容,不需要上游服务真的去工作。
举个栗子:应用中有很多服务,用户服务,订单服务,ID生成服务等等,当订单服务触发熔断机制导致服务降级后,应用中其他功能都不会受到影响,仅是订单服务是不可用状态,而不会导致整个应用所有功能都无法使用。- 为什么需要
服务熔断
?
当上游服务工作量达到瓶颈,CPU已经撑不住了,之后来的请求已经无法处理,如果这时不熔断就会导致下游服务的请求得不到回应,一直等待上游服务回应,下游服务的下游服务同样会等待,整个调用链都在等待,这样会把本来正常的服务也阻塞住,请求增多后就会导致整个应用的服务都成了不可用的状态。
注解开启断路器
@EnableHystrix
注解的作用和@EnableCircuitBreaker
注解的作用一样,@EnableHystrix
注解对EnableCircuitBreaker
注解进行了封装。所以使用Hystrix时用哪个注解都可以.
策略配置
首先需要区分的是,在
Ribbon
中的请求超时
和Hystrix
中的超时
是不同的,如果Hystrix
中配置timeoutInMilliseconds
<Ribbon
中的ReadTimeout
,这可能并不是你想要的结果,因为一旦触发Hystrix
中的超时就会立即产生服务熔断,不会达到重试的目的。timeoutInMilliseconds
的配置应 >Ribbon (1 + MaxAutoRetries + MaxAutoRetriesNextServer) * ReadTimeout
@DefaultProperties和@HystrixCommand
@DefaultProperties
注解是用在Controller
上的默认配置,在控制器方法上没有使用@HystrixCommand
时,就会使用@DefaultProperties
的配置。
简单的超时配置
@DefaultProperties(defaultFallback = "defaultFallBack",commandProperties = {@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds", value="1000")}) //Hystrix 定义全局 设置
public class HomeController {
//@Autowired
//private RestTemplate restTemplate;
@Qualifier("pay-server")
@Autowired
private IPayService payService;
@Autowired
private ConsulDiscoveryClient discoveryClient;
@GetMapping("getOrder")
@HystrixCommand(commandProperties = {@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds", value="5000")})
public String getOrder() throws ExecutionException, InterruptedException {
return payService.getOrder();
}
private String defaultFallBack() {
return "默认降级提示:请稍后重试~";
}
}
默认情况下,控制器内其他方法超时都是1秒,仅getOrder的配置会被替换,变成5秒。
其他配置
配置中我们可以看见commandProperties
配置了超时,commandProperties
接受的是@HystrixProperty
的列表,所以其中还有其他的配置可以设置。
我们可以在com.netflix.hystrix.HystrixCommandProperties中找到所有的配置项。
其中有隔离策略,断路器打开后的等待时间,错误阈值等等。
隔离策略
比如 execution.isolation.strategy
直译就是执行隔离策略,默认
的情况下是ExecutionIsolationStrategy.THREAD,意思就是线程隔离。
隔离策略中还有一个策略是ExecutionIsolationStrategy.SEMAPHORE,意思就是信号量,你可以理解为QPS。
默认情况下是根据threadPoolKey
和groupKey
进行区分。
如果没有规定,groupKey
的默认值是使用@HystrixCommand
标注的方法所在的类名
。
这就相当于对服务的接口进行限流,当超过阈值后就会触发熔断
。
如果想更改为信号量模式可以使用:
@HystrixProperty(name="execution.isolation.strategy", value="SEMAPHORE")
更改信号量模式下固定时间内(默认是1秒)最大请求数限制:
@HystrixProperty(name="execution.isolation.semaphore.maxConcurrentRequests", value="10")
threadPoolProperties
在@DefaultProperties
和@HystrixCommand
中 还有threadPoolProperties
的配置。
在默认使用线程池隔离时,你可以通过threadPoolProperties
配置线程池大小,如果需要可以也可以修改线程池队列大小。
@DefaultProperties(defaultFallback = "defaultFallBack",
threadPoolProperties = { @HystrixProperty(name="coreSize",value = "10"),
//@HystrixProperty(name="maxQueueSize",value = "5"), //如果改了 就会从无界队列变为有界队列
//@HystrixProperty(name="queueSizeRejectionThreshold",value = "5")//队列大小的拒绝阈值 这个值最好设置成和队列大小相同
},
commandProperties = { @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds", value="5000")
}
}
断路器状态
Hystrix
的断路器
有3种状态:
- 打开
断路器打开状态下,任何请求过来直接进行降级,返回fallback内容- 半开
当断路器在打开的状态下,等待固定时间后,转为半开状态,尝试处理部分请求,如果都正常才会关闭断路器。- 关闭
断路器关闭状态下,正常处理所有请求。
断路器时间配置
上面讲了如何通过@HystrixProperty
自己配置一些额外设置,现在就可以使用它对circuitBreaker.sleepWindowInMilliseconds
进行配置,这就是在断路器处于打开状态下,需要等待多久会进入半开状态,默认值是5秒。