昨天我们讨论了服务间是否应该提供批量接口的问题,很多同学留言讨论,非常好,一起讨论一起进步。
其中,留言最多的一种观点是说可以提供,但是要限制条数,比如每次最多传1000条数据过来。
说句实话,我们的项目很多也是这么做的。
不过我还是坚持我的观点,最好就不要提供批量接口。
因为随着数据量的不断增大,势必导致存储架构升级。
我们以商品查询为例,数据量变大,肯定是要上Redis的吧,以前批量接口可能直接一个数据库in就解决了,现在你是先走缓存还是不走呢?走的话要改代码,不走的话性能肯定不高。数据量再继续增大,分库分表了,批量接口怎么处理?上Elasticsearch了,怎么处理?
这里,我们举例是说的批量查询,如果换成批量操作呢?每次存储架构升级可能都要改这块的代码,而且还有另外一个操蛋的问题,比如你们规定服务间调用超时最大是1秒钟,超过1秒就有熔断逻辑,那么,你要不要单独为这个批量接口配置超时?
所以,批量接口极其容易形成瓶颈,需要花费巨大的代价去维护这个代码,还是不提供比较好。
当然,如果你们的数据量在可以预见的未来都不会增长到那么大,提供一个批量接口也不是不可以,视情况自行决定哈。(数据量都没有,还不赶紧跑路😂)
好了,关于昨天的问题先唠这么多,今天,我们看另外一个问题:对前端提供的批量接口,后端如何快速响应?有没有通用的解决方案呢?
首先,我们分析一下这个场景。
这里说的批量接口,肯定不是查询哈,而是批量操作类的接口,比如批量导入,批量发货,批量删除,批量流转,批量修改某种状态,等等,有很多,不过做2C系统的可能比较少见,一般2B的系统会有非常多这种批量的接口,往往他们也是系统中的顽固,需要投入很多精力不断打磨不断优化。
好了,场景我们清楚了,那么,怎么解决这类难题呢?
一般地,我们提供一个批量接口,前端传一堆id过来,或者数据过来,后端慢慢处理,处理完了再给前端返回,因为是2B的系统,用户也愿意等待。
但是,这里其实有很多问题,最典型的就是超时问题,超时这个问题说简单也简单,说复杂也复杂,以我们的系统为例,我们部署到华为云上面,可能会有这么几个超时的地方:
- 1、华为云的防火墙有超时;
- 2、华为云ELB有超时;
- 3、前端nginx有超时;
- 4、前端代码里写死了超时;
- 5、后端网关有超时;
- 6、后端服务有超时;
- 7、远程调用有超时;
所以,你看,一个超时问题能把你折磨死,而且,这种问题非常难排查,当然,你躺完一次这个坑之后后面可能会好很多。(所以,我为什么知道这么多地方可能有问题呢😂)
超时只是一个典型的问题,并不是全部,再说一个情形,以批量发货为例,晚上,很多商家都喜欢批量发货,比如一次1000条,这么多商家的请求呢,一不小心就会出现很多打到同一台机器上面去了,然后大家都在搞批量,都要申请大量的内存,都在搞内存,内存扛不住呀,然后就OOM了,这是典型的请求倾斜的问题,所以,怎么设置你的负载均衡策略呢?目前,并没有很好的解决方案。
基于以上这些可能会出现的问题,我一直在思考,能不能提供一种通用解决方案呢?
其实是有的,但是,要改原型。
比如,批量发货,本来状态只有未发货、已发货、发货失败,能不能加一个“发货中”呢?
别小看这个发货中的威力,真的很强大。
后端接收到批量发货这个请求,先检查数据的正确性,然后把数据库这些单据的状态改成发货中,接着把这些数据一个一个的丢到消息队列中,就可以返回了,前端查询的时候就显示发货中,旁边放一个刷新按钮。此时,用户完全去干别的事,比如去建商品,等会回来再看有没有发货完成或者发货失败的。
最后,有一组消费者不断的从消息队列中消费数据,调用物流服务发货等等。
经过这么一折腾,本来前端要hang死几分钟的请求几秒钟就返回了,用户体验上去了,也不用去搞超时、请求倾斜等问题了,解放了生产力,可以多划水了。
而且,这还是一个可以无限横向扩展的架构,随着用户量的不断增大,理论上来说,只要堆机器就可以了。
好了,关于前端批量接口的处理就到这里了。
最后,我想问,你们系统中是怎么处理前端批量接口的呢?
本文转载自微信公众号「彤哥读源码」,可以通过以下二维码关注。转载本文请联系彤哥读源码公众号。