Spring Cloud Circuit Breaker Implementation Using Resilience4j and Spring Open Feign

Faza Zulfika Permana Putra
Blibli.com Tech Blog
7 min readNov 28, 2022
image source : https://files.readme.io/8701241-small-Resilience4j.png

Last time, I wrote an article about Circuit Breaker implementation using Resilience4j in Spring Boot with Reactive Feign. Resilience4j is lightweight, circuit breaker library that inspired by Netflix Hystrix. You can read more about Resilience4j in this page.

Last time when I wrote that article, I had try to implement it in Reactive Feign. But currently I had try to implement it in Spring Open Feign. So I want to share about how I implemented it in Spring Open Feign with you guys.

Application Dependencies

We will use several spring dependencies to support our example.

  1. org.springframework.boot:spring-boot-starter-web → dependency for spring web mvc
  2. org.springframework.boot:spring-boot-starter-actuator → dependency for spring boot actuator that provides several production-ready endpoint that help us to monitor our application
  3. org.springframework.cloud:spring-cloud-dependencies → spring cloud dependency that contain all dependencies to use spring cloud features
  4. org.springframework.cloud:spring-cloud-starter-openfeign → dependency for feign with spring open feign
  5. org.springframework.cloud:spring-cloud-starter-circuitbreaker-resilience4j → dependency for resilience4j circuit breaker spring cloud starter

You can generate skeleton of project, using start.spring.io. Then add additional dependencies above.

This is the pom.xml file example (please adjust some part from this snippet based on your needs).

Configure Circuit Breaker Through Properties

Spring Open Feign v3.1.1 or Below

Each Circuit Breaker that created will have it’s own id. For Feign Client, Circuit Breaker will build id from Feign Client name. Below is Feign Client name convention.

{Feign-Class-Name}#{Method-Name}({Parameter-Types}{,})

As you can see, that Feign Client name will have name that contains ‘#’, ‘(‘, ‘)’, and ‘,’ characters. Unfortunately, Spring Boot Configuration Properties cannot contains those characters. So the id will be invalid, and we cannot set specific Circuit Breaker config based on id.

To handle that issue, I came up with solution to change the Circuit Breaker id. I will convert all of those characters to “_” character, and remove latest “_” character. So the id will be like below convention.

{Feign-Class-Name}_{Method-Name}_{Parameter-Types}{_}

Spring Open Feign v3.1.2 or Above

If you’re already using Spring Open Feign v3.1.2 or above, Spring already came up with default solution to configure Circuit Breaker through properties. You can set below properties to true

feign.circuitbreaker.alphanumeric-ids.enabled

Since Spring Boot Configuration Properties cannot contains ‘#’, ‘(‘, ‘)’, and ‘,’ characters, Spring Boot will automatically update Circuit Breaker id to remove non-alphanumeric characters. So Circuit Breaker id will only contains alphanumeric characters. Then the id will be like below convention.

{Feign-Class-Name}{Method-Name}{Parameter-Types}

If you’re using this solution, you didn’t need to create custom CircuitBreakerNameResolver like we created in previous section.

Get Default Circuit Breaker Config from Properties

Another challenge to use Resilience4j Circuit Breaker is to add default config for all Feign Clients from properties.

The case is I want to set default config according to my needs that applied to all Feign Clients. To handle that case, I need to set config for all Feign Clients manually. That solution is takes times, and will make my properties file full of Circuit Breaker config even though all config is same.

So I came up with solution to customize logic to set Circuit Breaker config. I make Circuit Breaker config always read “default” config from properties. So I didn’t need to set config for all Feign Clients manually.

Set Custom Circuit Breaker Event Consumer

Resilience4j Circuit Breaker have several events which is triggered based on several conditions, like state transition, a Circuit Breaker reset, a successful call, a recorded error or an ignored error.

So in this case, I want to show you how to implement event consumer that log the triggered event. We will modify our CustomCircuitBreakerConfig class that we created earlier to add our custom Resilience4JCircuitBreakerFactory.

In our custom Resilience4JCircuitBreakerFactory, we will add an event consumer through event publisher object from Circuit Breaker object.

In above example, I show you how to add event consumer for each events that triggered by Circuit Breaker. However we can add a consumer for specific event that we want.

Circuit Breaker event publisher have many “on” method that we can implement, as example onSuccess for success event, or onCallNotPermitted for failed process due to Circuit Breaker that is in OPEN state. You can explore other “on” method based on your needs.

Downstream Service

We will use https://httpbin.org/#/Dynamic_data/get_delay__delay_ to test our implementation. That API is an open API that allow us to set delay for the API response, it is suitable for the scenario that we will try.

Firstly we need to create Feign Client that will hit Delay Open API.

