
Resilience4j at a Glance
Scope of this article is applications based on microservice architecture.
Let me begin with a question, what is most important non-functional requirement from any application? Undoubtedly the answer of this question will be ‘Robustness’. This means applications must behave reasonable with respect to adverse scenarios. Against all adverse scenarios application needs to take either corrective action or redirect to reasonable action or application flow. It is very much required to understand about those adverse scenarios.
- Out of all one or more than one microservice is broken or out of order.
- Need to manage user traffic by fixing number of requests in specific time.
- Need to manage user traffic by fixing specific number of concurrent requests.
There is no dispute on need of above functionality in application to achieve robustness and resiliency in working of application. At some extent Hystrix from Netflix could resolve the issue but not all. Also, Spring Cloud Hystrix project is deprecated. So, under the umbrella of ‘Spring Cloud Circuit Breaker’ Resilience4j is introduced.
Now let us consider above mentioned scenarios in detail and how Resilience4j maintains resiliency.
1. Out of all one or more than one microservice is broken or out of order,
To understand let us consider below implementation of microservices,

In all favorable conditions, nothing to worry but what if any of microservice fails or does not behave as per expected functionality? For time being let us consider below negative scenario,

As per above diagram, Microservice MS2 is non-operational . In flow, microservice MS-1 will not be able to get expected response from MS-2 and expected functionality remains unfulfilled. resilience4j-circuitbreaker will help you to handle such scenarios.
So below are the steps you need to manage resiliency in Springboot,
a) Include dependency in maven similar to below,

b) Setting property value in application.properties file
If you want to call fallback method if failure rate is 60% or more,

more properties values can be set as per need of application behavior.
c) Writing fallback method,

2. Need to manage user traffic by fixing number of requests in specific time,
There are scenarios when we need to restrict number of requests within some specific time. One of the use cases we can consider here which is of provisioning of DB connection. If we want to provision only 100 connections pers second and for next connection after 100th connection application needs to wait for 5 second, below implementation will help to achieve this purpose,
a) Include dependency in maven similar to below,

b) Setting property value in application.properties file,
Below values will ensure that service MS1 will only allow 100 requests in 5 seconds,

c) Writing annotation on REST method,

Above implementation will put a cap of 100 request in 5 seconds. This approach will help to prevent against,
- Web/data scaping.
- Brute force attacks.
- DoS(Denial-of-Service) and DDoS (Distributed Denial-of-Service) attacks.
3. Need to manage user traffic by fixing specific number of concurrent requests,
This is nothing but implementation of bulkhead design pattern. This implementation will be required when we want to distribute concurrent requests evenly among multiple but same microservice. This means if we are anticipating 1000 concurrent request for particular functionality and we have 4 instances of microservice for that functionality. In such scenarios we need to distribute 1000 concurrent requests among 4 available instances.
Below implementation will consider only 25 concurrent requests per instance.
a) Include dependency in maven similar to below,

b) Setting property value in application.properties file
Below value will ensure that service MS1 will only allow 25 concurrent requests,

c) Required annotation for REST method to achieve this will be like below,

So, this is tolerant of failure. We can define or restrict number of request as per capacity of local resources to operate within tolerance limit. This will restrict failure by passively transferring responsibility to other microservices.