Backend Development 16 min read

Resilience4j Essentials: Circuit Breaker, TimeLimiter, Bulkhead & RateLimiter

This article introduces Resilience4j, a lightweight fault‑tolerance library for Spring Boot, explaining its core decorators—CircuitBreaker, TimeLimiter, Bulkhead, and RateLimiter—along with configuration examples, annotation usage, fallback handling, and practical test code to improve system stability and resilience.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Resilience4j Essentials: Circuit Breaker, TimeLimiter, Bulkhead & RateLimiter

Environment

Spring Boot 3.0.12

Introduction

In distributed systems, protecting interfaces from failures is crucial. The circuit‑breaker pattern prevents overload and crashes, keeping the system stable.

Resilience4j Overview

Resilience4j is a lightweight fault‑tolerance framework inspired by Netflix Hystrix and designed for functional programming. It provides higher‑order functions (decorators) such as circuit breaker, rate limiter, retry, and bulkhead, which can be combined on any functional interface, lambda, or method reference.

Core Decorators

CircuitBreaker : cuts off calls to a failing service, protecting the whole system.

TimeLimiter : limits the execution time of a call and triggers a fallback on timeout.

Bulkhead : isolates parts of the system to prevent a failure in one component from affecting others.

RateLimiter : controls the rate of incoming requests to avoid overload.

Setup

Add the following Maven dependencies:

<code><!-- 处理熔断 --></code>
<code><dependency></code>
<code>  <groupId>io.github.resilience4j</groupId></code>
<code>  <artifactId>resilience4j-circuitbreaker</artifactId></code>
<code>  <version>1.7.0</version></code>
<code>  <scope>compile</scope></code>
<code></dependency></code>
<code><!-- 处理超时 --></code>
<code><dependency></code>
<code>  <groupId>io.github.resilience4j</groupId></code>
<code>  <artifactId>resilience4j-timelimiter</artifactId></code>
<code>  <version>1.7.0</version></code>
<code>  <scope>compile</scope></code>
<code></dependency></code>
<code><dependency></code>
<code>  <groupId>io.github.resilience4j</groupId></code>
<code>  <artifactId>resilience4j-spring-boot2</artifactId></code>
<code>  <version>1.7.0</version></code>
<code>  <scope>compile</scope></code>
<code>  <exclusions></code>
<code>    <exclusion></code>
<code>      <artifactId>resilience4j-bulkhead</artifactId></code>
<code>      <groupId>io.github.resilience4j</groupId></code>
<code>    </exclusion></code>
<code>  </exclusions></code>
<code></dependency></code>
<code><!-- 处理隔离 --></code>
<code><dependency></code>
<code>  <groupId>io.github.resilience4j</groupId></code>
<code>  <artifactId>resilience4j-bulkhead</artifactId></code>
<code>  <version>1.7.0</version></code>
<code>  <scope>compile</scope></code>
<code>  <optional>true</optional></code>
<code></dependency></code>

CircuitBreaker Example

Service implementation:

<code>@Service
public class CircuitBreakerService {
  @CircuitBreaker(name = "akf")
  public Object query(Long id) {
    if (id == 6) {
      throw new RuntimeException("非法数字");
    }
    return "查询 - " + id ;
  }
}</code>

Configuration (application.yml):

<code>resilience4j:
  circuitbreaker:
    configs:
      default:
        failure-rate-threshold: 100
        sliding-window-type: count-based
        sliding-window-size: 5
        minimum-number-of-calls: 5
        wait-duration-in-open-state: 10000
      akf:
        failure-rate-threshold: 80
        sliding-window-type: count-based
        sliding-window-size: 3
        minimum-number-of-calls: 3
        wait-duration-in-open-state: 10000    
    instances:
      akf:
        base-config: akf
</code>

Controller usage:

<code>@Resource
private CircuitBreakerService cbs ;
@GetMapping("/{id}")
public Object index(@PathVariable("id") Long id) {
  return cbs.querty(id) ;
}</code>

Fallback method:

<code>@CircuitBreaker(name = "akf", fallbackMethod = "fallback")
public Object query(Long id) {}
public Object fallback(Throwable e) {
  return "fallback, " + e.getMessage() ;
}
</code>

Diagram:

TimeLimiter Example

Service implementation:

<code>@Service
public class TimeLimiterService {
  @TimeLimiter(name = "akf")
  public CompletionStage<Object> query(Integer id) {
    return CompletableFuture.supplyAsync(() -> {
      try {
        TimeUnit.SECONDS.sleep(3);
      } catch (Exception e) {
        e.printStackTrace();
      }
      return "没有超时,正常返回结果";
    }) ;
  }
}
</code>

