7.3 熔断降级:系统崩溃前的紧急逃生通道——让系统学会"装死"的艺术

138 阅读4分钟

《7.3 熔断降级:系统崩溃前的紧急逃生通道——让系统学会"装死"的艺术》


① 熔断降级の人类比喻

graph LR
    A[程序员] -->|连续加班| B(情绪崩溃)
    B -->|触发熔断| C[请假回家]
    C -->|恢复期| D{尝试工作}
    D -->|效率正常| E[继续搬砖]
    D -->|效率低下| C

经典场景
"当你的系统像连续加班三年的程序员,熔断就是强制它休年假,降级就是让它只处理核心需求(比如先别写PPT了)"


② Spring Cloud Alibaba Sentinel实战

代码

// 前置:pom.xml添加依赖
// <dependency>
//     <groupId>com.alibaba.cloud</groupId>
//     <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
//     <version>2021.0.4.0</version>
// </dependency>

@RestController
public class PaymentController {
    
    // 定义支付资源(模拟支付接口)
    @SentinelResource(value = "pay", 
        blockHandler = "blockHandlerForPay", 
        fallback = "fallbackForPay")
    @GetMapping("/pay")
    public String pay(@RequestParam String orderId) {
        // 模拟20%概率失败
        if (Math.random() > 0.8) {
            throw new RuntimeException("银行接口超时");
        }
        return "订单" + orderId + "支付成功";
    }
    
    // 熔断降级处理(参数要和原方法一致)
    public String blockHandlerForPay(String orderId, BlockException ex) {
        return "系统繁忙,请稍后再试(熔断保护中)";
    }
    
    // 业务异常处理
    public String fallbackForPay(String orderId, Throwable t) {
        return "支付失败,已启动托底方案:" + t.getMessage();
    }
}

// 熔断规则配置(可在控制台动态调整)
@PostConstruct
public void initRules() {
    List<FlowRule> rules = new ArrayList<>();
    FlowRule rule = new FlowRule();
    rule.setResource("pay");
    rule.setGrade(RuleConstant.FLOW_GRADE_QPS); // QPS阈值类型
    rule.setCount(100); // 每秒最大100次调用
    rules.add(rule);
    FlowRuleManager.loadRules(rules);
    
    DegradeRule degradeRule = new DegradeRule();
    degradeRule.setResource("pay");
    degradeRule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO); // 异常比例
    degradeRule.setCount(0.5); // 异常比例阈值50%
    degradeRule.setTimeWindow(10); // 熔断时长10秒
    degradeRule.setMinRequestAmount(20); // 最小请求数
    DegradeRuleManager.loadRules(Collections.singletonList(degradeRule));
}

代码彩蛋
启动后访问 http://localhost:8719/ 可进入Sentinel控制台,实时看到如下监控:

{
  "resource": "pay",
  "passQps": 85,
  "blockQps": 15,
  "rt": 230,
  "exceptionCount": 18
}

③ 熔断状态机

stateDiagram-v2
    [*] --> Closed
    Closed --> Open: 失败率超过阈值
    Open --> HalfOpen: 经过熔断时间窗
    HalfOpen --> Closed: 探测请求成功
    HalfOpen --> Open: 探测请求失败

④ 降级策略对比表

策略类型适用场景配置参数示例大厂应用案例
慢调用比例数据库查询类接口RT=500ms, 比例阈值=80%淘宝商品详情页查询
异常比例第三方服务依赖异常比例=50%, 时间窗=10s微信支付接口熔断
异常数硬件故障场景异常数=100次/分钟银行核心交易系统
热点参数高频访问特定数据参数索引=0, QPS=100微博热搜榜接口

⑤ 血泪案例库

案例1:某电商双十一雪崩事故

  • 现象:支付接口响应时间从200ms飙升到8s
  • 数据:订单流失率37%,损失¥2.3亿
  • 尸检报告
    [ERROR] 级联故障链:
    |-- 支付服务超时 → 重试风暴 → DB连接池耗尽
    |-- 风控服务阻塞 → 订单积压 → MQ堆积
    

案例2:社交平台明星官宣事件

  • 措施:提前配置熔断规则
  • 效果
    # 系统指标对比
    峰值QPS: 85万 → 限流到50万
    核心接口可用性: 63% → 99.98%
    服务器成本: 节省40%
    

⑥ 高频面试八连击

  1. 熔断和降级的区别是什么?

    答:熔断是自动故障保护(如保险丝),降级是主动功能裁剪(如关闭非核心服务)。熔断针对服务提供方,降级针对服务消费方。

  2. Sentinel和Hystrix的优劣对比?

    答:Sentinel支持实时规则调整、热点防护、系统自适应保护;Hystrix已停止更新但生态成熟。

  3. 如何设置合理的熔断阈值?

    答:通过压测获取基线数据,通常:

    • 慢调用比例:RT的2倍标准差
    • 异常比例:历史平均值的1.5倍
  4. 熔断恢复机制如何设计?

    答:采用指数退避算法,如初始10秒熔断,后续每次增加50%恢复时间,直到系统稳定。

  5. 如何测试熔断策略?

    答:使用混沌工程工具(如ChaosBlade)模拟超时、异常,验证熔断触发和恢复逻辑。

  6. 微服务中如何全局管理熔断?

    答:通过配置中心(Nacos)动态下发规则,结合Prometheus监控大盘实时调整。

  7. 熔断后的请求怎么处理?

    答:四种策略:快速失败、返回托底数据、排队等待(需配合漏桶算法)、降级到备用服务。

  8. 如何避免无意义的熔断?

    答:设置最小请求数阈值(如至少20次/秒),防止低流量时误触发。


⑦ 灵魂拷问:你的系统需要哪种逃生姿势?

决策树

graph TD
    A[是否核心链路?] -->|是| B{失败类型}
    A -->|否| C[直接降级]
    B -->|临时故障| D[熔断+自动恢复]
    B -->|持久故障| E[降级+人工介入]
    C --> F[返回缓存/默认值]

经典组合

  • 支付系统:熔断(异常比例)+ 降级(切换备用通道)
  • 推荐系统:熔断(慢调用)+ 降级(返回通用推荐)
  • 秒杀系统:熔断(QPS阈值)+ 降级(排队页面)

⑧ 自测实验:制造系统雪崩

步骤

  1. 用JMeter以1000线程压测/pay接口
  2. 观察控制台熔断触发日志:
    [WARN] Degrade rule triggered for resource pay
    |-- exceptionRatio: 62.3%
    |-- request count: 35
    
  3. 正常请求返回:
    {
      "code": 503,
      "msg": "系统繁忙,请稍后再试(熔断保护中)"
    }
    

进阶挑战
调整熔断规则参数,观察系统恢复时间的变化规律


下一讲预告
《7.4 限流算法:从漏桶到令牌桶的江湖恩怨》——手写分布式限流组件,用Guava和Redis分别实现百万级限流,带你破解高并发系统的流量密码!