在很多业务中,都需要和外部的一些机构进行交互,比如在电商场景,在发货环节,需要和各个快递公司做交互进行发货、物流更新。聚合支付场景需要和外部支付渠道做交互实现支付等。
很多时候,我们自己的可用性可以有一些保障的,但是,外部机构的可用性是没办法保证的,比如双十一大促期间,支付方式除了支付宝之外,还可能用银行卡支付,但是很难保证银联系统可以抗这么高的并发。、、
那么,遇到这样的情况,外部机构的SLA不可靠时,如何避免自己的应用不被拖垮呢?
主要有几个思路:
1、异步交互
2、文件交互
3、超时机制
4、限流降级熔断
5、业务取舍
首先比较容易想到的就是和机构之间不要进行同步交互,同步交互的话会把所有的流量都发送到外部合作方,并且本系统还要同步等结果,不仅会浪费系统资源,还会让系统整体响应变慢。
在有些场景中,可以考虑和机构进行异步交互。
比如,我们在电商网站上做一些金融产品的时候,比如天猫运费险,当用户下单以后,要给买家投保一笔运费险。
这个场景,运费险投保是必须要成功的,因为买家下单时已经看到自己有运费险了,所以必须要让他能享受这个服务。(如果有些用户不应该享受,那就应该在展示的时候就拦截,而不是先展示,后拒绝)
像这个场景,我们如果每一笔都去调保险公司的话,那大概率他们是扛不住这个业务量的。而运费险投保如果稍微晚一会,在小时级别的话,理论上对业务是无损的,因为一般不太可能几个小时内就发货,收货,退货。
所以,我们就可以异步的和外部的保险公司进行交互,通过定时任务或者延迟消息的方式,和保司交互,这样可以起到削峰填谷的作用,并且这个链路可以不断重试,即使失败了,也不会影响到正常的下单主流程。
文件交互是一种异步交互的极端例子,他在异步的基础上还做了批次。把之前的每单异步,变成了批量异步。
比如电商业务中,商家发货时,需要生成快递单号,但是这些快递单号如果实时去快递公司获取的话,那就有一定的失败的概率。
所以就可以事先先从快递公司申请一个批次的快递单号,然后自己本地发货时直接用,然后在批量的通知给快递公司就行了。
这种批量可以是一个接口调用,也可以用文件。用文件的好处就是甚至都不需要接口交互,只需要把文件生成好上传到FTP中,对方自己下载后解析就行了。
在做外部接口交互时,并不是所有的情况都可以做异步,比如说高德的聚合打车。
当我们输入完出发点和目的地之后开始叫车时,他就需要实时的和各个租车平台对接交互,然后分发这笔订单。
这个过程就要同步交互,但是我们需要给每个第三方平台都设置一个请求的超时时间,比如2秒钟,超过2秒钟就自动中断了。而不是让用户一直在前端的等。
并且根据这种外部接口的响应时间的数据,我们可以做一些动态的负载均衡,把更多的流量分发给性能更好的服务商。
接口如果超时很严重,我们也需要对他做限流、降级和熔断。
限流:就是假如他的接口就能扛100QPS,那么我们就需要不能给他超过100的并发请求,那样他会处理不过来,导致整体性能下降。
降级:假如查询一个用户中心的服务查用户名,但是接口响应慢,那么就可以暂时降级,直接返回"陌生人"或者“用户名加载中”等信息。
熔断:假如外部某个接口特别慢,那么就可以干脆就不要再调他了。
这样做对业务是有损的。比如大促当天,银联的接口性能太差了,我们把银联降级掉,那么用户就会无法用银联支付了。对用户来说就少了个选择。
但是对于我们的系统来说,起到了很好的保护作用。可以在外部接口性能恢复以后再恢复调用就行了。
大家知道最开始余额宝被做出来主要是干嘛的吗?其实最初是为了解决支付成功率低的问题的。
大促期间就是因为银联等外部渠道支付成功率太低了,但是很多人又因为银行有收益所以把钱存在银行。
那为了解决这个问题,一个好的办法,就是在业务上给用户多一个选择,让用户减少使用银行卡支付的概率。
就假如说,高德聚合打车,发现外部服务商技术都太差了,他做了自营,是不是也能大幅度降低对外部机构的依赖问题呢?