乐途乐途
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
  • 学习路径
  • 第1章 微服务与 Spring Cloud 概述

    • 微服务与 Spring Cloud 概述
  • 第2章 服务注册与发现

    • Eureka 服务注册与发现
    • Consul 服务注册与发现
  • 第3章 客户端负载均衡

    • Ribbon 客户端负载均衡
    • Spring Cloud LoadBalancer
  • 第4章 声明式服务调用

    • Feign 声明式 HTTP 客户端
    • OpenFeign 高级特性与 Spring Cloud 集成
  • 第5章 服务容错与熔断

    • Resilience4j 服务容错与熔断
    • Sentinel 流量控制与熔断降级
  • 第6章 配置中心

    • Spring Cloud Config 配置中心
  • 第7章 API 网关

    • Spring Cloud Gateway 现代化 API 网关
    • Zuul 网关(已进入维护模式)
  • 第8章 消息驱动的微服务

    • Spring Cloud Stream 消息驱动的微服务
  • 第9章 分布式追踪与监控

    • Sleuth + Zipkin 分布式链路追踪
  • 第10章 最佳实践与面试考点

    • Spring Cloud 最佳实践与面试考点

Resilience4j 服务容错与熔断

导学

2020 年双十一凌晨 2 点,飞翔科技系统告警:支付服务响应变慢,线程池堆积,最终导致整个商城 502。

CTO 大翔事后复盘:"为什么支付服务挂了,连商品浏览都不可用?"

白歌分析道:"订单服务调用支付服务超时后,RestTemplate 会一直等待直到自身线程池耗尽——这就是服务雪崩。我们需要熔断器。"

服务雪崩原理:


定位与问题场景

Resilience4j 是 Netflix Hystrix 的替代品,为 Spring Cloud 提供熔断、限流、重试、隔离四大容错能力:

能力解决的问题
Circuit Breaker(熔断)下游服务异常时快速失败,防止级联故障
Rate Limiter(限流)限制调用频率,防止流量突增压垮下游
Retry(重试)临时故障时自动重试
Bulkhead(隔离)限制并发数,防止单个服务耗尽所有线程
Time Limiter(超时)设置调用超时上限

熔断器核心原理

三态状态机

三态说明:

状态行为触发条件
CLOSED正常调用,统计失败率启动默认状态
OPEN拒绝所有请求,直接抛 CallNotPermittedException滑动窗口内失败率 ≥ failureRateThreshold
HALF_OPEN放行部分请求探测服务是否恢复OPEN 状态持续 waitDurationInOpenState 后

滑动窗口统计

Resilience4j 使用滑动窗口统计最近 N 次调用的成功/失败:


完整示例:飞翔科技订单服务熔断降级

场景描述

订单服务调用支付服务,当支付服务超时或异常时触发熔断,返回降级响应。

操作前后对比:

维度引入 Resilience4j 前引入 Resilience4j 后
支付服务超时订单线程阻塞,级联故障熔断器快速失败,返回降级响应
支付服务恢复人工重启后才能恢复半开状态自动探测恢复
可观测性无熔断状态变更事件 + 指标

步骤一:依赖引入

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

步骤二:基础熔断配置

resilience4j:
  circuitbreaker:
    configs:
      default:
        sliding-window-type: COUNT_BASED    # 基于调用次数统计
        sliding-window-size: 10             # 窗口大小 10 次
        failure-rate-threshold: 50          # 失败率阈值 50%
        wait-duration-in-open-state: 10s    # OPEN 状态等待 10s 后进入 HALF_OPEN
        permitted-number-of-calls-in-half-open-state: 3  # HALF_OPEN 允许 3 次探测
        automatic-transition-from-open-to-half-open-enabled: true
    instances:
      paymentService:
        base-config: default
        minimum-number-of-calls: 5          # 至少 5 次调用后才计算失败率

步骤三:代码实现

@RestController
public class OrderController {
    @Autowired
    private PaymentClient paymentClient;

    @GetMapping("/order/pay/{orderId}")
    // 引入 Resilience4j 前:无保护,支付服务挂了就一起挂
    // public Map<String, Object> pay(@PathVariable String orderId) {
    //     return paymentClient.pay(orderId);
    // }

    // 引入 Resilience4j 后:熔断保护
    @CircuitBreaker(
        name = "paymentService",
        fallbackMethod = "payFallback"
    )
    public Map<String, Object> pay(@PathVariable String orderId) {
        return paymentClient.pay(orderId);
    }

    // 降级方法:必须与原方法相同的参数 + Throwable
    public Map<String, Object> payFallback(String orderId, Throwable e) {
        log.warn("支付服务熔断降级,orderId={},原因:{}", orderId, e.getMessage());
        return Map.of(
            "orderId", orderId,
            "status", "PENDING",
            "message", "支付服务繁忙,订单已暂存,稍后自动重试"
        );
    }
}

