Hystrix 熔断器
1、分布式系统面临的问题
复杂分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免地失败。
我们都知道,多个微服务之间的调用往往是扇形的这就是所谓的“扇出”,如果其中一个服务响应时间过长或者不可用,往往会导致“雪崩效应”
我们为了应对以上的问题,就提出了Hystrix 这个概念
2、Hystrix
Hystix 是 Netflix 开源的一个延迟和容错库,用于隔离访问远程服务、第三方库,防止出现级联失败(雪崩)。
Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。
“断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方无法处理的异常,这样就保证了服务调用方的线程不会被长时间、不必要地占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。
Hystrix有几个核心的概念:
3、Hystrix 降级
从上图我们了解到了服务降级,那么Hystrix 的服务降级是怎么实现的呢?我们通过一个简单的例子去实现
Hystrix 降级 – 服务提供方
-
在服务提供方,引入 hystrix 依赖(Eureka 2.X 默认引入了hystrix 和 ribbon)
<!-- hystrix --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency>
-
在启动类上开启Hystrix功能:@EnableCircuitBreaker
/** * 启动类 */ @EnableEurekaClient @SpringBootApplication @EnableCircuitBreaker // 开启Hystrix功能 public class ProviderApp {
-
定义降级方法
/** * 定义降级方法: * 1. 方法的返回值需要和原方法一样 * 2. 方法的参数需要和原方法一样 * 3. 就是只有方法名不同 */ public Goods findOne_fallback(int id){ Goods goods = new Goods(); goods.setTitle("降级了~~~"); return goods; }
-
使用 @HystrixCommand 注解配置降级方法
@GetMapping("/findOne/{id}") @HystrixCommand(fallbackMethod = "findOne_fallback") public Goods findOne(@PathVariable("id") int id){ 。。。 }
-
如果要设置降级配置的属性,可以通过@HystrixCommand注解的commandProperties属性进行配置,配置的信息在HystrixCommandProperties类中定义。了解常用设置即可。
@GetMapping("/findOne/{id}") @HystrixCommand(fallbackMethod = "findOne_fallback",commandProperties = { //设置Hystrix的超时时间,默认1s @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value = "3000") }) public Goods findOne(@PathVariable("id") int id){
Hystrix 降级 – 服务消费方
-
在application.yml中配置开启 feign.hystrix.enabled = true
# 开启feign对hystrix的支持 feign: hystrix: enabled: true
-
定义feign 调用接口实现类,复写方法,即 降级方法
/** * Feign 客户端的降级处理类 * 1. 定义类 实现 Feign 客户端接口 * 2. 使用@Component注解将该类的Bean加入SpringIOC容器 */ @Component public class GoodsFeignClientFallback implements GoodsFeignClient { @Override public Goods findGoodsById(int id) { Goods goods = new Goods(); goods.setTitle("又被降级了~~~"); return goods; } }
-
在 @FeignClient 注解中使用 fallback 属性设置降级处理类。
@FeignClient(value = "HYSTRIX-PROVIDER",fallback = GoodsFeignClientFallback.class) public interface GoodsFeignClient { @GetMapping("/goods/findOne/{id}") public Goods findGoodsById(@PathVariable("id") int id); }
注意: 服务处理的时间过长,但是又不想做降级处理,我们可以给服务提供方设置降级的时间
@GetMapping("/findOne/{id}")
@HystrixCommand(fallbackMethod = "findOne_fallback",commandProperties = {
//设置Hystrix的超时时间,默认1s,ribbon默认的响应时间
@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value = "3000")
})
public Goods findOne(@PathVariable("id") int id){
4、Hystrix 熔断
Hystrix 熔断机制,用于监控微服务调用情况,当失败的情况达到预定的阈值(5秒失败20次),会打开断路器,拒绝所有请求,直到服务恢复正常为止。
熔断的目的是为了保护系统。全自动,不需要干预。
三种状态之间的切换
- 关闭到打开。失败降级的次数达到阈值。默认5秒失败20次。
- 打开到半开。持续5秒钟。半开:(允许一半的请求通过)
- 半开到关闭。通过的请求成功超过80%或者不足5秒20次
这里我们也可以做对应的代码演示
让我们的请求ID为1的时候抛出异常,引发降级。
hystrix-provider的GoodsController中进行设置:
public Goods findOne(@PathVariable("id") int id){
//如果id == 1 ,则出现异常,id != 1 则正常访问
if(id == 1){
//1.造个异常
int i = 3/0;
}
可以通过@HystrixCommand注解的commandProperties属性进行配置:
@GetMapping("/findOne/{id}")
@HystrixCommand(fallbackMethod = "findOne_fallback",commandProperties = {
//设置Hystrix的超时时间,默认1s
@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value = "3000"),
//监控时间 默认5000 毫秒
@HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds",value = "5000"),
//失败次数。默认20次
@HystrixProperty(name="circuitBreaker.requestVolumeThreshold",value = "20"),
//失败率 默认50%
@HystrixProperty(name="circuitBreaker.errorThresholdPercentage",value = "50")
})
public Goods findOne(@PathVariable("id") int id){
关于Hystrix 熔断器我们就聊到这里,感谢观看,希望下次再见。