Spring Cloud Circuit Breaker:断路器模式

1 概述

断路器模式是分布式系统中关键的容错设计模式,用于防止服务故障的连锁反应(雪崩效应)。其核心思想是监控服务调用的健康状态,并在检测到故障时快速失败,而非继续尝试可能失败的操作。断路器有三种状态:关闭(Closed)、开启(Open)和半开(Half-Open)。


1.1 状态

  • 关闭(Closed):正常状态,允许请求通过,统计成功/失败率;
  • 开启(Open):熔断状态,拒绝所有请求,直接执行fallback;
  • 半开(Half-Open):探测状态,允许少量请求通过,验证服务是否恢复。

在关闭状态,断路器允许请求正常通过;当失败率超过阈值时,断路器开启,快速拒绝请求;经过一段时间后,断路器进入半开状态,允许部分请求通过以探测服务是否恢复。这种状态转换机制有效平衡了系统可用性和故障隔离。


1.2 核心抽象类

核心抽象类包括CircuitBreakerFactory和ReactiveCircuitBreakerFactory,分别用于同步和响应式编程模型。

特性 CircuitBreakerFactory ReactiveCircuitBreakerFactory
适用场景 同步/阻塞式应用(Servlet 栈) 响应式/非阻塞应用(WebFlux、Gateway)
返回类型 CircuitBreaker ReactiveCircuitBreaker
执行模型 阻塞式调用(Thread-per-request) 非阻塞式(Reactor 模型)
调用方式 run(Supplier<T>, Function<Throwable, T>) run(Mono<T>/Flux<T>, Function<Throwable, Mono<T>/Flux<T>>)
典型技术栈 Spring MVC + RestTemplate/Feign Spring WebFlux + WebClient / Spring Cloud Gateway
底层实现 Resilience4JCircuitBreakerFactory ReactiveResilience4JCircuitBreakerFactory

2 响应式模型断路器示例

2.1 依赖配置

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

2.2 参数配置

方式一:yaml配置

resilience4j:
  circuitbreaker:
    instances:
      conditionalServiceBreaker:  # 与代码中CIRCUIT_BREAKER_NAME一致
        failure-rate-threshold: 50        # 失败率阈值(%)
        wait-duration-in-open-state: 10s  # OPEN状态持续时间
        permitted-number-of-calls-in-half-open-state: 3
        sliding-window-size: 10           # 滑动窗口请求数
        sliding-window-type: COUNT_BASED  # COUNT_BASED/COUNT_BASED
        automatic-transition-from-open-to-half-open-enabled: true
  timelimiter:
    instances:
      conditionalServiceBreaker:
        timeout-duration: 3s              # 超时时间

方式二:
使用配置类

@Configuration
public class CustomizeCircuitBreakerConfig {

    @Bean
    public ReactiveResilience4JCircuitBreakerFactory defaultCustomizer() {

        CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom() //
                .slidingWindowType(CircuitBreakerConfig.SlidingWindowType.TIME_BASED) // 滑动窗口的类型为时间窗口
                .slidingWindowSize(10) // 时间窗口的大小为60秒
                .minimumNumberOfCalls(5) // 在单位时间窗口内最少需要5次调用才能开始进行统计计算
                .failureRateThreshold(50) // 在单位时间窗口内调用失败率达到50%后会启动断路器
                .enableAutomaticTransitionFromOpenToHalfOpen() // 允许断路器自动由打开状态转换为半开状态
                .permittedNumberOfCallsInHalfOpenState(5) // 在半开状态下允许进行正常调用的次数
                .waitDurationInOpenState(Duration.ofSeconds(5)) // 断路器打开状态转换为半开状态需要等待60秒
                .recordExceptions(Throwable.class) // 所有异常都当作失败来处理
                .build();

        ReactiveResilience4JCircuitBreakerFactory factory = new ReactiveResilience4JCircuitBreakerFactory();
        factory.configureDefault(id -> new Resilience4JConfigBuilder(id)
                .timeLimiterConfig(TimeLimiterConfig.custom().timeoutDuration(Duration.ofMillis(200)).build())
                .circuitBreakerConfig(circuitBreakerConfig).build());

        return factory;
    }
}

2.3 断路器过滤器

动态判断请求特征并条件化应用断路器。

@Component
@Order(-100) // 高优先级,确保在路由过滤器前执行
public class ConditionalCircuitBreakerFilter implements GlobalFilter {

    private final ReactiveCircuitBreakerFactory circuitBreakerFactory;
    private static final String CIRCUIT_BREAKER_NAME = "conditionalServiceBreaker";
    private static final String TRIGGER_HEADER = "X-Enable-CircuitBreaker"; // 可替换为其他attribute判断逻辑

    public ConditionalCircuitBreakerFilter(ReactiveCircuitBreakerFactory circuitBreakerFactory) {
        this.circuitBreakerFactory = circuitBreakerFactory;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // === 条件判断逻辑(可根据需求扩展)===
        boolean shouldApplyCircuitBreaker = shouldApplyBreaker(exchange);
        
        if (shouldApplyCircuitBreaker) {
            ReactiveCircuitBreaker circuitBreaker = circuitBreakerFactory.create(CIRCUIT_BREAKER_NAME);
            
            return circuitBreaker.run(
                // 包装整个后续过滤器链(含路由、负载均衡、下游调用)
                chain.filter(exchange).then(Mono.empty()),
                // Fallback逻辑:断路器打开或调用失败时执行
                throwable -> handleFallback(exchange, throwable)
            ).then();
        }
        // 不满足条件:直接放行,不经过断路器
        return chain.filter(exchange);
    }

    /**
     * 条件判断扩展点(按需修改)
     */
    private boolean shouldApplyBreaker(ServerWebExchange exchange) {
        // 方案1:检查请求头
        String headerVal = exchange.getRequest().getHeaders().getFirst(TRIGGER_HEADER);
        if ("true".equalsIgnoreCase(headerVal)) return true;
        
        // 方案2:检查请求参数(示例)
        // String param = exchange.getRequest().getQueryParams().getFirst("use_circuit");
        // if ("1".equals(param)) return true;
        
        // 方案3:检查自定义attribute(需前置过滤器设置)
        // Boolean attr = exchange.getAttribute("custom.circuit.trigger");
        // return attr != null && attr;
        
        return false;
    }

    /**
     * Fallback处理(可扩展为转发到/fallback路径)
     */
    private Mono<Void> handleFallback(ServerWebExchange exchange, Throwable throwable) {
        ServerHttpResponse response = exchange.getResponse();
        response.setStatusCode(HttpStatus.SERVICE_UNAVAILABLE);
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
        
        String body = String.format(
            "{\"error\":\"CIRCUIT_BREAKER_OPEN\",\"message\":\"Service protected by circuit breaker\",\"trigger\":\"%s\"}",
            TRIGGER_HEADER
        );
        
        DataBuffer buffer = response.bufferFactory()
            .wrap(body.getBytes(StandardCharsets.UTF_8));
        return response.writeWith(Mono.just(buffer));
    }
}
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