步骤四:声明式集成(Feign + CircuitBreaker)

@FeignClient(
    name = "FEIXIANG-PAYMENT-SERVICE",
    fallbackFactory = PaymentClientFallbackFactory.class
)
public interface PaymentClient {
    @PostMapping("/payments")
    Map<String, Object> pay(@RequestBody PaymentRequest request);
}

@Component
@Slf4j
public class PaymentClientFallbackFactory implements FallbackFactory<PaymentClient> {
    @Override
    public PaymentClient create(Throwable cause) {
        if (cause instanceof CallNotPermittedException) {
            log.error("支付服务熔断器 OPEN!");
        }
        return request -> Map.of(
            "status", "FALLBACK",
            "message", "支付服务暂时不可用:" + cause.getMessage()
        );
    }
}

步骤五:熔断器事件监听

@Component
public class CircuitBreakerEventListener {
    @EventListener
    public void onStateTransition(CircuitBreakerOnStateTransitionEvent event) {
        log.warn("熔断器 [{}] 状态变更:{} → {}",
            event.getCircuitBreakerName(),
            event.getStateTransition().getFromState(),
            event.getStateTransition().getToState()
        );
    }
}

其他 Resilience4j 模块

Retry(重试)

resilience4j:
  retry:
    instances:
      paymentRetry:
        max-attempts: 3
        wait-duration: 500ms
        retry-exceptions:
          - java.net.SocketTimeoutException
@Retry(name = "paymentRetry", fallbackMethod = "payFallback")
public Map<String, Object> pay(String orderId) {
    return paymentClient.pay(orderId);
}

Bulkhead(舱壁隔离)

resilience4j:
  bulkhead:
    instances:
      paymentBulkhead:
        max-concurrent-calls: 10       # 最多 10 个并发
        max-wait-duration: 500ms       # 等待队列超时

信号量隔离 vs 线程池隔离:Resilience4j 默认使用信号量隔离,不创建额外线程。

TimeLimiter(超时控制)

resilience4j:
  timelimiter:
    instances:
      paymentTimeLimiter:
        timeout-duration: 3s

易错场景

1. fallback 方法签名不匹配

// ❌ 错误:缺少 Throwable 参数
public Map<String, Object> payFallback(String orderId) { ... }

// ✅ 正确:参数类型、顺序、数量完全一致 + Throwable
public Map<String, Object> payFallback(String orderId, Throwable e) { ... }

2. 熔断器配置名称与 @CircuitBreaker name 不一致

// @CircuitBreaker(name = "paymentService")  ← 此处
// resilience4j.circuitbreaker.instances.paymentService: ← 必须与此处一致

3. 同一方法多个 Resilience4j 注解顺序问题

// Resilience4j 按注解声明顺序执行
// 推荐顺序:Bulkhead → TimeLimiter → CircuitBreaker → Retry
@Bulkhead(name = "...")
@CircuitBreaker(name = "...")
@Retry(name = "...")
public Map<String, Object> pay(String orderId) { ... }

4. 将业务异常统计为熔断失败

默认所有异常(包括 IllegalArgumentException)都被计入失败统计。应配置 ignoreExceptions:

resilience4j:
  circuitbreaker:
    instances:
      paymentService:
        ignore-exceptions:
          - com.feixiang.exception.BusinessException

面试考点

Resilience4j 三种状态及转换条件?

CLOSED(正常放行,统计失败率)→ 失败率超过阈值 → OPEN(快速失败,拒绝请求)→ 等待时间过后 → HALF_OPEN(放行少量请求探测)→ 探测成功回到 CLOSED,探测失败回到 OPEN。

服务雪崩如何防止?

三层防护:

  1. 熔断(Circuit Breaker):下游故障时快速失败,防止线程阻塞
  2. 舱壁(Bulkhead):隔离不同服务的线程资源,防止一个服务耗尽所有线程
  3. 降级(Fallback):返回兜底响应,保证用户体验不中断

Resilience4j 和 Hystrix 的区别?

HystrixResilience4j
已停止维护活跃维护
强制线程池隔离信号量隔离(轻量)
架构较重函数式,轻量,无外部依赖
通过 Archaius 配置原生 Spring 配置
仅支持熔断+隔离熔断+限流+重试+隔离+超时

小结

Resilience4j 通过熔断器三态状态机阻止了故障的级联传播,配合重试、限流、舱壁隔离,构成了微服务的多层容错体系。下一节我们看来自阿里巴巴的 Sentinel,它在限流和流量整形方面有更强的表现。

下一页
Sentinel 流量控制与熔断降级