Hystrix 熔断降级配置
1. 基础知识
1.1 服务隔离
说明:把每个依赖或调用的服务都隔离开来,防止级联失败引起整体服务不可用
Hystrix 隔离策略的区别如下:
1.2 熔断
说明:为了防止服务雪崩,类似家用电的保险丝,起到保护服务的作用
1.3 降级
概念:接口出错时的兜底方法,以下图的4、5、6步能导致降级发生
1.4 Hystrix 线程划分:
- 分组 commandGroup:代表某一个服务;如 order-server
- 命令名称 commandKey:代表服务的一个接口;如获取订单的接口
- 线程池划分:默认以分组划分,可以使线程池划分的提供粒度更小
总结:command group一般来说,可以是对应一个服务,多个command key对应这个服务的多个接口,多个接口的调用共享同一个线程池
1.5 注解:
@HystrixCommand
@HystrixProperty
例子:
@GetMapping("test")
@HystrixCommand(
groupKey = "ConsumerControllerGroup",
commandKey = "test",
commandProperties = {
@HystrixProperty(name = HystrixPropertiesManager.EXECUTION_TIMEOUT_ENABLED, value = "false"),
@HystrixProperty(name = HystrixPropertiesManager.REQUEST_CACHE_ENABLED, value = "false")
}/*, fallbackMethod = "fallBack"*/,
threadPoolProperties = {
@HystrixProperty(name = HystrixPropertiesManager.CORE_SIZE, value = "200")
})
public String test() throws InterruptedException {
System.out.println("sleep");
TimeUnit.SECONDS.sleep(4);
System.out.println("4S 后的输出");
return "test";
}
2. 配置属性
4 种优先级别配置;全局内置默认值 < 动态全局配置属性 < 内置实例默认值 < 实例配置属性
- 全局内置默认值:写死在代码里面的配置;HystrixCommandProperties、HystrixPropertiesManager;
- 全局动态配置属性:通过配置文件配置全局的值;hystrix.command.default.xxx.x
- 内置类实例默认值:写死在代码里的实例的值;
- 类实例配置属:通过配置文件配置特定实例的值;hystrix.command.${HystrixCommandKey}.xxx.x
2.1 Command 属性
2.1.1 execution 配置
execution 配置控制的是 HystrixCommand.run() 的执行
配置 | 说明 | 默认值 |
---|---|---|
execution.isolation.strategy | 配置 HystrixCommand.run() 的执行隔离策略;可选:THREAD、SEMAPHORE | THREAD |
execution.isolation.thread.timeoutInMilliseconds | 该属性用来配置 HystrixCommand 执行的超时时间,单位为毫秒 。当Hystri xCommand 执行时间超过该配置值之后,Hystrix 会将该执行命令标记为 TIMEOUT 并进入服务降级 处理逻辑 。 | 1000 毫秒(1秒) |
execution.timeout.enable | 用来配置 HystrixCommand.run() (默认为同步执行),的执行是否启用超时时间。 | true |
execution.isolation.semaphore.maxConcurrentRequests | 仅隔离策略为 **SEMAPHORE **时生效,配置该属性的信号量的大小(并发请求数)。不够信号量,则请求会被拒绝。 | 10 |
2.1.2 fallback 配置(信号量、线程池隔离策略都适用)
以下这些属性用来控制HystrixCommand.getFallback() 的执行
配置 | 说明 | 默认值 |
---|---|---|
fallback.isolation.semaphore.maxConcurrentRequests | 方法的最大调用数;假设置为10,如果有11个请求 fallback 了,多出的 1 个请求则直接报错,不会再执行 fallback,因为没有 fallback 可用了。 | 10 |
fallback enable | 是否启用降级策略 | true |
2.1.3 circuitBreaker 配置
用来控制 HystrixCircuitBreaker.java 熔断的行为
配置 | 说明 | 默认值 |
---|---|---|
circuitBreaker.enable | 是否启用断路器 | true |
circuitBreaker.requestVolumeThreadshold | 滑动窗口时间内请求数不能超过该配置,如果超过是否熔断还需要再判断错误率。 | 20 |
circuitBreaker.sleepWindowInMilliseconds | 断路器打开后的休眠时间,休眠时间结束后会尝试检测是否能够关闭断路器 | 5000 |
circuitBreaker.errorThresholdPercentage | 断路器打开的错误的百分比条件 | 50% |
circuitBreaker.foreceOpen | 强制开启断路器 | false |
circuitBreaker.foreceClose | 强制关闭断路器 | false |
2.1.5 threadPool 属性
指定隔离策略为线程池时的配置;全局配置前缀 hystrix.threadpool.default。以下配置类似 ThreadPoolExecutor
配置 | 说明 | 默认值 |
---|---|---|
coreSize | 核心线程数 | 10 |
maxQueueSize | 线程池等待队列大小。设置-1使用 SynchronousQueue实现,否则使用LinkedBlockingQueue实现 | -1 |
queueSizeRejectionThreshold | 队列拒绝阈值,该参数即使队列没有达到最大值也能拒绝请求。对LinkedBlockingQueue队列的补充,因为LinkedBlockingQueue不能动态修改它的对象大小。 | 5 |
metrics.rollingStats.timeInMilliseconds | 该参数用来设置滚动时间窗的长度 | 10000 |
metrics.rollingStats.numBuckets | 设置滚动时间窗被划分成 “桶” 的数量 | 10 |
注意:metrics.rollingStats.timeInMilliseconds 参数必须能被 metrics.rollingStats.numBuckets 整除
线程池隔离策略共享请求信息
区分以下三个 ThreadLocal
- ThreadLocal
- InheritableThreadLocal
- TransmittableThreadLocal
import com.netflix.hystrix.HystrixCommandProperties;
import com.netflix.hystrix.strategy.HystrixPlugins;
import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import java.util.concurrent.Callable;
/**
* 此类能够保证:RequestContext 请求上下文,也就是 RequestAttributes 能够在线程池里自动有效
*
* @author Administrator
*/
@Component
@Log4j2
public class RequestContextHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy implements ApplicationContextAware {
@Value(value = "${hystrix.command.default.execution.isolation.strategy:THREAD}")
private String strategy;
@Override
public <T> Callable<T> wrapCallable(Callable<T> callable) {
return new RequestAttributeAwareCallable<>(callable, RequestContextHolder.getRequestAttributes());
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (!HystrixCommandProperties.ExecutionIsolationStrategy.THREAD.name().equals(strategy)) {
return;
}
log.info("Hystrix ---- 启用共享 RequestContext 请求上下文信息");
HystrixPlugins.getInstance().registerConcurrencyStrategy(new RequestContextHystrixConcurrencyStrategy());
}
private static class RequestAttributeAwareCallable<T> implements Callable<T> {
private final Callable<T> delegate;
private final RequestAttributes requestAttributes;
public RequestAttributeAwareCallable(Callable<T> callable, RequestAttributes requestAttributes) {
this.delegate = callable;
this.requestAttributes = requestAttributes;
}
@Override
public T call() throws Exception {
// 执行之前绑定上下文,执行完成后释放
try {
RequestContextHolder.setRequestAttributes(requestAttributes);
return delegate.call();
} finally {
RequestContextHolder.resetRequestAttributes();
}
}
}
}
参考:
https://blog.csdn.net/zhuyu19911016520/article/details/85346065
https://blog.csdn.net/qq_42046105/article/details/84000988
https://zhuanlan.zhihu.com/p/59109781
Spring Cloud微服务实战