Test code:

<code>@Test
public void testQuery() throws Exception {
  tls.query(10).thenAccept(System.out::println).whenComplete((v, e) -> {
    System.err.println(e.getMessage()) ;
  }) ;
}
</code>

Configuration:

<code>resilience4j:
  timelimiter:
    configs:
      default:
        timeout-duration: 6s
      akf:
        timeout-duration: 4s
    instances:
      akf:
        base-config: akf
</code>

Fallback:

<code>@TimeLimiter(name = "akf", fallbackMethod = "timeout")
public CompletionStage<Object> query(Integer id) {}
public CompletionStage<Object> timeout(Throwable e) {
  return CompletableFuture.supplyAsync(() -> "timeout, " + e.getMessage()) ;
}
</code>

Bulkhead Example

Service implementation (semaphore and thread‑pool):

<code>@Service
public class BulkheadService {
  @Bulkhead(name = "akf", type = Type.SEMAPHORE)
  public Object save() {
    System.out.println(Thread.currentThread().getName()) ;
    return "保存成功" ;
  }

  @Bulkhead(name = "akf", type = Type.THREADPOOL, fallbackMethod = "fallbackThreadPool" )
  public CompletionStage<Object> query(Integer id) {
    System.out.println(Thread.currentThread().getName()) ;
    return CompletableFuture.supplyAsync(() -> {
      try {
        System.out.println(Thread.currentThread().getName()) ;
        TimeUnit.SECONDS.sleep(3) ;
      } catch (Exception e) {
        e.printStackTrace();
      }
      return "没有超时,正常返回结果" ;
    }) ;
  }

  public CompletionStage<Object> fallback(Throwable e) {
    return CompletableFuture.supplyAsync(() -> "timeout, " + e.getMessage()) ;
  }
}
</code>

Configuration:

<code>resilience4j:
  bulkhead:
    configs:
      default:
        max-concurrent-calls: 2
        max-wait-duration: 2000
    instances:
      akf:
        max-concurrent-calls: 2
        max-wait-duration: 2000
</code>

Semaphore test:

<code>@Test
public void testSave() throws Exception {
  for (int i = 0; i < 5; i++) {
    new Thread(() -> {
      bs.save() ;
    }, "T - " + i).start() ;
  }
  System.in.read() ;
}
</code>

Fallback for semaphore:

<code>@Bulkhead(name = "akf", type = Type.SEMAPHORE, fallbackMethod = "fallbackSemaphore")
public Object save() {}
public Object fallbackSemaphore(Throwable e) {
  return "等待超时了 - " + e.getMessage() ;
}
</code>

Thread‑pool bulkhead configuration:

<code>resilience4j:
  thread-pool-bulkhead:
    configs:
      default:
        core-thread-pool-size: 2
        max-thread-pool-size: 2
        queue-capacity: 1
</code>

Thread‑pool test:

<code>@Test
public void testQuery() throws Exception {
  for (int i = 0; i < 5; i++) {
    new Thread(() -> {
      bs.query(10).thenAccept(System.out::println).whenComplete((v, e) -> {
        System.err.println(e.getMessage()) ;
      }) ;
    }, "T - " + i).start() ;
  }
  System.in.read() ;
}
</code>

RateLimiter Example

Service implementation:

<code>@RateLimiter(name = "akf", fallbackMethod = "fallback")
public Object save() {
  System.out.println(Thread.currentThread().getName()) ;
  try {
    TimeUnit.SECONDS.sleep(3) ;
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
  return "保存成功" ;
}

public Object fallback(Throwable e) {
  return "没有可用的许可证 - " + e.getMessage() ;
}
</code>

Configuration:

<code>resilience4j:
  ratelimiter:
    configs:
      default:
        limit-for-period: 50
        limit-refresh-period: 500ns
        timeout-duration: 5s
      akf:
        limit-for-period: 2
        limit-refresh-period: 10s
        timeout-duration: 2s
    instances:
      akf:
        base-config: akf
</code>

Test simulation (5 threads):

<code>for each thread call save();
output shows only two successful calls and fallback messages for the others.
</code>

Diagram:

Conclusion

Resilience4j provides powerful decorators—CircuitBreaker, TimeLimiter, Bulkhead, and RateLimiter—that protect system resources, prevent overload, and isolate failures. Using its annotation‑based approach in Spring Boot makes it easy to integrate these mechanisms and enhance application stability and availability.

JavaSpring Bootfault tolerancecircuit 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

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