Hystrix
在微服务架构中,服务与服务之间通过远程调用的方式进行通信,一旦某个被调用的服务发生了故障,其依赖服务也会发生故障,此时就会发生故障的蔓延,最终导致系统瘫痪。Hystrix实现了断路器模式,当某个服务发生故障时,通过断路器的监控,给调用方返回一个错误响应,而不是长时间的等待,这样就不会使得调用方由于长时间得不到响应而占用线程,从而防止故障的蔓延。Hystrix具备服务降级、服务熔断、线程隔离、请求缓存、请求合并及服务监控等强大功能。
1. Hystrix的使用
1.1 pom坐标的导入
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
1.2 Hystrix功能引入
在启动类上添加注解 @EnableCircuitBreaker //开启Hystrix熔断器
1.3 Hystrix功能使用
@HystrixCommand(fallbackMethod="fallBackMethodTest") //服务熔断的方法设置
在需要进行服务熔断的类、或者方法上添加 @HystrixCommand,通过注解参数fallbackMethod指定服务熔断的回调方法;
1.3.1 编写Hystrix回调方法
//需要注意的是:
//1. 方法的返回值需要和原方法一致
//2. 方法的参数需要和原方法一致
public void fallBackMethodTest(){
}
1.3.2 编写Hystrix回调类
@FeignClient(value = "service-hi", fallback = HelloServiceFallback.class)
public interface HelloService {
@RequestMapping(value = "/hi", method = RequestMethod.GET)
String sayHi(@RequestParam(value = "name") String name);
}
@Service
public class HelloServiceFallback implements HelloService {
@Override
public String sayHi(String name) {
return "Fallback method invoked, name is " + name;
}
}
1.4 使用
当配合Feign 使用时,由于Feign的包中已经有 Hystrix的jar包,所以不需要再引入 Hystrix的坐标,只需要再配置文件中添加部分配置即可;
feign:
hystrix:
enabled: true
2. 服务降级
触发条件:
- 服务调用超时
- 服务熔断
- 线程池、信号量不够
@HystrixCommand 注解;
@HystrixCommand中的常用参数
1. fallbackMethod:指定服务降级处理方法;
2. ignoreExceptions:忽略某些异常,不发生服务降级;
3. commandKey:命令名称,用于区分不同的命令;
4. groupKey:分组名称,Hystrix会根据不同的分组来统计命令的告警及仪表盘信息;
5. threadPoolKey:线程池名称,用于划分线程池。
//设置超时时间
@HystrixCommand(fallbackMethod="fallBackMethodTest",commandProperties={
//设置 Hystrix 的超时时间,默认1s
@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="3000")
})
hystrix除了在方法上特殊定制的fallback以外,还有一个全局的fallback。只需要在类上通过@DefaultProperties(defaultFallback = "globalFallback")
来实现全局的备选方案。一个方法满足触发降级的条件时如果该请求对应的HystrixCommand
注解中没有配置fallback则使用所在类的全局fallback。如果全局也没有则抛出异常。
3. 服务熔断
@HystrixCommand(
commandProperties = {
@HystrixProperty(name = "circuitBreaker.enabled",value = "true"), //是否开启断路器
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"), //请求次数
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "10000"), //时间范围
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "60"), //失败率达到多少后跳闸
},
fallbackMethod = "getInfoFallback"
)
3.1 关闭、半开和全开状态
当失败次数达到了上面的配置参数要求,断路器就会由关闭状态
变为打开状态
,当断路器为打开状态
时,所有的请求都会直接被降级,隔一段时间后,断路器会自动变为 半开状态
,这个时候如果服务能够正常被访问,断路器就会调整为 关闭状态
;
4. 业务隔离
4.1 线程隔离
@HystrixCommand(
groupKey = "order-service-getPaymentInfo",
commandKey = "getPaymentInfo",
threadPoolKey = "orderServicePaymentInfo",
commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "1000")
},
threadPoolProperties = {
@HystrixProperty(name = "coreSize" ,value = "6"),
@HystrixProperty(name = "maxQueueSize",value = "100"),
@HystrixProperty(name = "keepAliveTimeMinutes",value = "2"),
@HystrixProperty(name = "queueSizeRejectionThreshold",value = "100")
},
fallbackMethod = "fallBackMethodTest"
)
4.2 信号量隔离
@HystrixCommand(
commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "1000"),
@HystrixProperty(name = HystrixPropertiesManager.EXECUTION_ISOLATION_STRATEGY,value = "SEMAPHORE"),
@HystrixProperty(name = HystrixPropertiesManager.EXECUTION_ISOLATION_SEMAPHORE_MAX_CONCURRENT_REQUESTS,value = "6")
},
fallbackMethod = "fallBackMethodTest"
)
//信号量最大为6 。 表示并发6之后就会进行等待。等待超时时间为 1s。
5. 请求缓存
当系统并发量越来越大时,我们需要使用缓存来优化系统,达到减轻并发请求线程数,提供响应速度的效果。
@CacheResult:开启缓存,默认所有参数作为缓存的key,cacheKeyMethod可以通过返回String类型的方法指定key;
@CacheKey:指定缓存的key,可以指定参数或指定参数中的属性值为缓存key,cacheKeyMethod还可以通过返回String类型的方法指定;
@CacheRemove:移除缓存,需要指定commandKey。
6. 请求合并
微服务系统中的服务间通信,需要通过远程调用来实现,随着调用次数越来越多,占用线程资源也会越来越多。Hystrix中提供了@HystrixCollapser用于合并请求,从而达到减少通信消耗及线程数量的效果。
将多个请求合并成一个请求已达到降低并发的问题。
@HystrixCollapser的常用属性
batchMethod:用于设置请求合并的方法;
collapserProperties:请求合并属性,用于控制实例属性,有很多;
timerDelayInMilliseconds:collapserProperties中的属性,用于控制每隔多少时间合并一次请求;
@HystrixCollapser(
scope = com.netflix.hystrix.HystrixCollapser.Scope.GLOBAL,
batchMethod = "getIds",
collapserProperties = {
@HystrixProperty(name = HystrixPropertiesManager.MAX_REQUESTS_IN_BATCH , value = "3"), //最大请求数
@HystrixProperty(name = HystrixPropertiesManager.TIMER_DELAY_IN_MILLISECONDS, value = "10")
}
)