11.5、熔断降级规则
熔断降级规则
熔断降级规则用于保护系统免受慢调用和异常的影响。本节将学习如何配置和使用熔断降级规则。
本章节内容参考官方文档顺序: 根据 Sentinel 官方文档 - Circuit Breaking,官方文档按照以下顺序讲解:
- Circuit Breaking Overview(熔断降级概览)
- Slow Call Ratio(慢调用比例)
- Exception Ratio(异常比例)
- Exception Count(异常数)
- Circuit Breaker States(熔断器状态)
- Fallback Handling(降级处理)
本节将学习:慢调用比例、异常比例、异常数、熔断策略,以及降级处理。
在商城项目中配置熔断降级
场景:订单服务调用支付服务熔断
业务场景:
- 订单服务调用支付服务处理支付
- 如果支付服务响应慢或异常,应该熔断
- 熔断后返回降级响应,避免影响订单服务
步骤1:在订单服务中配置熔断规则
文件路径: mall-microservices/order-service/src/main/java/com/mall/orderservice/config/SentinelConfig.java
package com.mall.orderservice.config; import com.alibaba.csp.sentinel.slots.block.RuleConstant; import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule; import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; import org.springframework.context.annotation.Configuration; import javax.annotation.PostConstruct; import java.util.ArrayList; import java.util.List; @Configuration public class SentinelConfig { @PostConstruct public void initDegradeRules() { List<DegradeRule> rules = new ArrayList<>(); // 订单服务调用支付服务:慢调用比例熔断 DegradeRule paymentRule = new DegradeRule(); paymentRule.setResource("paymentService:createPayment"); paymentRule.setGrade(RuleConstant.DEGRADE_GRADE_RT); paymentRule.setCount(1000); // 慢调用阈值:1秒 paymentRule.setTimeWindow(10); // 熔断时长:10秒 paymentRule.setMinRequestAmount(5); // 最小请求数:5 paymentRule.setSlowRatioThreshold(0.5); // 慢调用比例:50% rules.add(paymentRule); DegradeRuleManager.loadRules(rules); } }
慢调用比例
在订单服务中的应用
场景:支付服务响应慢时熔断
配置说明:
- 慢调用阈值:1000ms(1秒)
- 时间窗口:10秒内统计
- 最小请求数:至少5个请求才开始统计
- 慢调用比例:50%(如果50%的请求超过1秒,触发熔断)
熔断效果:
- 触发熔断后,10秒内所有请求直接降级
- 10秒后进入半开状态,尝试一个请求
- 如果请求成功,关闭熔断;如果失败,继续熔断
异常比例
在订单服务中的应用
场景:支付服务异常率高时熔断
文件路径: mall-microservices/order-service/src/main/java/com/mall/orderservice/config/SentinelConfig.java
@PostConstruct public void initDegradeRules() { List<DegradeRule> rules = new ArrayList<>(); // 异常比例熔断:支付服务异常率超过50%时熔断 DegradeRule exceptionRatioRule = new DegradeRule(); exceptionRatioRule.setResource("paymentService:createPayment"); exceptionRatioRule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO); exceptionRatioRule.setCount(0.5); // 异常比例:50% exceptionRatioRule.setTimeWindow(10); // 熔断时长:10秒 exceptionRatioRule.setMinRequestAmount(10); // 最小请求数:10 rules.add(exceptionRatioRule); DegradeRuleManager.loadRules(rules); }
使用场景:
- 支付服务出现大量异常时
- 异常比例超过阈值时触发熔断
- 保护订单服务不被异常影响
异常数
在订单服务中的应用
场景:支付服务异常数达到阈值时熔断
文件路径: mall-microservices/order-service/src/main/java/com/mall/orderservice/config/SentinelConfig.java
// 异常数熔断:10秒内异常数达到5个时熔断 DegradeRule exceptionCountRule = new DegradeRule(); exceptionCountRule.setResource("paymentService:createPayment"); exceptionCountRule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT); exceptionCountRule.setCount(5); // 异常数:5 exceptionCountRule.setTimeWindow(10); // 时间窗口:10秒 exceptionCountRule.setMinRequestAmount(5); // 最小请求数:5 rules.add(exceptionCountRule);
使用场景:
- 适用于请求量较小的场景
- 异常数达到阈值立即熔断
- 比异常比例更敏感
熔断策略
策略说明
熔断策略:
- Open:熔断开启,拒绝请求
- Half-Open:半开状态,尝试恢复
- Close:熔断关闭,正常处理
降级处理
在订单服务中实现降级处理
场景:支付服务不可用时,返回降级响应
文件路径: mall-microservices/order-service/src/main/java/com/mall/orderservice/feign/PaymentServiceClient.java
package com.mall.orderservice.feign; import com.mall.orderservice.common.Result; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @FeignClient( name = "payment-service", fallback = PaymentServiceFallback.class ) public interface PaymentServiceClient { @PostMapping("/api/payments") Result createPayment(@RequestBody PaymentCreateDTO paymentDTO); }
文件路径: mall-microservices/order-service/src/main/java/com/mall/orderservice/feign/PaymentServiceFallback.java
package com.mall.orderservice.feign; import com.mall.orderservice.common.Result; import org.springframework.stereotype.Component; @Component public class PaymentServiceFallback implements PaymentServiceClient { @Override public Result createPayment(PaymentCreateDTO paymentDTO) { // 降级处理:返回错误信息,但不抛出异常 return Result.error("Payment service is temporarily unavailable, please try again later"); } }
使用 @SentinelResource 实现降级
文件路径: mall-microservices/order-service/src/main/java/com/mall/orderservice/service/impl/OrderServiceImpl.java
package com.mall.orderservice.service.impl; import com.alibaba.csp.sentinel.annotation.SentinelResource; import com.alibaba.csp.sentinel.slots.block.BlockException; import com.mall.orderservice.common.Result; import com.mall.orderservice.entity.Order; import com.mall.orderservice.feign.PaymentServiceClient; import com.mall.orderservice.mapper.OrderMapper; import com.mall.orderservice.service.OrderService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService { @Autowired private PaymentServiceClient paymentServiceClient; @Override @Transactional(rollbackFor = Exception.class) @SentinelResource( value = "createOrderWithPayment", blockHandler = "createOrderBlockHandler", fallback = "createOrderFallback" ) public Order createOrder(Order order) { // 1. 创建订单 order.setOrderNo(generateOrderNo()); order.setStatus(0); save(order); // 2. 调用支付服务创建支付订单 PaymentCreateDTO paymentDTO = new PaymentCreateDTO(); paymentDTO.setOrderId(order.getId()); paymentDTO.setAmount(order.getPayAmount()); Result paymentResult = paymentServiceClient.createPayment(paymentDTO); if (paymentResult == null || paymentResult.getCode() != 200) { throw new RuntimeException("Failed to create payment"); } return order; } /** * 限流降级处理 */ public Order createOrderBlockHandler(Order order, BlockException ex) { throw new RuntimeException("Service is busy, please try again later"); } /** * 异常降级处理 */ public Order createOrderFallback(Order order, Throwable ex) { // 降级处理:创建订单但不创建支付订单 // 订单状态设置为"待支付",用户可以稍后支付 order.setOrderNo(generateOrderNo()); order.setStatus(0); // 待支付 save(order); return order; } private String generateOrderNo() { return "ORD" + System.currentTimeMillis() + UUID.randomUUID().toString().substring(0, 8).toUpperCase(); } }
降级处理策略
商城项目中的降级策略:
-
支付服务降级:
- 创建订单成功,但不创建支付订单
- 订单状态为"待支付"
- 用户可以稍后支付
-
用户服务降级:
- 如果用户服务不可用,使用缓存中的用户信息
- 或者返回默认用户信息
-
商品服务降级:
- 如果商品服务不可用,使用订单中的商品信息(冗余字段)
- 或者返回错误,但不影响订单创建流程
测试熔断降级
测试步骤
1. 启动所有服务:
# 启动 Nacos cd mall-microservices/docker/nacos docker-compose -f docker-compose-simple.yml up -d # 启动 Sentinel 控制台 cd mall-microservices/docker/sentinel docker-compose up -d # 启动订单服务 cd mall-microservices/order-service mvn spring-boot:run
2. 模拟支付服务慢响应:
在支付服务中添加延迟:
@PostMapping("/api/payments") public Result createPayment(@RequestBody PaymentCreateDTO paymentDTO) { // 模拟慢响应 try { Thread.sleep(2000); // 延迟2秒 } catch (InterruptedException e) { e.printStackTrace(); } // 正常处理逻辑... }
3. 触发熔断:
- 快速发送多个创建订单请求
- 观察 Sentinel 控制台的熔断规则
- 验证降级处理是否生效
4. 验证降级响应:
- 熔断后,创建订单请求应该返回降级响应
- 订单创建成功,但支付订单创建失败
- 订单状态为"待支付"
官方资源
根据 Sentinel 熔断降级文档 和 Spring Cloud Alibaba Sentinel 集成文档:
-
熔断降级规则:官方文档详细说明了 Sentinel 支持的三种熔断策略:慢调用比例、异常比例、异常数。文档强调,熔断器有三种状态:关闭(Closed)、开启(Open)、半开(Half-Open),并详细说明了状态转换的条件和机制。
-
降级处理:官方文档说明了如何实现降级处理,包括使用
@SentinelResource注解的fallback和blockHandler属性。文档提供了完整的降级处理示例,帮助开发者实现优雅降级。 -
与 Feign 集成:官方文档详细说明了如何将 Sentinel 与 OpenFeign 集成,实现服务调用的熔断降级。文档提供了完整的配置示例,包括如何配置降级类、如何自定义降级逻辑等。
参考资源:
- Sentinel 熔断降级:https://sentinelguard.io/zh-cn/docs/circuit-breaking.html
- Sentinel 与 Feign 集成:https://github.com/alibaba/spring-cloud-alibaba/wiki/Sentinel
本节小结
在本节中,我们学习了熔断降级规则:
第一个是在商城项目中配置熔断降级。 在订单服务中配置了支付服务的熔断规则。
第二个是慢调用比例。 配置了基于慢调用比例的熔断,当支付服务响应慢时触发熔断。
第三个是异常比例。 配置了基于异常比例的熔断,当支付服务异常率高时触发熔断。
第四个是异常数。 配置了基于异常数的熔断,适用于请求量较小的场景。
第五个是降级处理。 实现了完整的降级处理逻辑,包括 Feign Fallback 和 @SentinelResource fallback。
第六个是降级处理策略。 为商城项目设计了合理的降级策略,保证用户体验。
这就是熔断降级规则。通过合理配置熔断降级,可以保护系统免受下游服务故障的影响,提高系统的稳定性和可用性。在下一节,我们将学习系统自适应限流。