← 返回首页

Java熔断器模式详解

📂 java ⏱ 3 min 546 words

Java熔断器模式详解

什么是熔断器

熔断器(Circuit Breaker)是一种保护机制,当下游服务出现问题时,快速失败并返回降级响应,避免级联故障。

熔断器状态

关闭(CLOSED) ──失败率超阈值──→ 打开(OPEN)
                                ↓ 等待超时
                            半开(HALF_OPEN)
                           ↓        ↓
                    成功→CLOSED  失败→OPEN
public class CircuitBreakerDemo {
    private enum State { CLOSED, OPEN, HALF_OPEN }

    private State state = State.CLOSED;
    private int failureCount = 0;
    private int successCount = 0;
    private final int failureThreshold = 5;
    private final long openTimeout = 5000;
    private long lastFailureTime = 0;

    public String call() {
        if (state == State.OPEN) {
            if (System.currentTimeMillis() - lastFailureTime > openTimeout) {
                state = State.HALF_OPEN;
            } else {
                throw new RuntimeException("熔断器打开,快速失败");
            }
        }

        try {
            String result = doCall();
            onSuccess();
            return result;
        } catch (Exception e) {
            onFailure();
            throw e;
        }
    }

    private void onSuccess() {
        if (state == State.HALF_OPEN) {
            state = State.CLOSED;
        }
        failureCount = 0;
        successCount++;
    }

    private void onFailure() {
        failureCount++;
        lastFailureTime = System.currentTimeMillis();
        if (failureCount >= failureThreshold) {
            state = State.OPEN;
        }
    }
}

Resilience4j

依赖配置

<dependency>
    <groupId>io.github.resilience4j</groupId>
    <artifactId>resilience4j-spring-boot3</artifactId>
    <version>2.1.0</version>
</dependency>

基本配置

resilience4j:
  circuitbreaker:
    instances:
      userService:
        slidingWindowSize: 10
        failureRateThreshold: 50
        waitDurationInOpenState: 10s
        permittedNumberOfCallsInHalfOpenState: 3
        slidingWindowType: TIME_BASED
        minimumNumberOfCalls: 5

  retry:
    instances:
      userService:
        maxAttempts: 3
        waitDuration: 500ms
        enableExponentialBackoff: true
        exponentialBackoffMultiplier: 2
        retryExceptions:
          - java.io.IOException
          - java.util.concurrent.TimeoutException

  ratelimiter:
    instances:
      userService:
        limitForPeriod: 10
        limitRefreshPeriod: 1s
        timeoutDuration: 0

  timelimiter:
    instances:
      userService:
        timeoutDuration: 3s

注解使用

@Service
public class UserServiceWithResilience4j {
    @CircuitBreaker(name = "userService", fallbackMethod = "getUserFallback")
    public User getUser(Long id) {
        return restTemplate.getForObject(
            "http://user-service/api/users/" + id, User.class);
    }

    public User getUserFallback(Long id, Exception e) {
        log.warn("获取用户失败,使用降级数据: {}", e.getMessage());
        return new User(id, "默认用户", "降级数据");
    }

    @Retry(name = "userService", fallbackMethod = "retryFallback")
    public String fetchData(String url) {
        return restTemplate.getForObject(url, String.class);
    }

    public String retryFallback(String url, Exception e) {
        return "降级数据";
    }

    @RateLimiter(name = "userService")
    public void rateLimitedOperation() {
        System.out.println("限流保护的操作");
    }

    @TimeLimiter(name = "userService")
    public CompletableFuture<User> timeoutOperation(Long id) {
        return CompletableFuture.supplyAsync(() ->
            restTemplate.getForObject(
                "http://user-service/api/users/" + id, User.class)
        );
    }
}

组合使用

@Service
public class CompositeResilience {
    // 熔断 + 重试 + 限流 + 超时
    @CircuitBreaker(name = "userService", fallbackMethod = "fallback")
    @Retry(name = "userService")
    @RateLimiter(name = "userService")
    @TimeLimiter(name = "userService")
    public CompletableFuture<User> getUser(Long id) {
        return CompletableFuture.supplyAsync(() ->
            restTemplate.getForObject(
                "http://user-service/api/users/" + id, User.class)
        );
    }

    public CompletableFuture<User> fallback(Long id, Exception e) {
        return CompletableFuture.completedFuture(
            new User(id, "默认用户", "降级数据")
        );
    }
}

事件监听

@Component
public class CircuitBreakerEventListener {
    @EventListener
    public void onCircuitBreakerEvent(CircuitBreakerOnStateChangeEvent event) {
        log.info("熔断器状态变更: {} -> {}",
            event.getStateTransition().getFromState(),
            event.getStateTransition().getToState());
    }

    @EventListener
    public void onCircuitBreakerError(CircuitBreakerOnErrorEvent event) {
        log.warn("熔断器错误: {}", event.getThrowable().getMessage());
    }

    @EventListener
    public void onCircuitBreakerSuccess(CircuitBreakerOnSuccessEvent event) {
        log.info("熔断器调用成功");
    }
}

降级策略

@Component
public class FallbackStrategy {
    // 缓存降级
    public User getUserWithCache(Long id) {
        try {
            User user = callRemoteService(id);
            cache.put(id, user);
            return user;
        } catch (Exception e) {
            User cached = cache.get(id);
            if (cached != null) {
                return cached;
            }
            return getDefaultUser(id);
        }
    }

    // 默认值降级
    public User getDefaultUser(Long id) {
        User user = new User();
        user.setId(id);
        user.setName("默认用户");
        user.setStatus("服务暂时不可用");
        return user;
    }

    // 兜底接口降级
    public User getUserFromFallbackService(Long id) {
        try {
            return fallbackService.getUser(id);
        } catch (Exception e) {
            return getDefaultUser(id);
        }
    }
}

监控面板

@Configuration
public class Resilience4jActuatorConfig {
    @Bean
    public HealthIndicator circuitBreakerHealthIndicator(
            CircuitBreakerRegistry registry) {
        return new CircuitBreakerHealthIndicator(registry);
    }
}

// 访问 /actuator/health 查看健康状态
// 访问 /actuator/circuitbreakers 查看所有熔断器状态

最佳实践

// 1. 合理设置阈值
// 关键服务:failureRateThreshold=50, slidingWindowSize=10
// 非关键服务:failureRateThreshold=30, slidingWindowSize=5

// 2. 降级策略要具体
// 数据查询:返回缓存数据
// 操作类:返回操作失败提示
// 通知类:异步重试

// 3. 监控告警
@Component
public class CircuitBreakerAlert {
    @EventListener
    public void onStateChange(CircuitBreakerOnStateChangeEvent event) {
        if (event.getStateTransition().getToState() == State.OPEN) {
            alertService.sendAlert(
                "熔断器打开: " + event.getName());
        }
    }
}

总结

熔断器是微服务架构中保护系统稳定性的重要组件。Resilience4j提供了熔断、重试、限流、超时等完整的弹性能力。合理配置阈值和降级策略,可以有效防止级联故障。