当前位置: 首页 > news >正文

SpringCloud-05 Resilience4J 服务降级和熔断

服务雪崩:指在多个服务之间存在依赖关系时,当一个服务发生故障或不可用时,导致其他服务也无法正常工作的情况。这种现象通常是因为服务之间的依赖关系过于紧密,当一个服务发生故障时,其他服务无法正确处理该服务的请求或返回结果,从而导致级联故障,整个系统无法正常运行。所以,有问题的节点,快速熔断(快速返回失败处理或者返回默认兜底数据【服务降级】)。
“断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方无法处理的异常,这样就保证了服务调用方的线程不会被长时间、不必要地占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。

服务熔断:服务熔断(Circuit Breaker)是一种用来控制服务间调用的一种机制,目的是为了减少故障对系统的影响。当某个服务出现故障或者响应时间过长时,熔断器会自动打开,停止向该服务发送请求,而是返回一个预设的错误响应。这样可以防止故障或响应缓慢的服务拖垮整个系统,同时也可以快速失败,减少用户的等待时间。

服务降级:服务降级是指在系统负载过高或者出现异常情况下,为了保证核心功能的稳定性和可用性,暂时关闭一些非核心功能或者降低服务的质量,以保证系统整体的稳定运行。服务降级可以通过调整系统配置参数、限流、降低并发请求等方式实现。

服务限流 服务限时 服务预热 接近实时的监控 兜底的处理动作

Circuit Breaker:一种设计模式,用于在分布式系统中处理故障和延迟。在分布式系统中,服务之间通常会相互调用。当一个服务发生故障或延迟时,调用链上的其他服务可能会受到影响,导致整个系统出现级联故障。为了解决这个问题,引入了Circuit Breaker模式。Circuit Breaker模式包含三个状态:关闭、开启和半开。

Circuit Breaker是一套规范和接口,真正落地实现的是Resilience4J

Resilience4J是一个用于构建可靠和弹性应用程序的Java库。它提供了一套轻量级的容错模式和工具,帮助开发人员更容易地实现应用程序的弹性。 需要Java17

//核心模块
resilience4j-circuitbreaker: 熔断		√
resilience4j-ratelimiter: 限流			√
resilience4j-bulkhead: 舱壁				√
resilience4j-retry: ⾃动重试
resilience4j-cache: 结果缓存
resilience4j-timelimiter: 超时处理

1.熔断
熔断器有三种状态:关闭状态(正常状态)、开启状态(不允许通过)和半开状态。

failure-rate-threshold 
以百分比配置失败率峰值sliding-window-type 
断路器的滑动窗口期类型
可以基于“次数”(COUNT_BASED)或者“时间”(TIME_BASED)进行熔断,默认是COUNT_BASED。sliding-window-size
若COUNT_BASED,则10次调用中有50%失败(即5次)打开熔断断路器;
若为TIME_BASED则,此时还有额外的两个设置属性,含义为:在N秒内(sliding-window-size)100%(slow-call-rate-threshold)的请求超过N秒(slow-call-duration-threshold)打开断路器。slowCallRateThreshold
以百分比的方式配置,断路器把调用时间大于slowCallDurationThreshold的调用视为慢调用,当慢调用比例大于等于峰值时,断路器开启,并进入服务降级。slowCallDurationThreshold
配置调用时间的峰值,高于该峰值的视为慢调用。permitted-number-of-calls-in-half-open-state
运行断路器在HALF_OPEN状态下时进行N次调用,如果故障或慢速调用仍然高于阈值,断路器再次进入打开状态。minimum-number-of-calls
在每个滑动窗口期样本数,配置断路器计算错误率或者慢调用率的最小调用数。比如设置为5意味着,在计算故障率之前,必须至少调用5次。如果只记录了4次,即使4次都失败了,断路器也不会进入到打开状态。wait-duration-in-open-state
从OPENHALF_OPEN状态需要等待的时间

配置 滑动窗口类型: COUNT_BASED

