最近有个项目需要本地处理之后,然后调用第三方接口,本来开始觉得很简单得事情,不就是调用第三方接口吗?但是却一波三折。
初版
首先有了下面的第一版的设计。
这个设计很简单,也是最容易想到的。主要有下面几步
1、本地处理;
2、调用第三方接口;
3、本地日志打印,包括是否调用成功及失败原因等;
看似很简单的过程,却在线上出了问题,我们说看一个功能是否稳定,不是看99.9%的正常,而是看0.01%的失败。没错,线上报错了,问题出现在调用第三方接口的时候由于网络问题,超时了,真尴尬,
分析这个方案有以下几个不足,
1、没有重试功能;
2、调用接口记录未持久化;
为此在第一版的基础上做了修改;
优化版本
优化版本考虑了上面的两个不足之处,对调用第三方接口进行了重试,且把调用记录写进本地表;
改进方案有几个需要注意的地方,
1、重试,由于是第一次调用失败便要重试,要注意重试的次数,可以在系统中设计一个最大重试次数(比如5次),超过最大重试次数不再重试,每次的重试可以有一定的间隔,可以采用当前线程睡眠的方式,睡眠的时间可以随着重试次数增大二增加;
2、记录调用日志,这里调用日志记录在mysql中,mysql的表结构可参考,
另外,由于包含重试,对于调用日志的话,考虑是否要区分重试日志;还有一点就是是否需要一个最终的调用结果。
改进版上线后,返现确实线上调用第三方接口失败的情况很少了,但是还是存在失败的情况,由于已经把调用记录保存在了mysql中,为此针对重试仍然失败的情况可以单启一个定时任务,
好了,有了定时任务,针对调用失败的情况可以进行再次执行,那么成功的几率就很高了,换而言之失败的情况很少了。
如果还是有失败的情况,那么应该从调用方式、第三方接口是否正常等方面去排查,程序方面很难有所改进了。
其实针对重试这块还可以直接使用定时,这种情况对于实时性要求不高的情况完全可以,也就是下面的样子,
这就是直接定时扫描调用记录表,定时执行。不过,仍然会出现一直失败的情况,那就陷入死循环了,可以针对扫描范围作一个限制,比如最近7天的记录,超过这个时间即使失败也不会再执行定时重调了。
除了在程序中作重试外还有其他方案吗?
最优版本吗
日常的开发中肯定都用过MQ,用来生产及消费消息,那么这里的重试便可以使用MQ,把第一次调用第三方接口失败作为消息投递到MQ,再重启另外的服务去消费MQ,在消费者中进行重试。
这种方案适合调用第三方接口较多,而且对主程序性能要求较高的情况,把重试从主程序中分离开,可以避免重试成为影响程序性能的瓶颈。
这个方案的优点是将重试和主程序分割开来,起到了解耦的作用。可能有不少会问消费MQ如果第一次执行失败怎么办,MQ已经考虑到这个问题了,MQ可以重发,感兴趣的小伙伴可以了解下哦。
总结,通过上边的几种方案,可以看到调用第三方接口看似简单,其实内含玄机。到底采用哪种方案要根据实际情况而定,不要因为想使用什么技术而去采取相应的方案,只有适合的才是最好的。可以从下面几个方面考虑,
1、系统性能;
2、实时性;
3、系统调用量;
好了,读到这里的小伙伴,不知道对于调用第三方接口,有没有其他的想法,欢迎交流哦。
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.fwqtg.net
1 AQS AbstracQueuedSynchronizer简称AQS,很重要!有多重要呢?看看附图就知道了! 可以毫不夸张的说是AQS是java代码实现锁的基础,更是线程池的基础! AQS的实现原理是一个先入先出的等待队列! 子类必须定义更改此状态的受保护…