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.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Auto‑Optimizing Resilience4j Circuit Breaker Settings with Spring AI

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.1

3. 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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Spring BootSpring AIai-optimizationCircuit Breakerresilience4j
Spring Full-Stack Practical Cases
Written by

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.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.