一、为什么需要熔断降级

想象一下,你正在经营一家网红奶茶店。突然有一天,某个爆款原料供应商的系统崩溃了,导致所有分店都无法制作这款奶茶。如果没有应急方案,顾客的订单会不断堆积,最终整个系统崩溃。

在微服务架构中,这种情况更加常见。某个服务出现故障,调用它的服务可能会因为等待超时而耗尽资源,引发雪崩效应。这时候,熔断降级机制就像是电路中的保险丝,在故障发生时快速切断请求,避免连锁反应。

二、熔断降级的核心概念

熔断(Circuit Breaker)和降级(Fallback)是两种常见的服务保护策略:

  • 熔断:当服务调用失败率达到阈值时,自动切断请求,直接返回错误或执行备用逻辑。
  • 降级:在服务不可用或超时时,返回一个预设的兜底结果,保证核心流程可用。

比如,电商系统中的商品详情页依赖库存服务。如果库存服务挂了,我们可以展示"库存查询中"的提示,而不是让整个页面卡死。

三、Sentinel vs Resilience4j

目前主流的熔断降级框架有两个:

  1. Sentinel(阿里开源)

    • 优势:功能丰富,支持流量控制、熔断、系统保护
    • 缺点:配置略复杂,社区文档以中文为主
  2. Resilience4j(Netflix Hystrix的替代品)

    • 优势:轻量级,函数式编程风格
    • 缺点:需要手动集成,功能相对单一

下面我们分别用Java技术栈展示它们的用法。

四、Sentinel实战示例

假设我们有一个订单服务需要调用支付服务:

// 1. 定义资源(使用Sentinel注解)
@SentinelResource(
    value = "createOrder", 
    blockHandler = "handleBlock",  // 熔断处理
    fallback = "createOrderFallback" // 降级处理
)
public Order createOrder(OrderRequest request) {
    // 调用支付服务
    PaymentResult result = paymentService.charge(request);
    return convertToOrder(result);
}

// 2. 熔断处理逻辑(参数需与原方法一致,最后加BlockException参数)
public Order handleBlock(OrderRequest request, BlockException ex) {
    log.warn("触发熔断,订单创建被限制", ex);
    return Order.failOrder("系统繁忙,请稍后重试");
}

// 3. 降级处理逻辑(参数需与原方法一致,可加Throwable参数)
public Order createOrderFallback(OrderRequest request, Throwable t) {
    log.error("订单服务降级", t);
    return Order.failOrder("支付系统暂时不可用");
}

然后在配置文件中设置熔断规则:

spring:
  cloud:
    sentinel:
      datasource:
        ds1:
          nacos:
            server-addr: localhost:8848
            dataId: sentinel-rules
            rule-type: flow

五、Resilience4j实战示例

同样的场景,用Resilience4j实现:

// 1. 定义熔断器配置
CircuitBreakerConfig config = CircuitBreakerConfig.custom()
    .failureRateThreshold(50) // 失败率阈值50%
    .waitDurationInOpenState(Duration.ofMillis(1000)) // 熔断后1秒进入半开状态
    .slidingWindowType(SlidingWindowType.COUNT_BASED) // 基于计数的滑动窗口
    .slidingWindowSize(10) // 窗口大小10个请求
    .build();

// 2. 创建熔断器实例
CircuitBreaker circuitBreaker = CircuitBreaker.of("paymentService", config);

// 3. 使用熔断器包装方法
Supplier<OrderResult> decoratedSupplier = CircuitBreaker
    .decorateSupplier(circuitBreaker, () -> paymentService.charge(request));

// 4. 添加降级处理
Try<OrderResult> result = Try.of(decoratedSupplier::get)
    .recover(throwable -> {
        log.error("支付服务调用失败", throwable);
        return OrderResult.fallback("支付服务暂不可用");
    });

六、技术选型建议

根据实际场景选择:

  • 需要全面防护(限流+熔断+降级) → Sentinel
  • 只需要轻量级熔断 → Resilience4j
  • Spring Cloud Alibaba生态 → Sentinel
  • Spring Boot原生集成 → Resilience4j

七、注意事项

  1. 熔断阈值设置:太敏感会导致误熔断,太宽松会失去保护作用
  2. 降级逻辑设计:避免降级方法本身又依赖其他服务
  3. 监控报警:熔断事件需要及时通知运维人员
  4. 半开状态处理:允许少量请求试探服务是否恢复

八、总结

熔断降级是微服务稳定性的重要保障。通过Sentinel或Resilience4j,我们可以像给电路安装保险丝一样,为系统建立自动防护机制。关键是要根据业务特点选择合适的策略,并持续监控调整参数。记住,没有万能的配置模板,只有最适合业务场景的解决方案。