Retry mechanism: the use of Spring-Retry

In everyday development, there are scenarios where we need to retry a method. For example, when making a network call, because of network fluctuation, it is impossible to access, so it is necessary to retry several times.

I. Introduction

gihub: https://github.com/spring-projects/spring-retry

II. Usage

1,Spring-Boot

1. Introducing dependencies

<dependency>
	<groupId>org.springframework.retry</groupId>
	<artifactId>spring-retry</artifactId>
</dependency>

2. Startup files introduce the @EnableRetry tag, such as

@SpringBootApplication
@EnableWebMvc
@EnableScheduling
@EnableRetry//Open retry mechanism label
public class MytestApplication {

    public static void main(String[] args) {
        SpringApplication.run(MytestApplication.class, args);
    }

}

3. To retry, add the @Retryable tag, such as

    /**
     * Method to be retried
     *
     * @param dto Retry transmission dto
     * @author lin
     * @since 2019 September 24th 2013
     * <p>
     * value: To specify an exception to retry, only that exception will be retried. If multiple exceptions are retried, you can write value = {RetryException.class,Exception.class}
     * maxAttempts: For the number of retries, the default is 3
     * @Backeoff Tags in
     * delay: Delay time (in milliseconds, default is 0 milliseconds)
     * multiplier: Delay interval multiplier, for example, if the delay is defined as 1 second and the delay multiplier is 2, then the first retry interval is 1 second, the second two seconds, the third four seconds, and so on.
     * maxDelay: Maximum interval time
     */
    @Retryable(value = RetryException.class, maxAttempts = 5, backoff = @Backoff(delay = 1000, multiplier = 2))
    public void handle(RetryTransferDto dto) {
        log.info("The message is being processed, the current number of times{}Secondly, the message is{}", dto.getCount(), dto.getMessage());
        if (true) { // Simulation failure
            dto.setCount(dto.getCount() + 1);
            dto.setMessage(dto.getMessage() + " haha ");
            throw new RetryException("Message processing failed, current number of times" + dto.getCount() + "Secondly, the message is" + dto.getMessage());
        }
    }

In order to facilitate counting, the blogger adds a custom transport class RetryTransferDto. The specific contents of the class are as follows.

import lombok.Data;

/**
 * Retry transmission dto
 *
 * @author lin
 * @since 2019 September 24th 2013
 */
@Data
public class RetryTransferDto {
    // retry count
    private int count = 0;
    // Retry content
    private String message;
}

4. If you want to enter a specific method to perform certain operations (such as writing a log, etc.) after the last retry, you can use the @Recover tag, for example

    /**
     * Enter this method when the retry reaches the specified number of times
     *
     * @author lin
     * @since 2019 September 24th 2013
     */
    @Recover
    public void recover(RetryException e) {
        log.error("Retry to reach the specified test", e);
    }

5. The log output is as follows

2019-09-24 10:49:28.572  INFO 2416 --- [           main] com.lin.mytest.retry.RetryService        : The message is being processed, the first time in the current number, the message is haha
2019-09-24 10:49:29.575  INFO 2416 --- [           main] com.lin.mytest.retry.RetryService        : The message is being processed, the second time in the current number, the message is haha haha 
2019-09-24 10:49:31.576  INFO 2416 --- [           main] com.lin.mytest.retry.RetryService        : The message is being processed, the third time in the current number, the message is haha haha  haha 
2019-09-24 10:49:35.577  INFO 2416 --- [           main] com.lin.mytest.retry.RetryService        : The message is being processed, the fourth time, the message is haha haha  haha  haha 
2019-09-24 10:49:43.577  INFO 2416 --- [           main] com.lin.mytest.retry.RetryService        : The message is being processed for the fifth time, and the message is haha haha  haha  haha  haha 
2019-09-24 10:49:43.582 ERROR 2416 --- [           main] com.lin.mytest.retry.RetryService        : Retry to reach the specified test

org.springframework.retry.RetryException: Message processing failed, current number 6, message haha haha  haha  haha  haha  haha 
	at com.lin.mytest.retry.RetryService.handle(RetryService.java:33) ~[classes/:na]
	......

Notes

1. because Spring-Retry principle is cut operation, so pom dependency also needs aop dependency.

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2. Because it is a tangent operation, the method to be retried cannot be called in the current class. For example, there are methods a and B in class A. When method a calls method b, a retry mechanism is added to method B. This retry method is invalid.
3. maxAttempts, delay, multiplier and other parameters in tags need to be constant. If you want to get it dynamically from the configuration file of yml or properties, use the corresponding Expression parameter. such as

    /**
     * Method to be retried
     *
     * @param dto Retry transmission dto
     * @author lin
     * @since 2019 September 24th 2013
     * <p>
     * value: To specify an exception to retry, only that exception will be retried. If multiple exceptions are retried, you can write value = {RetryException.class,Exception.class}
     * maxAttemptsExpression: For the number of retries, the default is 3
     * Backeoff Tags in
     * delayExpression: Delay time (in milliseconds, default is 0 milliseconds)
     * multiplierExpression: Delay interval multiplier, for example, if the delay is defined as 1 second and the delay multiplier is 2, then the first retry interval is 1 second, the second two seconds, the third four seconds, and so on.
     * maxDelayExpression: Maximum interval time
     */
    @Retryable(value = RetryException.class, maxAttemptsExpression = "${retry.attempts}", backoff = @Backoff(delayExpression = "${retry.delay}", multiplierExpression = "${retry.multiplier}"))
    public void handle(RetryTransferDto dto) {
        log.info("Get parameters from the configuration file, process messages, current number of times{}Secondly, the message is{}", dto.getCount(), dto.getMessage());
        if (true) { // Simulation failure
            dto.setCount(dto.getCount() + 1);
            dto.setMessage(dto.getMessage() + " haha ");
            throw new RetryException("Getting parameters from the configuration file, message processing failed, current number of times" + dto.getCount() + "Secondly, the message is" + dto.getMessage());
        }
    }

4. My test code

Code cloud:

https://gitee.com/doubletreelin/mytest.git

Keywords: Spring network github Lombok

Added by kafmil on Wed, 02 Oct 2019 12:38:35 +0300