Using Spring boot Async with Retry
A few months ago, during technical design session for a light micro service that requires calling different microservices while customer receives an asynchronous response. Ive seen the need to use something simple, but effective and choose to go with Async & Retry of Spring boot.
Why this choice?
Spring Retry provides the ability to automatically re-invoke a failed operation. This is helpful when errors may be transient in nature (like a momentary temporary errors). Also it provides a declarative control of the process and policy-based behavior that is easy to extend and customize.
Spring boot @Async provides the ability to make it execute in a separate thread, for instance, the caller will not wait for the completion of the called method.
Why those choices? It’s simple with less lines of code and Retry & Async is implemented. All you need is @EnableRetry on SpringBootApplication:
1 2 |
@EnableRetry @EnableAsync |
Add the async on any public method that is used before the retry:
1 |
@Async |
And on the function in your interface:
1 |
@Retryable( value = {RestClientException.class}, maxAttempts = 3, backoff = @Backoff(3000)) |
After that, a simple test that asserts that the retry mechanism is working as expected.
Annotations are an easy way to get started with Spring Retry And Async and it is good enough for many cases. However, if you need more customization there is a RetryTemplate & RestTemplate where you easily can configure stuff exactly the way you want it. Sure you could create RetryTemplate and more sophisticated rules and properties. You can find more in this article: https://www.baeldung.com/spring-retry
When working with external APIs, especially micro services, a lot of things can go wrong especially network glitches. This is where it is important to consider having retries. Spring Retry can handle this for you in an easy and convenient.
Is retries always the way to go? Not always, like everything in software engineering there is no right or wrong solution for everything. There is the right solution for a particular use case. Use retry only on the temporary errors, it isn’t recommended to to use it on permanent errors else it can cause system performance issues.
To improve the resilience of microservices architecture, it is recommended considering Spring Retry & Circuit Breaker. Spring retry is not an alternative to circuit breaker.
1 |
@CircuitBreaker(value = {RestClientException.class}, maxAttempts = 3, openTimeout = 15000l, resetTimeout=30000l) |
With CircuitBreaker, using a RetryTemplate is recommended.
A nice article to check, Applying The Circuit Breaker Pattern at HMHDo you have any thoughts, comments disagreements? let me know!