Use Spring RetryTemplate to retry gracefully

1. Use scenario

  • When we interact with the downstream data through http, we will stipulate the interface protocol. For example, when both parties agree to return 20000, they can re request to get the correct result.
  • In the process of http network communication, there are often some network level exceptions such as IOException: unexpected end of stream on Connection; SocketException: Broken pipe (Write failed), Connection reset, etc. the lazy way is to add retry logic. If you are a technical house, you can go deep into the underlying reasons.
  • Any other scenario that can be retried

2. Normal retry writing

    int retryTimes = 3;
    for (int i = 0; i < retryTimes; i++) {
        Result result = doSomethingPre();
        if (result == Expected value){

Do you think this code is like a bunch of shits? If there is a lot of retry requirements, the project will be full of shits. As a code farmer with pursuit, we can't tolerate this kind of thing. Next, Spring RetryTemplate comes on stage.

3. Use of Spring RetryTemplate

  • Introducing dependency
  • To configure
    If we want to retry, we must define the strategy of retry: the trigger condition of retry, the number of retries, time interval and other elements.


The figure below shows the relationship between RetryPolicy and implementation class. It's too large to see clearly. It doesn't matter. We only look at the simplest and most commonly used SimpleRetryPolicy, in which you can set the number of retries: setMaxAttempts(); if not, the default value is 3 times.


As the name implies, BackOffPolicy is a backoff policy. Take a look at its implementation class.

Take the exponential backoff policy for example. It is an exponential backoff policy. You need to set parameters
initialInterval: initial sleep time, default 100 ms
Multiplier: Specifies the multiplier. The current sleep time * multiplier is the next sleep time;
maxInterval: Specifies the maximum sleep time, 30 seconds by default, to avoid infinite waiting caused by too large multiplier.


The spring container injects the RetryTemplate bean and sets the above two strategies in the bean:

    public RetryTemplate simpleRetryTemplate() {
        RetryTemplate retryTemplate = new RetryTemplate();
        retryTemplate.setRetryPolicy(new SimpleRetryPolicy());
        ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
        return retryTemplate;

Generally speaking, the above configuration means that the maximum retries are three times, with a time interval of 3,32, 32 * 2 and no more than 15s.

  • Use
    retryTemplate.execute(RetryCallback<T, E> retryCallback);
    The RetryCallback interface has only one interface, that is, a functional interface, which can be written using lamda expressions. It is concise and intuitive.
    The final writing method: retrytemplate. Execute (retrycontext - > {retry logic code});
    This is the source code, which can be omitted. You can see that the final call is RetryCallback The implementation class of the interface, and lamda Expression
    public final <T, E extends Throwable> T execute(RetryCallback<T, E> retryCallback) throws E {
	return doExecute(retryCallback, null, null);

    protected <T, E extends Throwable> T doExecute(RetryCallback<T, E> retryCallback,RecoveryCallback<T> recoveryCallback, RetryState state)throws E, ExhaustedRetryException {
        return retryCallback.doWithRetry(context);

The above is the simplest use of retryTemplate. It has many powerful uses. I will add them when I have time.

Tags: Java Spring network

Posted on Tue, 24 Mar 2020 02:46:40 -0700 by will