通过上一节的讲解,相信读者对消息队列有了一个初步的认识,那么我们平时什么时候可能会用到消息队列呢?接下来将通过图1-2中的例子介绍消息队列的适用场景。
业务系统在超高并发场景中,由于后端服务来不及同步处理过多、过快的请求,可能导致请求堵塞,严重时可能由于高负荷拖垮We b服务器。
我们都希望流量如图1-3虚线部分一样一直比较平稳,这样我们的系统也会更加稳定。但是实际的流量会随着时间不短变化,像12306 App这样的App流量大得难以想象,而一年中不同的时间段,其流量也不同,如图1-3曲线所示。为了能支持最高峰流量,我们通常采取短平快的方式——直接扩容服务器,增加服务端的吞吐量。
图1-3
优点是显而易见的,短时间内吞吐量增加了好几倍,甚至数十倍。缺点也明显,流量低峰期服务器相对较闲。
如何平衡平时的空闲与节假日的超高峰呢?我们想到了消息队列(比如 Apache RocketMQ,Apache Kafka),也是目前业界比较常用的手段。利用消息队列扭转处理订票请求,告知用户 30min 内会告诉他/她订票结果。优缺点明显:性能提升了,但是我们作为业务开发人员,还要维护一个消息队列服务,人手完全不够。消息中间件呼之欲出。
不同的业务端在联合开发功能时,常常由于排期不同、人员调配不方便等原因导致项目延期。其实,其根本原因是业务耦合过度。
如图1-4所示,上下游系统之间的通信是彼此依赖的,所以不得不协调上下游所有的资源同步进行,跨团队处理问题显然比在团队内部处理问题难度大。
图1-4
你是否依稀记得另一个团队的同事调用你的API,你告诉他发个请求过来,你打断点一步一步调试代码的场景?
你是否记得为了协调开发资源、QA 资源,以及协调上线时间等所做的一切,你被老板骂了多少次,最后还是延期了:我们依赖他们,他们的QA说,高峰期不让发布。
加入消息队列后,不同的业务端又会是何种情况呢?如图1-5所示,上下游系统进行开发、联调、上线,彼此完全不依赖,也就是说,系统间解耦了。
图1-5
处理订票请求是一个漫长的过程,需要检查预订的车次是否有预订数量的票、下单扣库存、更新缓存等一系列操作。这些耗时的操作,我们可以通过使用消息队列的方式,把提交请求成功的消息告诉用户。然后异步处理这些耗时的操作,保证30min内能把处理的结果通过短信推送给用户,否则系统处理多久,用户就会等多久。
我们举例说明。很怀念每月的1号,可以向老婆的“财务部”缴费了。你的工资在招商银行,你老婆的工资在北京银行。通常,两个系统的通信过程如图1-6所示。
图1-6
如果通信失败,怎么保证你的钱“上交”了呢?业内常用的手段就是消息队列。消息系统的优点:
(1)免去了招商银行App多次重试(发起请求)的复杂逻辑。
(2)免去了北京银行App处理过多重试请求的压力。
(3)即使北京银行服务不可用,业务也不受影响。