一介闲人
一介闲人
断路器是在调用项目(保险丝是安装在家里,不是安装在供电局)中配置使用的。
1、修改pom.xml
文件,引入断路器Resilience4j依赖
<!-- Resilience4j CircuitBreaker -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
</dependency>
<!-- 由于断路保护等需要AOP实现,所以必须导入AOP包 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2、修改application.yml
文件,添加断路器Resilience4j的配置参数
spring:
cloud:
openfeign:
circuitbreaker: #开启circuitbreaker 和 分组激活 spring.cloud.openfeign.circuitbreaker.enabled
enabled: true
group:
enabled: true #没开分组永远不会分组的配置,精确优先、分组次之(开了分组)、默认最后
# Resilience4j CircuitBreaker 按照次数:COUNT_BASED的例子
# 6次访问中当执行方法的失败率达到50%时 CircuitBreaker将进入开启OPEN状态(保险丝跳闸断电)拒绝所有请求。
# 等待5秒后,CircuitBreaker 将自动从开启OPEN状态过渡到半开HALF_OPEN状态,允许一些请求通过以测试服务是否恢复正常。
# 如还是异常 CircuitBreaker 将重新进去开启OPEN状态;如正常 将进入关闭CLOSE(闭合)状态恢复正常处理请求
resilience4j:
circuitbreaker:
configs:
default:
failure-rate-threshold: 50 # 设置50%的调用失败时打开断路器,超过失败请求的百分比CircuitBreaker变为OPEN状态
sliding-window-type: count_based #设置滑动窗口类型为按次数:COUNT_BASED
sliding-window-size: 6 #滑动窗口的大小,类型配置为COUNT_BASED 表示6个请求,配置为TIME_BASED 表示6秒
minimum-number-of-calls: 6 #断路器计算失败率或慢调用率之前所需要的最小样本(每个滑动窗口周期),如果配置为 10,则必须最少及记录10个样本,然后才能计算失败率。如果只记录9次调用,即使所有的调用都很失败了,断路器也不会开启进入OPEN状态
automatic-transition-from-open-to-half-open-enabled: true #是否启用自动从开启状态过度到半开状态,默认为 true,如果启用,CircuitBreaker将自动从开启状态过渡到半开状态,并允许一些请求通过以测试服务是否恢复正常
wait-duration-in-open-state: 5s #从OPEN状态到HALF_OPEN状态需要等待的时间
permitted-number-of-calls-in-half-open-state: 2 #半开状态允许的最大请求数,默认为10, 在半开状态下,CircuitBreaker将允许最多该设置值的个数请求通过,如果其中有任何一个请求失败,circuitbreaker将
record-exceptions:
- java.lang.Exception
instances:
cloud-payment-service:
base-config: default
3、使用@CircuitBreaker
注解,使用断路器
@RestController
public class OrderCircuitController {
@Resource
private PayFeignApi payFeignApi;
@GetMapping("feign/pay/circuit/{id}")
@CircuitBreaker(name = "cloud-payment-service", fallbackMethod = "myCircuitFallback") //name是指调用哪个微服务
public String myCircuitBreaker(@PathVariable("id") Integer id){
return payFeignApi.myCircuit(id);
}
public String myCircuitFallback(Integer id, Throwable throwable){
return "服务降级了,参数是: " + id + " 原因:" + throwable.getMessage();
}
}
4、自定义配置(选用)
虽然可以直接在@CircuitBreaker
注解中指定一些基本的配置,但更复杂的配置可能需要通过创建配置类来实现。
@Configuration
public class CircuitBreakerConfiguration {
@Bean
public Customizer<CircuitBreakerConfig> defaultCustomizer() {
return config -> config
.failureRateThreshold(50)
.waitDurationInOpenState(Duration.ofMillis(10000))
.slowCallDurationThreshold(Duration.ofMillis(5000));
}
}
基于时间的滑动窗口是通过有N个桶的环形数组实现。
如果滑动窗口的大小为10秒,这个环形数组总是有10个桶,每个桶统计了在这一秒发生的所有调用结果(部分统计结果)数组中的第一个桶存储了当前这一秒内的所有调用结果,其他的桶存储了之前每秒调用的结果。
滑动窗口不会单独存储所有的调用结果,而是对每个桶内的统计结果和总的统计值进行增量的更新,当新的调用结果被记录是,总的统计值会进行增量更新。
检索快照(总的统计值)的时间复杂度为O(1),因为快照已经预先统计好了,并且和滑动窗口大小无关。
关于此方法实现的空间需求(内存消耗)约等于O(n)。由于每次调用结果(元组)不会被单独存储,只是对N个桶进行单独统计和一次总分的统计。
每个桶在进行部分统计时存在三个整型,为了计算,调用失败数,慢调用数,总调用数。还有一个long类型变量,存储所有调用的响应时间。
修改application.yml
文件,添加断路器Resilience4j的配置参数
# Resilience4j CircuitBreaker 按照時間:TIME_BASED的例子
resilience4j:
timelimiter:
configs:
default:
timeout-duration: 10s #是一个坑,timelimiter默认限制远程1s,超过1s就超时异常,配置了降级,就走降级逻辑
circuitbreaker:
configs:
default:
failure-rate-threshold: 50 #设置50%的调用失败时打开断路器,超过失败请求的百分比CircuitBreaker变为OPEN状态
slow-call-duration-threshold: 2s #慢调用阈值,高于这个阈值的视为慢调用并增加慢调用比例
slow-call-rate-threshold: 30 #慢调用比例百分比峰值,断路器把调用时间大于slow-call-duration-threshold,视为慢调用,当慢调用比例高于该值
sliding-window-type: TIME_BASED #滑动窗口类型:按照時間(TIME_BASED)
sliding-window-size: 2 #滑动窗口的大小配置,配置TIME_BASED,表示2秒
minimum-number-of-calls: 2 #断路器计算失败了或者调用率之前所需的最小样本(每个滑动窗口期)
permitted-number-of-calls-in-half-open-state: 2 #半开状态下允许的最大请求数,默认时10
wait-duration-in-open-state: 5s # 从OPEN到HALF_OPEN状态需要等待的时间
record-exceptions:
- java.lang.Exception
ignore-exceptions:
- java.lang.IndexOutOfBoundsException
instances:
cloud-payment-service:
base-config: default
评论