记一次Spring retry的使用

问题背景

调用三方平台接口 偶尔会访问不到,导致了逻辑错误

具体描述
  1. 由于工作职责重新划分,我新接手维护了一个项目,这个项目已经开发完成,项目中需要和第三方平台进行对接,主要是我方向对方推送数据

  2. 但是刚接手没几天,实施同事就反馈过来一个问题,我们推送过去的数据在对方那边显示重复了,同一笔数据有好几条

  3. 和同事沟通知道了这个问题之前就出现过,算是一个疑难问题,之前有临时解决方案,我就先临时处理了

解决思路
  1. 那么该如何彻底解决这个疑难问题呢,我开始仔细读相关的代码,读了几遍 已经看懂代码的意思,按照代码逻辑理论上 不会有问题,原代码考虑的比较全面了

  2. 代码中找不出问题,我开始根据出错时间查日志,果然发现了一个异常

Failed to create service. 
at org.apache.cxf.jaxws.ServiceImpl.initialize

和对方之间的通信是用的 webservice技术,但是这个webservice会偶尔访问不到, 通过对比日志和代码,发现这个异常代码里并没有预判到,而是异常向上抛出了,并导致了一系列问题,比较重要的是 影响了数据库事务提交, 由于事务没提交,一部分数据实际已经推送,导致被误认为未推送,下一次推送时进行了重新推送,最终导致了数据重复现象

具体办法
  1. 我第一时间想到的方式是 catch住这个异常,不要向上抛出异常,起码保证数据库事务正常提交。这种思路 不会影响其他数据推送,只影响极少部分的数据, 但是仔细想想可能会出现 数据漏推的问题

  2. 那么有没有更好的方式解决这个问题呢,我又想到了重试机制:如果一次失败,就多试几次。 根据日志排查发现webservice只是偶尔访问不到,相同时间点附近是有成功访问到的, 那么重试时就很有可能会成功。

  3. 基本确定思路后,怎么写代码呢,我想到了Spring retry组件, 我之前用过一次这个组件,也写过一个文档记录如何使用,包括最近看《左耳听风》大神也提到了这个组件。于是很快编写了代码,主要逻辑是 尝试重试5次,每隔2s执行一次, 如果5次后依然有问题就给我发个异常通知,我再手动处理。经过测试环境测试结果符合预期,现在已经开始上线运行。

思考和延伸

编写代码时,我很快就完成了编写,并没有费什么劲,我觉得要归功于之前记录的一个文档,更加体会到日常记录文档的好处。

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Retry 是一个用于在失败情况下自动重试的库。它提供了一些注解和模板来简化重试逻辑的编写和配置。 要使用 Spring Retry,首先需要将其添加为项目的依赖项。在 Maven 项目中,可以通过在 pom.xml 文件中添加以下依赖项来实现: ``` <dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> <version>1.3.1</version> </dependency> ``` 然后,在需要进行重试的方法上添加 @Retryable 注解。该注解可以指定重试的次数、重试的异常类型以及可选的回退方法。例如: ```java import org.springframework.retry.annotation.Retryable; @Retryable(value = {CustomException.class}, maxAttempts = 3, backoff = @Backoff(delay = 1000)) public void retryMethod() throws CustomException { // 重试逻辑 } ``` 在上面的示例中,retryMethod() 方法将在捕获 CustomException 异常时进行最多三次重试。每次重试之间会等待 1000 毫秒。 最后,需要在 Spring 的配置类上添加 @EnableRetry 注解以启用重试功能。例如: ```java import org.springframework.context.annotation.Configuration; import org.springframework.retry.annotation.EnableRetry; @Configuration @EnableRetry public class AppConfig { // 配置类内容 } ``` 这样,Spring Retry 就会自动在发生异常时触发重试逻辑。 需要注意的是,Spring Retry 默认只会重试在方法内部抛出的异常,而不会重试外部异常(例如网络故障)。如果需要对外部异常进行重试,可以通过自定义 RetryPolicy 或使用 Spring 的 AspectJ 功能来实现。 希望这些信息能帮助到你使用 Spring Retry。如果有任何进一步的问题,请随时提问!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值