实现熔断,设置开启/关闭熔断器,设置半打开熔断器

1.熔断器的开启--常用的熔断器方法:defaultFallback 

 // 可以造成熔断的方法
    @GetMapping("/sleep5/{id}")
    @HystrixCommand(defaultFallback = "sleepBreaker", commandProperties = {
//@HystrixProperty(name = "fallback.enabled", value = "true"),//服务降級是否启用 @HystrixProperty(name
= "circuitBreaker.enabled", value = "true"), // 是否执行回调函数,开启熔断器 @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"), // 当请求达到这个数量之后,才进行错误占比的计算。 @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"), // 时间窗口期:半打开休眠时间,熔断之后过了这段休眠时间,就会半打开(熔断半开),如果请求成功 且 符合规则 则认为当前服务恢复正常,就会 关闭熔断 @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60") // 错误占比,当错误次数超过这个百分比,就会熔断。 }) // commandProperties 的整个意思就是10秒中10次请求中有60%的请求出问题就熔断 public String sleep5(@PathVariable("id") int id) throws Exception { if (id < 0) { throw new Exception("id 是负数,抛出异常!!"); } return "访问正常 id:" + id + " port:" + port; } // 熔断时调用的方法 public String sleepBreaker() { return "接口有问题,目前被熔断了..."; }
1)传参正常情况:

2)问题情况:(errorThresholdPercentage设置为60%)

 3)多次使用-1为参数访问,再用1做为参数再访问,也不会得到正常结果了,就是被熔断了:

是因为(sleepWindowInMilliseconds", value = "10000"), 半打开休眠时间10s,熔断之后过了这段休眠时间,就会半打开,尝试接口是否恢复,如果恢复就完全打开熔断器。

 解析:

 

1.)涉及到断路器的三个重要参数:

  1. 快照时间窗:断路器确定是否打开需要统计一些请求和错误数据,而统计的时间范围就是快照时间窗,默认为最近的10秒。
  2. 请求总数阀值:在快照时间窗内,必须满足请求总数阀值才有资格熔断。默认为20,以为这在10秒内,如果该Hystrix命令的调用次数不足20次,即使所有的请求都超时或其他原因失败,断路器都不会打开。
  3. 错误百分比阀值:当请求总数在快照时间窗内超过了阀值,比如发生了30次调用,如果在这30次调用中,有15次发生了超时异常,也就是超过了50%的错误百分比,在默认设定50%的阀值情况下,这时候就会将断路器打开。

2)发现一个奇怪的现象:为什么熔断后,我请求接口 传入参数id明明是正数,却还是调用了降级方法呢?

这就是熔断器的链路服务恢复有一个过程,由此我们可以得出以下结论:

  1. 熔断打开请求不再调用当前服务,内部设置一般为MTTR(平均故障处理时间),当打开长达导致所设时钟则进入半熔断状态
  2. 熔断关闭:熔断关闭后不会对服务进行熔断
  3. 熔断半开:部分请求根据规则调用当前服务,如果请求成功且符合规则则认为当前服务恢复正常,关闭熔断

 2.另一种熔断器方法:fallbackMethod

注解@HystrixCommand除了defaultFallback这个参数可以调默认降级方法外,还有一个fallbackMethod可以调用一个与原方法对应的参数相同的方法,用于提供更明确的提示。
// 感觉这个说法还算靠谱点
    // fallbackMethod: 设置HystrixCommand服务降级所使用的方法名称,注意该方法需要与原方法定义在同一个类中,并且方法签名也要一致
    // defaultFallback: 设置HystrixCommand默认的服务降级处理方法,如果同时设定了fallbackMethod,会优先使用fallbackMethod所指定的方法,需要注意的是defaultFallback该属性所指定的方法没有参数,需要注意返回值与原方法返回值的兼容性
    @GetMapping("/sleep/{id}")
    @HystrixCommand(fallbackMethod = "sleepFallbackMethod", defaultFallback = "sleepFallback") // 使用指定的降级方法
    public String sleep(@PathVariable("id") int id) {
        int a = 10 / 0; // 触发抛出异常
        return productApi.sleep() + port + " id: " + id;
    }
    
    // 参数签名必须与原方法相同
    public String sleepFallbackMethod(int id) {
        return "sleep 方法被 控制器中指定的方法sleepFallbackMethod 降级,参数是:" + id;
    }
 
    // 无参数
    public String sleepFallback() {
        return "sleepFallback 控制器中方法降级..." + port;
    }

 

三. 给多个方法指定默认的降级方法

有可能多个方法降级的提示只需要返回相同的内容,这时可以给控制器类增加注解:@DefaultProperties(defaultFallback = "通用的降级方法名")

@DefaultProperties(defaultFallback = "sleepFallbackDefault")

控制器内添加4个方法:需要有降级的方法只需添加注解@HystrixCommand,不需要指定降级方法名,会使用类上指定的默认降级方法。不添加注解的不会做降级处理。

 @GetMapping("/sleep2")
    @HystrixCommand // 使用默认的降级方法
    public String sleep2() {
        return productApi.sleep() + port;
    }
 
    @GetMapping("/sleep3")
    @HystrixCommand // 使用默认的降级方法
    public String sleep3() {
        return productApi.sleep() + port;
    }
 
    // 不做降级处理,会出异常:java.net.SocketTimeoutException: Read timed out
    @GetMapping("/sleep4")
    public String sleep4() {
        return productApi.sleep() + port;
    }
    
    // 无参数
    public String sleepFallbackDefault() {
        return "sleepFallbackDefault 控制器中方法降级,默认的降级方法..." + port;
    }

 

 

 

 

可以看到sleep4方法没有指定注解,方法没有降级。为了防止出现这种情况出现,可以为Feign定义的接口(ProductApi)提供一个实现类,来定义接口中各方法的降级方法。

为Feign的接口实现一个类

步骤:

  1. 修改application.yml 启用 Feign 对 Hystrix的支持。
  2. 实现接口 ProductApi 的一个实现类。
  3. 为接口ProductApi的注解@FeignClient增加参数fallback

 

feign:
  hystrix:
      
    # 开启 Feign对Hystrix的支持
    enabled: true

添加 ProductApi 接口的实现类 ProductApiHystrix.java,并注入容器

 

package com.example.api.hystrix;
 
import com.example.api.ProductApi;
import org.springframework.stereotype.Component;
 
@Component // 注入容器
public class ProductApiHystrix implements ProductApi{
 
    @Override
    public String index() {
        return "ProductApiHystrix.index 降级方法...";
    }
 
    @Override
    public String sleep() {
        return "ProductApiHystrix.sleep 降级方法...";
    }
    
}
 

 为接口ProductApi的注解@FeignClient增加参数fallback

 
 
@FeignClient(value = "PRODUCT-SERVICE", fallback = ProductApiHystrix.class)

重启并访问,可以看到控制器的方法没有做改变的情况下,达到了降级的目的:

 

 

测试:

 

 到此,降级已经完成。

posted @ 2024-06-19 14:04  苹果芒  阅读(5)  评论(0编辑  收藏  举报