MQ PUSH/PULL

作为一个消息系统,消息的传递是一块核心内容,最近在看amq的consumer消费的时候,突然想分析下推拉模式的优劣。好,闲话不多说,来点干货。
消息系统必不可少的就是消息的 push 和 pull了。事实上,push模式和pull模式各有优劣。比如Facebook的Scribe和Cloudera的Flume,AMQ 采用push模式。
Kafka这种新型的消息队列采用2种模式,选择由Producer向broker push消息并由Consumer从broker pull消息。


push模式
在push方式里,是由consumer把轮询过程封装了,并注册MessageListener监听器,取到消息后,唤醒MessageListener的consumeMessage()来消费,对用户而言,感觉消息是被推送过来的。常见的push模式如storm的消息处理,由spout负责消息的推送。该模式下需要一个中心节点,负责消息的分配情况(哪段消息分配给consumer1,哪段消息分配给consumer2),同时还要监听consumer的ack消息用于判断消息是否处理成功,如果在timeout时间内为收到响应可以认为该consumer挂掉,需要重新分配sonsumer上失败的消息。而且容易冲垮consumer,虽然可以向amq那样使用prefetch limit  和预留缓冲区 ,但是还是不能解决由consumer的选择性消费。
使用场景:
push模式很难适应消费速率不同的消费者,因为消息发送速率是由broker决定的。push模式的目标是尽可能以最快速度传递消息,但是这样很容易造成Consumer来不及处理消息,典型的表现就是拒绝服务以及网络拥塞。而pull模式则可以根据Consumer的消费能力以适当的速率消费消息。


pull模式
取消息的过程需要用户自己写,根据offset取得消息,kafka中的offset是有zk管理(具体不叙述细节)。由consumer决定消息的消费情况,这种模式有一个好处是我们不需要返回ack消息,因为当consumer申请消费下一批消息时就可以认为上一批消息已经处理完毕,也不需要处理超时的问题,consumer可以根据自己的消费能力来消费消息。但是pull最大问题是实时性问题,对于现在的MQ系统,对latency的追求越来越高,这个时候纯粹的Pull模式将满足不了实时性方面的需求。这时可以采用动态push/pull方式。
consumer在pull的时候,告诉broker自己buffer中可用的容量,整个流程如下:
1、consumer请求broker,告诉broker本地的可承载量,比如500
2、broker在收到消息后,如果没有消息则进入long polling状态
3、当有消息的时候,broker直接向consumer进行push,总共push的数据量为500
4、在整个push期间,consumer无需重新pull,即可获取数据
5、由于broker知道最大容量,所以无需担心被冲垮。
这样也不用担心consumer 被冲垮。


使用场景:
简化Broker的设计,consuemr根据自己的消费能力以适当的速率消费信息;

参考:
http://lifestack.cn/archives/387.html
http://wangzzu.github.io/2016/03/09/kafka-transmit/

你可能感兴趣的:(技术)