会是调用第三方接口那么简单吗?
最近有个项目需要本地处理之后,然后调用第三方接口,本来开始觉得很简单得事情,不就是调用第三方接口吗?但是却一波三折。
初版
首先有了下面的第一版的设计。
这个设计很简单,也是最容易想到的。主要有下面几步
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、系统调用量;
好了,读到这里的小伙伴,不知道对于调用第三方接口,有没有其他的想法,欢迎交流哦。
感谢分享、关注、收藏。公众号:【良工说技术】
版权声明: 本文为 InfoQ 作者【高端章鱼哥】的原创文章。
原文链接:【http://xie.infoq.cn/article/9b6d7490549eb9deed953ac03】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论