spring-cloud-circuitbreaker
Spring Cloud Circuit BreakerとResilience4jを使用したレジリエンスパターンについて説明します。サーキットブレーカー、リトライ、レート制限、バルクヘッド、フォールバックパターンをカバーしています。 以下の場合に使用してください:ユーザーが「circuit breaker」「resilience4j」「fallback」「retry pattern」「rate limiter」「bulkhead」「fault tolerance Spring」について言及している場合。 以下の場合は使用しないでください:基本的なHTTPエラー(コード内で処理)、Hystrix(非推奨)はResilience4jを代わりに使用してください。
description の原文を見る
Resilience patterns with Spring Cloud Circuit Breaker and Resilience4j. Covers circuit breaker, retry, rate limiter, bulkhead, and fallback patterns. USE WHEN: user mentions "circuit breaker", "resilience4j", "fallback", "retry pattern", "rate limiter", "bulkhead", "fault tolerance Spring" DO NOT USE FOR: basic HTTP errors - handle in code, Hystrix (deprecated) - use Resilience4j instead
SKILL.md 本文
Spring Cloud Circuit Breaker - クイックリファレンス
詳細情報:
mcp__documentation__fetch_docsを technology:spring-cloud-circuitbreakerで使用して、包括的なドキュメントを取得してください。
依存関係
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
</dependency>
<!-- リアクティブの場合 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId>
</dependency>
サーキットブレーカーの状態
┌─────────────────────────────────────┐
│ │
▼ │
┌─────────┐ failure threshold ┌──────────┐
│ CLOSED │ ──────────────────────▶ │ OPEN │
│(通常) │ │(拒否中) │
└─────────┘ └──────────┘
▲ │
│ │
│ 待機時間が経過 │
│ ▼
│ ┌───────────┐
└────── 成功 ──────────────────│HALF_OPEN │
│ (テスト中) │
└───────────┘
基本設定
application.yml
resilience4j:
circuitbreaker:
configs:
default:
sliding-window-size: 10
sliding-window-type: COUNT_BASED
failure-rate-threshold: 50
slow-call-rate-threshold: 100
slow-call-duration-threshold: 2s
permitted-number-of-calls-in-half-open-state: 3
wait-duration-in-open-state: 10s
automatic-transition-from-open-to-half-open-enabled: true
record-exceptions:
- java.io.IOException
- java.net.SocketTimeoutException
ignore-exceptions:
- com.example.BusinessException
instances:
user-service:
base-config: default
failure-rate-threshold: 30
wait-duration-in-open-state: 5s
payment-service:
base-config: default
failure-rate-threshold: 20
slow-call-duration-threshold: 1s
retry:
configs:
default:
max-attempts: 3
wait-duration: 500ms
retry-exceptions:
- java.io.IOException
ignore-exceptions:
- com.example.BusinessException
instances:
user-service:
base-config: default
max-attempts: 5
timelimiter:
configs:
default:
timeout-duration: 3s
cancel-running-future: true
instances:
user-service:
timeout-duration: 5s
bulkhead:
configs:
default:
max-concurrent-calls: 25
max-wait-duration: 0
instances:
user-service:
max-concurrent-calls: 10
ratelimiter:
configs:
default:
limit-for-period: 100
limit-refresh-period: 1s
timeout-duration: 0
instances:
api-calls:
limit-for-period: 50
limit-refresh-period: 1s
プログラマティックな使用方法
CircuitBreakerFactory
@Service
@RequiredArgsConstructor
public class UserService {
private final CircuitBreakerFactory circuitBreakerFactory;
private final UserClient userClient;
public User getUser(Long id) {
CircuitBreaker circuitBreaker = circuitBreakerFactory.create("user-service");
return circuitBreaker.run(
() -> userClient.getUserById(id),
throwable -> getDefaultUser(id, throwable)
);
}
private User getDefaultUser(Long id, Throwable throwable) {
log.warn("Fallback for user {}: {}", id, throwable.getMessage());
return User.builder()
.id(id)
.name("Unknown")
.status("FALLBACK")
.build();
}
}
リアクティブ
@Service
public class ReactiveUserService {
private final ReactiveCircuitBreakerFactory circuitBreakerFactory;
private final WebClient webClient;
public Mono<User> getUser(Long id) {
ReactiveCircuitBreaker circuitBreaker = circuitBreakerFactory.create("user-service");
return circuitBreaker.run(
webClient.get()
.uri("/users/{id}", id)
.retrieve()
.bodyToMono(User.class),
throwable -> Mono.just(User.fallback(id))
);
}
}
アノテーションベース
@CircuitBreaker
@Service
public class PaymentService {
@CircuitBreaker(name = "payment-service", fallbackMethod = "paymentFallback")
public PaymentResult processPayment(PaymentRequest request) {
return paymentClient.process(request);
}
private PaymentResult paymentFallback(PaymentRequest request, Throwable t) {
log.error("Payment failed for order {}: {}", request.getOrderId(), t.getMessage());
return PaymentResult.builder()
.status("PENDING")
.message("Payment service unavailable, will retry later")
.build();
}
}
@Retry
@Service
public class NotificationService {
@Retry(name = "notification-service", fallbackMethod = "notifyFallback")
public void sendNotification(Notification notification) {
notificationClient.send(notification);
}
private void notifyFallback(Notification notification, Throwable t) {
log.warn("Failed to send notification, queueing for retry: {}", t.getMessage());
retryQueue.add(notification);
}
}
@RateLimiter
@Service
public class ApiService {
@RateLimiter(name = "api-calls", fallbackMethod = "rateLimitFallback")
public ApiResponse callExternalApi(ApiRequest request) {
return externalClient.call(request);
}
private ApiResponse rateLimitFallback(ApiRequest request, Throwable t) {
throw new TooManyRequestsException("Rate limit exceeded");
}
}
@Bulkhead
@Service
public class ReportService {
@Bulkhead(name = "report-service", type = Bulkhead.Type.THREADPOOL)
public CompletableFuture<Report> generateReport(ReportRequest request) {
return CompletableFuture.supplyAsync(() -> reportGenerator.generate(request));
}
}
@TimeLimiter
@Service
public class SlowService {
@TimeLimiter(name = "slow-service", fallbackMethod = "timeoutFallback")
public CompletableFuture<Result> slowOperation() {
return CompletableFuture.supplyAsync(() -> {
// 遅い可能性がある処理
return performSlowOperation();
});
}
private CompletableFuture<Result> timeoutFallback(Throwable t) {
return CompletableFuture.completedFuture(Result.timeout());
}
}
複合アノテーション
@Service
public class ResilientService {
@CircuitBreaker(name = "backend", fallbackMethod = "fallback")
@Retry(name = "backend")
@RateLimiter(name = "backend")
@Bulkhead(name = "backend")
@TimeLimiter(name = "backend")
public CompletableFuture<Response> resilientCall(Request request) {
return CompletableFuture.supplyAsync(() -> backendClient.call(request));
}
private CompletableFuture<Response> fallback(Request request, Throwable t) {
log.error("All resilience measures failed: {}", t.getMessage());
return CompletableFuture.completedFuture(Response.error());
}
}
カスタマイズ
カスタムサーキットブレーカー設定
@Configuration
public class CircuitBreakerConfig {
@Bean
public Customizer<Resilience4JCircuitBreakerFactory> defaultCustomizer() {
return factory -> factory.configureDefault(id ->
new Resilience4JConfigBuilder(id)
.circuitBreakerConfig(CircuitBreakerConfig.custom()
.slidingWindowSize(10)
.failureRateThreshold(50)
.waitDurationInOpenState(Duration.ofSeconds(10))
.permittedNumberOfCallsInHalfOpenState(3)
.build())
.timeLimiterConfig(TimeLimiterConfig.custom()
.timeoutDuration(Duration.ofSeconds(3))
.build())
.build());
}
@Bean
public Customizer<Resilience4JCircuitBreakerFactory> specificCustomizer() {
return factory -> factory.configure(builder ->
builder.circuitBreakerConfig(CircuitBreakerConfig.custom()
.failureRateThreshold(25)
.build()),
"payment-service", "critical-service");
}
}
イベントリスナー
@Component
public class CircuitBreakerEventListener {
@Autowired
private CircuitBreakerRegistry circuitBreakerRegistry;
@PostConstruct
public void init() {
circuitBreakerRegistry.getAllCircuitBreakers().forEach(cb -> {
cb.getEventPublisher()
.onStateTransition(event ->
log.info("Circuit breaker {} state changed: {} -> {}",
event.getCircuitBreakerName(),
event.getStateTransition().getFromState(),
event.getStateTransition().getToState()))
.onFailureRateExceeded(event ->
log.warn("Circuit breaker {} failure rate exceeded: {}%",
event.getCircuitBreakerName(),
event.getFailureRate()))
.onSlowCallRateExceeded(event ->
log.warn("Circuit breaker {} slow call rate exceeded: {}%",
event.getCircuitBreakerName(),
event.getSlowCallRate()));
});
}
}
メトリクスとモニタリング
Actuator エンドポイント
management:
endpoints:
web:
exposure:
include: health,circuitbreakers,retries,ratelimiters,bulkheads
health:
circuitbreakers:
enabled: true
ratelimiters:
enabled: true
# サーキットブレーカーの状態
GET /actuator/circuitbreakers
# 特定のサーキットブレーカー
GET /actuator/circuitbreakers/{name}
# サーキットブレーカーイベント
GET /actuator/circuitbreakerevents
# 詳細を含むヘルスチェック
GET /actuator/health
メトリクス(Prometheus)
management:
metrics:
tags:
application: ${spring.application.name}
export:
prometheus:
enabled: true
主要なメトリクス:
resilience4j_circuitbreaker_stateresilience4j_circuitbreaker_calls_totalresilience4j_circuitbreaker_failure_rateresilience4j_retry_calls_totalresilience4j_ratelimiter_available_permissionsresilience4j_bulkhead_available_concurrent_calls
Spring Cloud Gateway との統合
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://USER-SERVICE
predicates:
- Path=/api/users/**
filters:
- name: CircuitBreaker
args:
name: userServiceCB
fallbackUri: forward:/fallback/users
- name: Retry
args:
retries: 3
statuses: BAD_GATEWAY,SERVICE_UNAVAILABLE
ベストプラクティス
| すること | しないこと |
|---|---|
| 適切なしきい値を設定する | 本番環境でデフォルトを使用する |
| 意味のあるフォールバックを実装する | フォールバックでエラーを返す |
| サーキットブレーカーの状態を監視する | 状態遷移を無視する |
| リソース分離にバルクヘッドを使用する | 1つのサービスがリソースを枯渇させる |
| バックオフ付きでリトライを設定する | 無期限にリトライする |
本番環境チェックリスト
- サービスごとにサーキットブレーカーが設定されている
- フォールバックが意味のある応答を返す
- メトリクスがモニタリングに公開されている
- 状態遷移でアラートが発火する
- 適切なタイムアウト値が設定されている
- 指数バックオフ付きのリトライが実装されている
- 外部 API に対するレート制限が設定されている
- リソース分離のためのバルクヘッドが設定されている
- ヘルスインジケータが有効になっている
- デバッグ用にイベントがログに記録されている
このスキルを使用しない場合
- 内部エラー - バグを修正する。サーキットブレーカーを使用しない
- Hystrix - 廃止予定。Resilience4j を使用してください
- データベース障害 - コネクションプール、リトライを使用してください
- 単純なリトライ - Spring Retry で十分な場合があります
アンチパターン
| アンチパターン | 問題 | 解決策 |
|---|---|---|
| すべてにサーキットブレーカーを適用 | オーバーヘッド、複雑さ | 外部/不安定な呼び出しのみに適用 |
| フォールバックが定義されていない | 空の応答 | 意味のあるフォールバックを提供する |
| 間違ったしきい値 | サーキットが早期/遅期に開く | SLA に基づいてチューニング |
| モニタリングがない | 問題をデバッグできない | Actuator メトリクスを有効にする |
| 遅い呼び出しを無視 | タイムアウトが設定されない | タイムアウト設定を追加する |
クイックトラブルシューティング
| 問題 | 診断 | 修正 |
|---|---|---|
| サーキットが常に開いている | 失敗率を確認 | しきい値をチューニング、根本的な問題を修正 |
| フォールバックが呼ばれない | 例外の種類を確認 | 正しい例外処理を設定 |
| リトライが多すぎる | リトライ設定を確認 | 最大試行回数を削減 |
| レート制限が厳しすぎる | パーミッション/秒を確認 | リミットを増加 |
| バルクヘッドが拒否 | 同時呼び出しを確認 | 最大同時実行数を増加 |
リファレンスドキュメント
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- d-subrahmanyam
- ライセンス
- MIT
- 最終更新
- 2026/3/24
Source: https://github.com/d-subrahmanyam/deno-fresh-microservices / ライセンス: MIT