
Resilience4J is an open-source library that provides different resilience patterns for building resilient applications. Bulkhead is one of the patterns provided by Resilience4J to prevent the cascading failure of an application by limiting the resources used by a failed component. In this blog, we will discuss in detail what it is and how Resilience4J implements it.
What is a Bulkhead?
It is a physical barrier that separates different compartments of a ship to prevent flooding in case of a hull breach. Similarly, in software architecture, a bulkhead is a pattern that creates isolated compartments or pools of resources to prevent failures in one pool from affecting the availability of resources in other pools. It can be implemented in different ways, such as thread pools, process pools, or network partitions.
In a microservices architecture, bulkheads are important to ensure that a failure in one service does not bring down the entire system. By isolating services and creating separate pools of resources, a bulkhead can prevent a failure in one service from affecting other services in the system.
Resilience4J Bulkhead
Resilience4J provides a Bulkhead pattern that can be used to limit the number of concurrent requests that can be processed by a component. The Bulkhead pattern is implemented using the Semaphore concept from the java.util.concurrent package. A Semaphore is a synchronization construct that maintains a set of permits that can be acquired by threads to gain access to a shared resource.
Resilience4J Bulkhead has three main configurations:
- MaxConcurrentCalls: This configuration sets the maximum number of concurrent calls that can be made to a protected component. If the maximum number of calls is reached, the bulkhead will reject further requests.
- MaxWaitDuration: This configuration sets the maximum time a request can wait for a permit to be acquired from the bulkhead. If the wait time exceeds the configured value, the bulkhead will reject the request.
- ReserveFactor: This configuration sets the percentage of permits that are reserved for high-priority requests. The remaining permits are used for normal requests.
Resilience4J Bulkhead can be used in combination with other resilience patterns provided by Resilience4J, such as Circuit Breaker and Retry, to create a robust and resilient application.
Features of Bulkhead:
Bulkhead is a resilience pattern that provides several features to help prevent a cascading failure in an application. Some of the key features of Bulkhead are:
- Concurrency control: Bulkhead limits the number of concurrent requests that can be made to a component, preventing overload and resource exhaustion.
- Isolation: Bulkhead creates isolated compartments or pools of resources, which prevents failures in one pool from affecting the availability of resources in other pools.
- Fault tolerance: By limiting the number of concurrent requests and creating isolated pools of resources, Bulkhead helps prevent a failure in one component from cascading to other components in the system, ensuring that the application remains available.
- Configurability: Bulkhead is highly configurable, allowing developers to set the maximum number of concurrent requests, maximum wait time, and reserve factor for high-priority requests.
- Ease of use: Resilience4J provides an easy-to-use implementation of Bulkhead that can be integrated into a Spring Boot application with just a few lines of code.
- Composability: Bulkhead can be used in combination with other resilience patterns provided by Resilience4J, such as Circuit Breaker and Retry, to create a more robust and resilient application.
Bulkhead Pattern in Action
Let’s consider a simple example of a web application that processes user requests. The application has a service that processes incoming requests, and it uses a thread pool to handle the requests.
Here is the code for the service:



This service processes requests asynchronously using a thread pool. However, if there are too many requests, the thread pool can become overwhelmed and start to reject requests, causing a failure. This failure can affect other parts of the system that depend on this service.
To prevent this failure from affecting other parts of the system, we can use this pattern to limit the number of requests that can be processed concurrently in the thread pool. Here’s the modified code:



In this modified code, we’ve added a Semaphore to limit the number of concurrent requests that can be processed in the thread pool. The Semaphore is initialized with a maximum of 5 concurrent requests, which means that only 5 requests can be processed concurrently. If there are more than 5 requests, they will be queued until one of the processing threads becomes available.
Conclusion
The bulkhead pattern is a useful pattern for improving the resilience of a system. By using bulkheads to partition resources and limit the impact of failures, we can ensure that failures in one part of the system do not affect other parts of the system. In the example we’ve looked at, we’ve used a Semaphore to limit the number of concurrent requests that can be processed in a thread pool, but there are many other ways that bulkheads can be implemented.
For more detailed explanation we can visit this https://resilience4j.readme.io/docs/bulkhead