How SpringBoot integrates spring-retry to implement interface request retry

1. Retry mechanism

Due to network instability or network jitter, interface requests often fail. When we try again, we succeed. This is the retry mechanism.

This article was first published on Java Teacher Pan’s personal blog : SpringBoot integrates the spring-retry component to implement the retry mechanism

Its main purpose is to increase the probability of successful request as much as possible, but generally, if our request fails for the first time, the code will throw an exception and end. If you want to request again, you may need to do it manually, which is very inconvenient. , the feasibility is not good either. Therefore, the Spring framework provides support for the retry mechanism, and can be used in conjunction with Hystrix in Spring Cloud to avoid accessing abnormal instances.

2. Elements of the retry mechanism

The elements of the retry mechanism are as follows:

  • Limit the number of retries
  • The time interval between each retry
  • Alarm or rollback of final failure results
  • Choose to retry in case of specific failure exceptions

3. Things to note about the retry mechanism

For non-idempotent methods, we must use the retry mechanism with caution, as it may cause unexpected consequences.
The so-called idempotence means that the results of one request or multiple requests initiated by the user for the same operation are consistent, and there will be no side effects caused by multiple clicks.

4. SpringBoot integrates spring-retry

Let's take a look at how we should use SpringBoot to integrate the spring-retry component to implement the retry mechanism.

1) Add dependencies

First, we add relevant dependencies to the SpringBoot project pom.xml, as follows:

<!-- 重试相关依赖包 -->
<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
    <version>1.2.4.RELEASE</version>
</dependency>
 
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.4</version>
</dependency>

2) Add @EnableRetry annotation

Add the @EnableRetry annotation to the main startup class Application to support the retry mechanism.

@SpringBootApplication
@EnableRetry
public class RetryApplication {
 
    public static void main(String[] args) {
 
        SpringApplication.run(RetryApplication.class, args);
    }
 
}

Note: @EnableRetry can also be used in configuration classes, ServiceImpl classes, and methods

3) Add @Retryable annotation

We add annotations to the methods that need to be retried @Retryableso that the method can be retried. Here I list a method in ServiceImpl:

@Service
public class RetryServiceImpl implements RetryService {
 
    @Retryable(value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 2000,multiplier = 1.5))
    public String testRetry() throws Exception {
 
        System.out.println("开始执行代码:"+ LocalTime.now());
        int code = 0;
        // 模拟一直失败
        if(code == 0){
           // 这里可以使自定义异常,@Retryable中value需与其一致
            throw new Exception("代码执行异常");
        }
        System.out.println("代码执行成功");
        return "success";
    }
}

Description: @Retryable configuration metadata:
value: Retry for the specified exception type thrown, what is specified here is Exception
maxAttempts: Configure the maximum number of retries, here it is configured as 3 times (including the first and last time)
delay: The first retry delay interval, configured here is 2s
multiplier: each retry interval is several times the previous one, here it is 1.5 times

4) Controller test code

@RestController
@RequestMapping("/test")
public class TestController {
    @Autowired
    private RetryService retryService;
 
    @GetMapping("/retry")
    public String testRetry() throws Exception {
        return retryService.testRetry();
    }
}

5) Send request

After sending the request, we found that the background printing situation was indeed retried three times, and an exception was thrown only when the last retry failed. The details are as follows (you can pay attention to the time interval):

SpringBoot integrates the spring-retry component to implement the retry mechanism

6) Supplement: @Recover

Under normal circumstances, if we still fail and throw an exception after retrying the maximum set number of times, we will handle it uniformly through the global exception handling class, but we can actually handle it ourselves, which can be achieved through annotations, as follows @Recover:

@Service
public class RetryServiceImpl implements RetryService {
 
    @Retryable(value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 2000,multiplier = 1.5))
    public String testRetry() throws Exception {
 
        System.out.println("开始执行代码:"+ LocalTime.now());
        int code = 0;
        if(code == 0){
            // 这里可以使自定义异常,@Retryable中value需与其一致
            throw new Exception("代码执行异常");
        }
        System.out.println("代码执行成功");
        return "success";
    }
 
    /**
     * 最终重试失败处理
     * @param e
     * @return
     */
    @Recover
    public String recover(Exception e){
 
        System.out.println("代码执行重试后依旧失败");
        return "fail";
    }
}

Note:
1) The parameter exception type in the @Recover method needs to be consistent with the retry method.
2) The return value type of the method must be consistent with the retry method.
Test again as follows (no more exceptions will be thrown):

SpringBoot integrates the spring-retry component to implement the retry mechanism

This article was first published on Java Teacher Pan’s personal blog : SpringBoot integrates the spring-retry component to implement the retry mechanism

Guess you like

Origin blog.csdn.net/mixika99/article/details/119700434