//在8001端口新增controller
@RestController
public class PayCircuitController {//=========Resilience4j CircuitBreaker 的例子@GetMapping(value = "/pay/circuit/{id}")public String myCircuit(@PathVariable("id") Integer id){if(id == -4) throw new RuntimeException("----circuit id 不能负数");if(id == 9999){try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) {e.printStackTrace(); }}return "Hello, circuit! inputId:  "+id+" \t " + IdUtil.simpleUUID();}
}//在通用接口添加
/*** Resilience4j CircuitBreaker 的例子* @param id* @return*/@GetMapping(value = "/pay/circuit/{id}")public String myCircuit(@PathVariable("id") Integer id);//在80端口pom文件新增依赖
<!--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>//改yml文件
server:port: 80spring:application:name: cloud-consumer-openfeign-ordercloud:consul:host: localhostport: 8500discovery:prefer-ip-address: true #优先使用服务ip进行注册service-name: ${spring.application.name}openfeign:client:config:default:#连接超时时间connectTimeout: 3000          #3秒#读取超时时间readTimeout: 3000cloud-payment-service:#连接超时时间connectTimeout: 20000#读取超时时间readTimeout: 20000httpclient:hc5:enabled: truecompression:request:enabled: truemin-request-size: 2048 #最小触发压缩的大小mime-types: text/xml,application/xml,application/json #触发压缩数据类型response:enabled: true# 开启circuitbreaker和分组激活 spring.cloud.openfeign.circuitbreaker.enabledcircuitbreaker:enabled: truegroup:enabled: true #没开分组永远不用分组的配置。精确优先、分组次之(开了分组)、默认最后
# feign日志以什么级别监控哪个接口        OpenFeign内容
logging:level:com:dc:cloud:apis:PayFeignApi: debug# Resilience4j CircuitBreaker 按照次数:COUNT_BASED 的例子
#  6次访问中当执行方法的失败率达到50%CircuitBreaker将进入开启OPEN状态(保险丝跳闸断电)拒绝所有请求。
#  等待5秒后,CircuitBreaker 将自动从开启OPEN状态过渡到半开HALF_OPEN状态,允许一些请求通过以测试服务是否恢复正常。
#  如还是异常CircuitBreaker 将重新进入开启OPEN状态;如正常将进入关闭CLOSE闭合状态恢复正常处理请求。
resilience4j:circuitbreaker:configs:default:failureRateThreshold: 50 #设置50%的调用失败时打开断路器,超过失败请求百分⽐CircuitBreaker变为OPEN状态。slidingWindowType: COUNT_BASED # 滑动窗口的类型slidingWindowSize: 6 #滑动窗⼝的⼤⼩配置COUNT_BASED表示6个请求,配置TIME_BASED表示6秒minimumNumberOfCalls: 6 #断路器计算失败率或慢调用率之前所需的最小样本(每个滑动窗口周期)。如果minimumNumberOfCalls为10,则必须最少记录10个样本,然后才能计算失败率。如果只记录了9次调用,即使所有9次调用都失败,断路器也不会开启。automaticTransitionFromOpenToHalfOpenEnabled: true # 是否启用自动从开启状态过渡到半开状态,默认值为true。如果启用,CircuitBreaker将自动从开启状态过渡到半开状态,并允许一些请求通过以测试服务是否恢复正常waitDurationInOpenState: 5s #从OPENHALF_OPEN状态需要等待的时间permittedNumberOfCallsInHalfOpenState: 2 #半开状态允许的最大请求数,默认值为10。在半开状态下,CircuitBreaker将允许最多permittedNumberOfCallsInHalfOpenState个请求通过,如果其中有任何一个请求失败,CircuitBreaker将重新进入开启状态。recordExceptions:- java.lang.Exceptioninstances:cloud-payment-service:baseConfig: default//在80端口新增OrderCircuitController类
@RestController
public class OrderCircuitController {@Resourceprivate PayFeignApi payFeignApi;@GetMapping(value = "/feign/pay/circuit/{id}")@CircuitBreaker(name = "cloud-payment-service", fallbackMethod = "myCircuitFallback")public String myCircuitBreaker(@PathVariable("id") Integer id){return payFeignApi.myCircuit(id);}//myCircuitFallback就是服务降级后的兜底处理方法public String myCircuitFallback(Integer id,Throwable t) {// 这里是容错处理逻辑,返回备用结果return "myCircuitFallback,系统繁忙,请稍后再试-----/(ㄒoㄒ)/~~";}
}

滑动窗口类型: TIME_BASED

//把之前的基于COUNT_BASED的yml配置注释掉注释掉,改为新的yml配置
# Resilience4j CircuitBreaker 按照时间:TIME_BASED 的例子
resilience4j:timelimiter:configs:default:timeout-duration: 10s #神坑的位置,timelimiter 默认限制远程1s,超于1s就超时异常,配置了降级,就走降级逻辑circuitbreaker:configs:default:failureRateThreshold: 50 #设置50%的调用失败时打开断路器,超过失败请求百分⽐CircuitBreaker变为OPEN状态。slowCallDurationThreshold: 2s #慢调用时间阈值,高于这个阈值的视为慢调用并增加慢调用比例。slowCallRateThreshold: 30 #慢调用百分比峰值,断路器把调用时间⼤于slowCallDurationThreshold,视为慢调用,当慢调用比例高于阈值,断路器打开,并开启服务降级slidingWindowType: TIME_BASED # 滑动窗口的类型slidingWindowSize: 2 #滑动窗口的大小配置,配置TIME_BASED表示2秒minimumNumberOfCalls: 2 #断路器计算失败率或慢调用率之前所需的最小样本(每个滑动窗口周期)。permittedNumberOfCallsInHalfOpenState: 2 #半开状态允许的最大请求数,默认值为10。waitDurationInOpenState: 5s #从OPENHALF_OPEN状态需要等待的时间recordExceptions:- java.lang.Exceptioninstances:cloud-payment-service:baseConfig: default 

