关于Feign的重试机制

发布时间 2023-04-19 17:19:59作者: 小羊摩多摩多

日期:2023-4-17

问题:项目中feign接口的请求,一次性发多个,甲方的服务器资源有限,

导致抛出FeignException 429:too many requests

 

1.feign的重试机制流程

使用 Feign 客户端发送 HTTP 请求时,如果请求失败了(例如网络超时或者是目标服务器返回的 5xx 错误码),Feign 可以自动重试该请求。这就是 Feign 中的重试机制,它可以提高请求成功率和系统的健壮性。

Feign 的重试机制非常简单:在某个请求失败时,Feign 将重新尝试几次该请求,直到请求成功或者达到最大重试次数为止。默认情况下,Feign 最多会重新尝试一次请求。

当我们自定义异常重试的时候,只有返回RetryableException 异常,才会让feign进行重新调用。

 

2.feign的重试配置

  1. 创建CustomRetryer 类实现Retryer接口
  2. 添加重试相关的属性:最大重试次数,间隔。。。
  3. 在continueOrPropagate()方法中,执行重试的逻辑 
 1 public class CustomRetryer implements Retryer {
 2 
 3     // 最大重试次数
 4     private final int maxAttempts;
 5     // 重试次数
 6     private int attempt;
 7     // 重试间隔次数
 8     private final long backoff;
 9 
10     public CustomRetryer() {
11         this(5, 1000);
12     }
13 
14     public CustomRetryer(int maxAttempts, long backoff) {
15         this.maxAttempts = maxAttempts;
16         this.backoff = backoff;
17     }
18 
19     @Override
20     public void continueOrPropagate(RetryableException e) {
21         if (attempt < maxAttempts) {
22             try {
23                 Thread.sleep(backoff);
24             } catch (InterruptedException ex) {
25                 throw new RuntimeException(ex);
26             }
27             attempt++;
28         }
29         else {
30             log.error("重试了5次");
31             try {
32                 throw new Exception("重试次数超过最大值");
33             } catch (Exception ex) {
34                 throw new RuntimeException(ex);
35             }
36         }
37     }
38 
39     @Override
40     public Retryer clone() {
41         return new CustomRetryer(maxAttempts, backoff);
42     }
43 }

 

3.使用重试

  1. 在 feign中的自定义Configuration 中 注入重试Bea
  1. feign接口中指定configuration的类
  2. 创建一个继承了feign.codec.ErrorDecoder接口的自定义错误解码器类

  

import feign.Response;
import feign.RetryableException;
import feign.codec.ErrorDecoder;

public class CustomErrorDecoder implements ErrorDecoder {

    @Override
    public Exception decode(String methodKey, Response response) {
        if (response.status() == 429) {
            return new RetryableException(
                    "Too many requests",
                    null,
                    response.request().httpMethod(),
                    null,
                    response.request());
        }

        return new RuntimeException("Unknown error");
    }
}

 

上面的代码将HTTP状态码为429的响应转换为RetryableException异常。当Feign遇到这个异常时,它会自动进行重试。