Hystrix的熔断、隔离和降级
首先引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
启动类加==@EnableHystrix注解开启熔断器,所有被@HystrixCommand==注解修饰的方法会被aspect处理
@Service
public class TestService {
@HystrixCommand(groupKey = "AnnotationHystrixInvoke", commandKey = "getInfo", fallbackMethod = "getFallback",
commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000"),
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50")
}
)
public String getInfo() {
System.out.println(Thread.currentThread().getName() + "开始执行getInfo");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
System.out.println("捕获到异常" + e.getMessage());
}
System.out.println(Thread.currentThread().getName() + "仍在执行getInfo");
return "hello";
}
public String getFallback() {
System.out.println(Thread.currentThread().getName() + "开始执行getFallback");
return "bye bye";
}
}
本例中主业务逻辑是getInfo函数,该函数调用超时时间设置为1s,降级逻辑为getFallback()。主业务逻辑线程sleep了2s,到了超时时间后hystrix启动一个新的线程中断主业务逻辑线程,新线程执行降级逻辑,同时主业务逻辑线程被中断后抛出了中断异常,捕获异常处理后继续执行。执行结果如下:
hystrix-AnnotationHystrixInvoke-1开始执行getInfo
捕获到异常sleep interrupted
hystrix-AnnotationHystrixInvoke-1仍在执行getInfo
HystrixTimer-1开始执行getFallback
bye bye
hystrix-AnnotationHystrixInvoke-2开始执行getInfo
捕获到异常sleep interrupted
hystrix-AnnotationHystrixInvoke-2仍在执行getInfo
HystrixTimer-1开始执行getFallback
bye bye
hystrix-AnnotationHystrixInvoke-3开始执行getInfo
捕获到异常sleep interrupted
hystrix-AnnotationHystrixInvoke-3仍在执行getInfo
HystrixTimer-2开始执行getFallback
bye bye
...
类级别默认属性
在实际项目中,业务场景较多。而HystrixCommand的属性也很多。于是就产生了一个问题:我们是否需要为每一个需要使用hystrix方法都定义一遍属性?比如:一个类中有很多方法,不能在每个方法都配置一遍相同的属性,容易造成配置代码的冗余,所以Javanica提供了@DefaultProperties注解,解释如下:
@DefaultProperties是类(类型)级别的注释,允许默认命令属性,如groupKey,threadPoolKey,commandProperties,threadPoolProperties,ignoreExceptions和raiseHystrixExceptions。
使用此注解指定的属性,将在类中使用@HystrixCommand注解的方法中公用,除非某个方法明确使用相应的==@HystrixCommand==参数来指定这些属性
@DefaultProperties(groupKey = "DefaultGroupKey")
class Service {
@HystrixCommand // hystrix command group key is 'DefaultGroupKey'
public Object commandInheritsDefaultProperties() {
return null;
}
@HystrixCommand(groupKey = "SpecificGroupKey") // command overrides default group key
public Object commandOverridesGroupKey() {
return null;
}
}
注意事项
Hystrix只能在外部方法使用,这是因为Hystrix的使用是通过AOP进行拦截调用的,而Spring AOP是无法拦截内部方法调用的
结合配置使用
在某些业务场景下,确实有必要为每一个HystrixCommand设置不同的参数值,全部写在注解上面显得代码很臃肿,冗余。而且有时这些参数值可能还会动态改变。
#-----------------Hystrix配置-----------------------
hystrix:
# === === === == 默认Command === === === ==
command:
default:
execution:
isolation:
# 调用隔离方式, 默认: 采用线程隔离, ExecutionIsolationStrategy:THREAD
strategy: THREAD
# 调用超时时间, 默认: 5 秒
thread:
timeoutInMilliseconds: 8000
# 使用信号量隔离时, 命令调用最大的并发数
semaphore:
maxConcurrentRequests: 10
#使用信号量隔离时, 命令fallback调用最大的并发数
fallback:
isolation:
semaphore:
maxConcurrentRequests: 10
# === === === == 熔断器 === === === ==
circuitBreaker:
# 熔断器在整个统计时间内是否开启的阀值, 默认20个请求
requestVolumeThreshold: 8
# 熔断器默认工作时间, 默认: 5 秒
sleepWindowInMilliseconds: 5
# 默认: 50%, 当出错率超过50% 后熔断器启动
errorThresholdPercentage: 50
# 是否强制开启熔断器阻断所有请求, 默认: false, 不开启
forceOpen: false
# 是否允许熔断器忽略错误, 默认false, 不开启
forceClosed: false
# === === === == 线程池 === === === ==
threadpool:
default:
# 配置线程池大小, 默认值10个
coreSize: 0
# 配置队列长度, 默认-1使用SynchronousQueue,其他值则使用LinkedBlockingQueue:不可动态修改:
maxQueueSize: -1
# 队列拒绝的阈值,可通过修改这个变量动态修改允许排队的长度: maxQueueSize=-1时不适用:
queueSizeRejectionThreshold: 5
# 线程生存时间, 默认1分钟
keepAliveTimeMinutes: 1
HystrixCommand含义请参考 HystrixCommand注解分析