2.舱壁隔离
Spring Cloud的舱壁隔离是一种微服务架构中的隔离机制,用于防止服务之间的相互影响和故障扩散。舱壁隔离通过在不同的线程池或线程组中执行不同的服务实例,将它们隔离开来。
Spring Cloud提供了两种常用的舱壁隔离实现方法:线程池隔离信号量隔离

1.信号隔离

//PayCircuitController类中添加
//=========Resilience4j bulkhead 的例子
@GetMapping(value = "/pay/bulkhead/{id}")
public String myBulkhead(@PathVariable("id") Integer id)
{if(id == -4) throw new RuntimeException("----bulkhead id 不能-4");if(id == 9999){try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); }}return "Hello, bulkhead! inputId:  "+id+" \t " + IdUtil.simpleUUID();
}//在PayFeignApi接口新增方法
/*** Resilience4j Bulkhead 的例子* @param id* @return*/
@GetMapping(value = "/pay/bulkhead/{id}")
public String myBulkhead(@PathVariable("id") Integer id);//在feign80端口新增依赖
<!--resilience4j-bulkhead-->
<dependency><groupId>io.github.resilience4j</groupId><artifactId>resilience4j-bulkhead</artifactId>
</dependency>//新增yml配置
####resilience4j bulkhead 的例子
resilience4j:bulkhead:configs:default:maxConcurrentCalls: 2 # 隔离允许并发线程执行的最大数量maxWaitDuration: 1s # 当达到并发调用数量时,新的线程的阻塞时间,我只愿意等待1秒,过时不候进舱壁兜底fallbackinstances:cloud-payment-service:baseConfig: defaulttimelimiter:configs:default:timeout-duration: 20s//在OrderCircuitController类新增方法
/***(船的)舱壁,隔离* @param id* @return*/
@GetMapping(value = "/feign/pay/bulkhead/{id}")												//Bulkhead.Type.SEMAPHORE类型
@Bulkhead(name = "cloud-payment-service",fallbackMethod = "myBulkheadFallback",type = Bulkhead.Type.SEMAPHORE)	
public String myBulkhead(@PathVariable("id") Integer id)
{return payFeignApi.myBulkhead(id);
}
public String myBulkheadFallback(Throwable t)
{return "myBulkheadFallback,隔板超出最大数量限制,系统繁忙,请稍后再试-----/(ㄒoㄒ)/~~";
}
http://www.lryc.cn/news/438741.html

相关文章:

  • 哈希表、算法
  • 变更AWS EC2 实例配置或实例类型
  • 【前端】ref引用的作用
  • 运用Java实现倒计时功能
  • Vue 第三方调用若依系统实现系统单点登录
  • IP纯净度对跨境电商有哪些影响
  • docker-01 创建一个自己的镜像并运行容器
  • 国产视频转换HDMI1.4转单/双MIPI DSI/CSI LT6911C芯片方案,带音频输出,QFN64封装 Lontium
  • 亚马逊、沃尔玛、敦煌网、Target塔吉特、Temu环境搭建测评技术!
  • yjs05——matplotlib画其他图像
  • 【C#】添加临时环境变量
  • 物联网之ESP32与微信小程序实现指示灯、转向灯
  • ICPC网络赛 以及ACM训练总结
  • 优化深度学习模型训练过程:提升PASCAL VOC 2012数据集上Deeplabv3+模型训练效率的策略
  • 【乐吾乐大屏可视化组态编辑器】使用手册
  • uniapp+若依 开发租房小程序源码分享
  • 日系编曲:节奏吉他与主音吉他 吉他的节奏型 节奏吉他的编写思路 吉他的Riff
  • 【网络安全的神秘世界】目录遍历漏洞
  • 使用 SpringBoot 基础web开发的支持
  • nature reviews genetics | 细胞互作和通讯方法总结
  • AI 浪潮中的一体化数据库|外滩大会之OceanBase实录
  • Qt自定义按键实现长,短按
  • 禁用win10的自动更新功能
  • 机器学习 第12章 计算学习理论
  • 【雅特力AT32】外部中断事件控制器EXINT(附源码解析)
  • Redis集群_cluster
  • jdk相关介绍
  • 【GoMate框架案例】讯飞大模型RAG智能问答挑战赛top10 Baseline
  • 2024/9/15 408“回头看”之应用层小总结(下)
  • 经纬恒润高压电池管理系统,助力新能源汽车飞速发展