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