日期:2023-4-17
问题:项目中feign接口的请求,一次性发多个,甲方的服务器资源有限,
导致抛出FeignException 429:too many requests
1.feign的重试机制流程
使用 Feign 客户端发送 HTTP 请求时,如果请求失败了(例如网络超时或者是目标服务器返回的 5xx 错误码),Feign 可以自动重试该请求。这就是 Feign 中的重试机制,它可以提高请求成功率和系统的健壮性。
Feign 的重试机制非常简单:在某个请求失败时,Feign 将重新尝试几次该请求,直到请求成功或者达到最大重试次数为止。默认情况下,Feign 最多会重新尝试一次请求。
当我们自定义异常重试的时候,只有返回RetryableException 异常,才会让feign进行重新调用。
2.feign的重试配置
- 创建CustomRetryer 类实现Retryer接口
- 添加重试相关的属性:最大重试次数,间隔。。。
- 在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.使用重试
- 在 feign中的自定义Configuration 中 注入重试Bea
- feign接口中指定configuration的类
- 创建一个继承了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遇到这个异常时,它会自动进行重试。