-
背景
-
Spring Cloud 版本
-
Feign 重试
-
重试源码分析
-
扩展
-
总结
背景
有时候在一些特殊的场景我们需要服务又重试机制,比如微服务之间服务上下线如果没有做到特别优雅就需要服务A在调用服务B时,而服务B正在重启,如果服务发现剔除不及时,就会调用到已经被kill
的服务,导致业务报错,影响系统的稳定性。或者由于网络原因调用失败,我们可能也需要重试。
Spring Cloud 版本
2020.0.1
Feign 重试
其实Feign
的重试是非常简单的。只需要很简单的配置
public class FeignConfigure {
@Value("${feign.period}")
private long feignPeriod;
@Value("${feign.maxPeriod}")
private long feignMaxPeriod;
@Value("${feign.maxAttempts}")
private int feignMaxAttempts;
@Bean
public Retryer feignRetryer(){
return new Retryer.Default(feignPeriod, feignMaxPeriod, feignMaxAttempts);
}
}
核心配置也非常简单,配置一个Retryer
,几个参数简单解释一下
-
feignPeriod: 发起重试的时间间隔,单位毫秒 -
feignMaxPeriod: 发起重试的最大时间间隔,单位毫秒 -
feignMaxAttempts: 重试次数,如果需要重试1次,就设置为2
这里我单纯说的就是feign的重试机制,不是ribbon的
在需要重试的feign客户端指定该配置类即可
@FeignClient(name = "${feign.client.service.order}", url = "${feign.client.order.url}", configuration = FeignConfigure.class)
public interface OrderClient {
@GetMapping("/order/v1/list")
Response<List<OrderVO>> orders(@SpringQueryMap OrderDTO orderDTO);
}
然后我们故意将order服务不启动然后调用,会发现会自动重试,并重试两次。
可以注意的是只有RetryableException 异常才会重试,也就是说我们的普通业务异常并不会重试,所以这点我们可以放心
重试源码分析
其实重试的源码也很简单,主要在SynchronousMethodHandler
类中的invoke
方法
我们简单分析下
这里就可以看到我们设置的参数在这里生效使用了,而feign留给我们的扩展也很灵活,我们只需要实现Retryer
接口即可
当然前面配置的就是使用的feign为我们提供的默认的Retryer
实现

扩展
实际上上面的重试方案还是有风险,可能存在业务幂等问题,因为类似Post
方法我们重试,由于网络两将军问题的存在,我们可能会调用多次导致接口多次调用,出现不幂等情况,所以最为稳妥的方式应该是只重试Get
请求。要实现只重试Get
请求,我们就需要自己实现Retryer
接口,而RetryableException
中拿到HttpMethod
,所以实现起来还是比较简单的
总结
feign
的重试主要实现是在SynchronousMethodHandler
类中的,重试许谨慎,为了防止数据幂等问题,最好的方案是只重试Get
请求,不过还是得根据自己实际业务场景来,其次feign
的重试和ribbon
的重试机制不同,如果使用了ribbon
,配置方式就不是这种方式了
原文始发于微信公众号(小奏技术):简单聊聊Spring Cloud Feign重试机制
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/29901.html