From Feign Client that we created above, Spring Open Feign will automatically create the implementation to call the downstream service.

Application Controller and Service

In previous section, we already create a Feign Client to hit our downstream service. So on this section we will create a controller and service class that will be hit by our upstream service.

Wrap It Up!

At this point, all codes that we need to implement Circuit Breaker Resilience4j is complete. We only need to set several annotations in our spring boot application class, and set several properties.

From snippet code above, we add several annotations.

  1. @EnableFeignClients → Tell spring that we implement Feign Client and need help to auto-configure the Feign Client

Beside the annotation that we set, we need to set several properties also to custom the behavior of our application.

From snippet code above, we add several properties.

  1. server.servlet.context-path → we set base-path for our web application, so if we will hit our endpoint, we will hit it under /demo path.
  2. management.endpoint.health.show-details → this is property to tells actuator to enable endpoint to show health information of our application or not. By default, actuator never show detail of our application health information, so we need to set it as always to make it always show detail of our application health.
  3. management.health.circuitbreakers.enabled → this is property to tells actuator to enable endpoint to show health of our Circuit Breaker. Circuit Breaker health information show statistics for each Circuit Breaker, including failure rate, failure rate threshold, failed calls, Circuit Breaker state, etc.
  4. feign.client.config.{feign-client-name} → this property is used to set option properties for our feign client. It used feign client name that we set in FeignClient annotation. We use this property to set read timeout and connect timeout threshold for our downstream service.
  5. feign.circuitbreaker.enabled → this property is used to tell our feign client that we want to use Circuit Breaker. If we set this property to true, then Spring Open Feign will automatically configure all beans that we need to use Circuit Breaker with Spring Open Feign.
  6. resilience4j.circuitbreaker.configs.default.registerHealthIndicator → this property is used to tells Circuit Breaker to register it’s health indicator in actuator application health information. We set config in ‘default’, so all of our Circuit Breaker will have this config.
  7. resilience4j.circuitbreaker.instances.{Circuit-Breaker-Id}.minimumNumberOfCalls → this property is used by Circuit Breaker to tell when they start to calculate the failure rate. So if we set the value as 10, Circuit Breaker will wait until they receive 10 request before calculate the failure rate. This property is configure for specific Circuit Breaker id, as example we set it for HttpBinClient_getBinWithDelayInSeconds_int id. You can read more about this property in this page.
  8. resilience4j.circuitbreaker.instances.{Circuit-Breaker-Id}.failureRateThreshold → this property is used to set percentage threshold for error that occurs. If percentage of error that occurs exceed the threshold, circuit breaker will open it circuit. You can read more about this property in this page.
  9. resilience4j.timelimiter.configs.default.timeoutDuration → this property is used to set how long Circuit Breaker will wait until it cancel the process and throw timeout error. We set config in ‘default’, so all of our Circuit Breaker will have this config. You can read more about Time Limiter from this page.

Wrap It Up using Spring Open Feign v3.1.2 or Above

If you’re using Spring Open Feign v3.1.2 or above, we need to change Circuit Breaker id that we used in properties based on the explanation in Configure Circuit Breaker Through Properties — Spring Open Feign v3.1.2 or Above section.

As you can see, we change our Circuit Breaker id that we put in resilience4j.circuitbreaker.instances. Instead of putting HttpBinClient#getBinWithDelayInSeconds(int) or HttpBinClient_getBinWithDelayInSeconds_int, we put HttpBinClientgetBinWithDelayInSecondsint.

Since if we use feign.circuitbreaker.alphanumeric-ids.enabled, as default Spring Open Feign will remove non-alphanumeric characters from Circuit Breaker id.

Testing

Based on our configuration in application.yaml, to test Circuit Breaker implementation, we need to sent at least 10 request, and after 100 request Circuit Breaker will reset the data. To make Circuit Breaker open, at least 50% of the request that we sent is failed.

Our API url for testing is http://localhost:8080/demo/get

To hit with success response, we can try using 1s for delayInSeconds query parameter. It will give us success response.

http://localhost:8080/demo/get?delayInSeconds=1

To hit with failed response due to read timeout. We can try using 3s for delayInSeconds query parameter, since our read timeout configuration is 2s.

http://localhost:8080/demo/get?delayInSeconds=3

If you hit with failed response 8 times more, it will give you different error response since our circuit breaker is OPEN and give us circuit breaker is OPEN failed response.

If you open application actuator health information, you will find statistics about your Circuit Breakers.

Our application actuator health information url is http://localhost:8080/demo/actuator/health

Conclusion

Spring Cloud Circuit Breaker with Resilience4j is easy to implemented in Reactive Feign and also in Spring Open Feign. If you have interest and want to read more about Resilience4j, you can go to this page.

--

--