依赖外部接口过多时,如何提升写服务稳定性?

1,123 阅读4分钟

本文源于mp.weixin.qq.com/s/_1pZ8ShmE… 作者:潘新宇

关注公众号:勾勾的Java宇宙(Javagogo)


完成一个写请求时,不仅需要依赖存储,大部分场景还需要依赖各种外部第三方提供的接口。

  • 当你发布一条微博,在数据存储至数据库前,不仅需要依赖用户模块校验用户的有效性,还需要依赖安全过滤非法内容等;

  • 在创建订单时,同样是先要校验用户有效性、再校验用户的收货地址合法性,以及获取最新价格、扣减库存、扣减支付金额等。完成上述的校验和数据获取,最后一步才是写入存储。

  • 其他的写场景,比如发布短视频、发布博客等亦是如此。

上述几种场景的架构如下图所示:

插图-11.jpeg

对于整个链路依赖的各项外部接口,可能是出现了以下几个问题,导致系统不可用:

  1. 外部接口性能抖动严重,比如从 50ms 飙升至 500 ms,进而导致你的接口超时,此时会影响你的系统可用率
  2. 完成上述某一个写业务时,如果需要依赖外部的接口过多,也会导致你的接口性能太差
  3. 外部接口可用率下降,也会影响你的系统的可用率

当依赖外部接口过多时,可以从几个方面进行优化,来提升整体的性能和写接口的稳定性。

将依赖接口串行改并行

假设一次写请求要依赖二十个外部接口,可以将这些依赖全部并行化,优化的架构如下图所示:

插图-12.jpeg

如果一个依赖接口的性能为 10ms,以串行执行的方式,请求完所有外部依赖就需要 200ms(10ms×20)。但改为并行执行后,只需要 10ms 即可完成。

上述情况中,我们假设每个接口的性能都是 10ms,但在实际场景中并没有这么精确的数字,有的外部依赖可能快一点、有的可能慢一点。实际并行执行的耗时,等于最慢的那个接口的性能。

全部外部依赖的接口都可以并行是一种理想情况。

接口能否并行执行有一个前置条件:两个接口间没有任何依赖关系。

如果 A 接口执行的前置条件是需要 B 接口返回的数据才能执行,那么这两个接口则不能并行执行。按相互依赖梳理后的并行执行方案如下图所示。对于并行中存在相互依赖的场景,并行化后的性能等于最长子串(下图中红色框)的性能总和。

插图-13.jpeg

依赖接口后置化

此外,虽然整个链路上会有较多外部接口,但大部分场景里,很多接口都是可以后置化的。后置化是指当接口里的业务流程处理完成并返回给用户之后,后置去处理一些非重要且对实时性无要求的场景。

比如在提交订单后,用户只需要查看订单是否下单成功,以及对应的价格、商品和数量是否正确。而对于商品的详细描述信息、所归属的商家名称等信息并不会特别关心,如果在提单的同时还需要获取这些用户不太关心的信息,会给整个提单的性能和可用率带来非常大的影响。

鉴于这种情况,可以在提单后异步补齐这些仅供展示的信息。

采用依赖后置化后,需要增加一个异步 Worker 进行数据补齐。架构如下图所示:

插图-14.jpeg

对于一些可以后置补齐的数据,可以在写请求完成时将原始数据写入一张任务表。然后启动一个异步 Worker,异步 Worker 再调用后置化的接口去补齐数据,以及执行相应的后置流程(比如发送 MQ 等)。

通过依赖后置化移除一些不必要的接口调用,会提升你的写接口的整体性能和可用性。


本文源于mp.weixin.qq.com/s/_1pZ8ShmE… 作者:潘新宇

关注公众号:勾勾的Java宇宙(Javagogo)