背景:
我们的组件(简称A),在业务链中属于数据支撑节点。其中与组件B存在接口同步数据的直接关系(API接口直接调用进行数据交互)
问题:
我们的上游有另一个组件C(带有界面),调用A(us)进行数据的变更操作,此时需要A调用B服务接口进行同步,问题出在这里,C调用
A通常速度比较快,比较稳定,但是A调用B经常超时或者失败,网络原因or 组件B自己的设计原因吧,反正是推不动
方案:经沟通考察,这条数据的变更在可接受的时间范围只要最终一致即可,于是首先,我们先将事物中的调用B服务的一系列逻辑抽出来,
做成异步的,让C操作数据后能及时返回,在这个异步调用B服务接口同步过程中,出现异常时自动记录这次接口调用失败的日志,再开一个
Worker线程任务去轮询调用
设计:
1、第三方接口调用中,涉及增,删,改的逻辑脱离事物管理,异步执行
2、接口调用后出现异常,记录下该方法调用的详细日志到数据库表中
3、开启一个单独的任务轮询改表中待重试状态的记录,依次重试,重试成功或失败,均更改状态,对于重试若干次仍然失败的,界面上展示,通知排查
实现:
接口的异步调用就不讲了,springboot的异步方案很多,这里主要讲异常日志如何自动入库,并提供补偿
1、日志获取思路
(1)调用B服务的api接口异常时,需要抛出具体的异常,这里假设叫BusinessException,该异常继承RuntimeException,异常中可以带出错误码,错误描述等信息
(2)自定义收集日志的注解,作用在方法上,收集日志
(3)异常信息入库,注意使用摘要加密保证唯一性
2、单独开启一个线程处理收集的状态为待重试的记录,对调用失败的进行retry
编码:
1、自定义注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/**
* 自定义注解-处理调用第三方接口数据交互异常时日志收集
*
* RetentionPolicy.RUNTIME JVM在运行期也保留注解,可以通过反射机制读取注解信息
* ElementType.METHOD 方法上生效*/@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)public@interface ExceptionCollect {
String value()default "";
String beanName()default "";
}
自定义的属性可自行调整
2、定义注解的方法签名
importorg.aspectj.lang.ann