Auto‑Optimizing Resilience4j Circuit Breaker Settings with Spring AI
This article demonstrates how to replace static Resilience4j circuit‑breaker parameters in a Spring Boot 3.5 application with dynamically generated values using Spring AI, detailing environment setup, code examples, AI prompt construction, and runtime configuration replacement to improve fault tolerance.
1. Introduction
In microservice systems, frequent service failures and timeouts can cause cascading failures. The default static configuration of Resilience4j circuit breakers does not adapt to changing traffic and runtime conditions. This tutorial shows how to integrate Spring AI to automatically analyze runtime metrics and generate optimal circuit‑breaker parameters, achieving adaptive tuning and higher fault‑tolerance.
2. Environment
Spring Boot 3.5.0
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-spring-boot3</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
<version>1.1.2.0</version>
</dependency>Basic YAML configuration:
resilience4j:
circuitbreaker:
instances:
businessService:
registerHealthIndicator: true
slidingWindowSize: 100
minimumNumberOfCalls: 2
failureRateThreshold: 10
waitDurationInOpenState: 10s
permittedNumberOfCallsInHalfOpenState: 3
automaticTransitionFromOpenToHalfOpenEnabled: true
---
spring:
ai:
dashscope:
api-key: ${DASHSCOPE_API_KEY}
base-url: https://dashscope.aliyuncs.com
chat:
options:
stream: true
model: qwen-turbo
temperature: 0.13. Basic circuit‑breaker usage
Service method with @CircuitBreaker annotation:
@CircuitBreaker(name = "businessService", fallbackMethod = "queryFallback")
public String query(Long id) {
System.err.println("Executing business query [%s]".formatted(id));
if (id == 666L) {
throw new RuntimeException("Invalid parameter");
}
return "Apple";
}
public String queryFallback(Throwable e) {
logger.error("Fallback: query error {}", e.getMessage());
return "fallback-query";
}Controller exposing the service:
private final BusinessService businessService;
@GetMapping("/{id}")
public ResponseEntity<String> query(@PathVariable Long id) {
return ResponseEntity.ok(businessService.query(id));
}When the endpoint is called with id = 666, the circuit breaker opens after two failed calls, preventing the actual method execution.
4. AI‑driven dynamic tuning
A scheduled component collects the current circuit‑breaker metrics, builds a prompt for the AI model, receives recommended parameters, and replaces the existing configuration at runtime.
@Component
public class AiControllerResilience {
private static final String CB_NAME = "businessService";
private final CircuitBreakerRegistry circuitBreakerRegistry;
private final ChatClient chatClient;
@Scheduled(fixedRate = 10000)
public void tuneAiCircuitBreaker() throws Exception {
// 1. Get current circuit‑breaker and its metrics
CircuitBreaker cb = circuitBreakerRegistry.circuitBreaker(CB_NAME);
CircuitBreaker.Metrics metrics = cb.getMetrics();
// 2. Build AI prompt with current config and metrics
CircuitBreakerConfig config = cb.getCircuitBreakerConfig();
String prompt = String.format("""
# 1 Analyze Resilience4j service metrics
## 1.1 Current circuit‑breaker config
| Field | Current Value |
| ----- | ------------- |
| slidingWindowSize | %s |
| minimumNumberOfCalls | %s |
| failureRateThreshold | %s |
| waitDurationInOpenState | %s |
| permittedNumberOfCallsInHalfOpenState | %s |
## 1.2 Runtime metrics
%s
# 2 Desired result
Provide a set of optimal parameters (slidingWindowSize, minimumNumberOfCalls, failureRateThreshold, waitDurationInOpenState, permittedNumberOfCallsInHalfOpenState) and a reason if any parameter changes.
""",
config.getSlidingWindowSize(),
config.getMinimumNumberOfCalls(),
config.getFailureRateThreshold(),
config.getWaitIntervalFunctionInOpenState().apply(1),
config.getPermittedNumberOfCallsInHalfOpenState(),
new ObjectMapper().writeValueAsString(metrics));
// 3. Call AI model
AiConfigRecommend recommend = chatClient.prompt().user(prompt).call().entity(AiConfigRecommend.class);
// 4. Build new config
CircuitBreakerConfig newCfg = CircuitBreakerConfig.custom()
.failureRateThreshold(recommend.getFailureRateThreshold())
.slidingWindowSize(recommend.getSlidingWindowSize())
.minimumNumberOfCalls(recommend.getMinimumNumberOfCalls())
.waitDurationInOpenState(Duration.ofMillis(recommend.getWaitDurationInOpenState()))
.permittedNumberOfCallsInHalfOpenState(recommend.getPermittedNumberOfCallsInHalfOpenState())
.build();
// 5. Replace configuration
circuitBreakerRegistry.remove(CB_NAME);
circuitBreakerRegistry.circuitBreaker(CB_NAME, newCfg);
System.err.println("Old config: slidingWindowSize = %s, minimumNumberOfCalls = %s, failureRateThreshold = %s, waitDurationInOpenState = %s, permittedNumberOfCallsInHalfOpenState = %s"
.formatted(config.getSlidingWindowSize(), config.getMinimumNumberOfCalls(), config.getFailureRateThreshold(), config.getWaitIntervalFunctionInOpenState().apply(1), config.getPermittedNumberOfCallsInHalfOpenState()));
System.err.println("New config: slidingWindowSize = %s, minimumNumberOfCalls = %s, failureRateThreshold = %s, waitDurationInOpenState = %s, permittedNumberOfCallsInHalfOpenState = %s, reason = %s"
.formatted(recommend.getSlidingWindowSize(), recommend.getMinimumNumberOfCalls(), recommend.getFailureRateThreshold(), recommend.getWaitDurationInOpenState(), recommend.getPermittedNumberOfCallsInHalfOpenState(), recommend.getReason()));
}
public static class AiConfigRecommend {
private int slidingWindowSize;
private int minimumNumberOfCalls;
private float failureRateThreshold;
private long waitDurationInOpenState;
private int permittedNumberOfCallsInHalfOpenState;
private String reason;
// getters and setters omitted for brevity
}
}5. Result
After restarting the service and invoking the endpoint with both valid and error parameters, the console prints the old and new configuration values, confirming that the circuit‑breaker settings have been updated automatically.
Console example:
Final observation: the businessService circuit‑breaker configuration is now dynamically tuned by AI, eliminating manual parameter adjustments.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
