kafka消息中间件

聊聊消息中间件Push模型和Pull模型优缺点

2019-03-17  本文已影响60人  longxingxiu

目录

一 、常用消息中间件支持模型
二、消费端Push模型优缺点
三、消费端Pull模型优缺点
四、两种模型在实际场景中的优缺点分析
五、常见消息中间Push和Pull实现实战和客户端源码分析

这篇文章前,先抛出个问题

当然不是,如果没有服务端Broker支持,它如何知道消费端当前选取的消息消费模型,准确讲推拉模型是指消息的消费模型,需要服务端Broker支持,也需要消费端Client支持。(通常服务端Broker和消费端Client都是互相配合工作的,一起开发,一起作用的)。

 
 

一、常用消息中间件支持模型

中间件 push模型 pull模型
RabbitMQ 支持 支持
Kafka --- 支持(只有)
RabbitMQ 支持 支持

\color{red}{我们通常所说的push模型和pull模型都是指的消息的消费模型。}

二、两种模型优缺点对比

Push 和 Pull 的区别

举个例子:
消息=食物;服务端Broker=老爸;消费端 = 儿子

  • 如果采用Push模型:
    优点:老爸一拿到食物就给儿子吃【食物送达及时】
    缺点:儿子已经吃跑了,老爸还强塞儿子吃,可能导致儿子被撑死【儿子不堪重负,撑死了】

  • 如果采用Pull模型
    优点:儿子饿了,主动找老爸要食物,不饿的时候不要。【儿子根据饥饿程度获取食物】
    缺点:儿子饿了,发消息给老爸给我点食物,等老爸收到消息已经过了十分钟了,儿子等不及了饿死了。【食物没有及时送给儿子】

\color{red}{所以说两种模型各有利弊,根据业务需求和实际业务量来选择。}

Push模型优缺点

Pull模型优缺点

三、两种模型在实际场景中的优缺点分析

选择 Push 还是 Pull

简要分析下 Push 和 Pull模型,在不同场景下各自存在的利弊。

场景 1:Producer 的速率大于 Consumer 的速率

对于 Producer 速率大于 Consumer 速率的情况,有两种可能性需要讨论:

Push方式由于无法得知当前 Consumer 的状态(\color{red}{Push模型不管消费者有没有消费,都会往消费订阅者推动并缓存到消费者队列中}),所以只要有数据产生,便会不断地进行推送,在以上两种情况下时,可能会导致 Consumer 的负载进一步加重,甚至是崩溃(比如生产者是 flume 疯狂抓日志,消费者是 HDFS+hadoop,处理效率跟不上)。除非Consumer 有合适的反馈机制能够让服务端知道自己的状况。(也可以 通过消费端限流方案,比如RabbitMQ消费者设置Qos,服务端Borker就会限制对消费端的发送流程,但是这个流量设置就需要衡量,不能太大也不能太小)

而采取 Pull 的方式问题就简单了许多,由于 Consumer 是主动到服务端拉取数据,此时只需要降低自己访问频率就好了。举例:如前端是 flume 等日志收集业务,不断往 CMQ 生产消息,CMQ 往后端投递,后端业务如数据分析等业务,效率可能低于生产者。

场景 2:强调消息的实时性

场景 3:Pull 的长轮询

Pull 模式有什么问题呢?由于主动权在消费方,消费方无法准确地决定何时去拉取最新的消息。如果一次 Pull 取到消息了还可以继续去 Pull,如果没有 Pull 取到消息则需要等待一段时间再重新 Pull。

但等待时间就很难判定了。你可能会说,我可以有xx 动态拉取时间调整算法,但问题的本质在于,有没有消息到来这件事情决定权不在消费方。也许 1 分钟内连续来了 1000 条消息,然后半个小时没有新消息产生,可能你的算法算出下次最有可能到来的时间点是31分钟之后,或者 60 分钟之后,结果下条消息 10 分钟后到了,是不是很让人沮丧?

当然也不是说延迟就没有解决方案了,业界较成熟的做法是从短时间开始(不会对 CMQ broker 有太大负担),然后指数级增长等待。比如开始等 5ms,然后 10ms,然后 20ms,然后 40ms……直到有消息到来,然后再回到 5ms。即使这样,依然存在延迟问题:假设 40ms 到 80ms 之间的 50ms 消息到来,消息就延迟了 30ms,而且对于半个小时来一次的消息,这些开销就是白白浪费的。

总之就是消费端长时间没有消息消费的话,消费端轮训时间间隔如果太长,可能在轮训间隔中让部分消息延时消费,如果轮训时间太短,则频繁的请求在消耗服务端Broker,broker要应答消费端的请求(线程开销等)而造成服务端Broker的负担。

在腾讯云的 CMQ 里,有一种优化的做法-长轮询,来平衡 Pull/Push 模型各自的缺点。

基本方式是:消费者如果尝试拉取失败,不是直接 return,而是把连接挂在那里 wait,服务端如果有新的消息到来,把连接拉起,返回最新消息。

场景 4:部分或全部 Consumer 不在线

在消息系统中,Producer 和 Consumer 是完全解耦的,Producer 发送消息时,并不要求Consumer 一定要在线,对于 Consumer 也是同样的道理,这也是消息通信区别于 RPC 通信的主要特点;但是对于 Consumer不在线的情况,却有很多值得讨论的场景

折中的方案是:MQ 给数据设定一个超时时间,当 Consumer 宕机时间超过这个阈值时,则清理数据;但这个时间阈值也并太容易确定。

参考文章:
1 、选择 Push 还是 Pull(腾讯消息中间件CMQ技术文档)
2、 RabbitMQ之Consumer消费模式(Push & Pull)(厮大文章,抓包说明Push模型不会等待消费者是否消费完成前一个消息,就会发送第二个消息)。

上一篇下一篇

猜你喜欢

热点阅读