简介: POP Consumer—使客户端无状态,更轻量!
作者:凯易&耘田
前言:随着 RocketMQ 5.0 preview 的发布,5.0 的重大特性逐步与大家见面。POP Consumer 作为 5.0 的一大特性,POP 消费模式展现了一种全新的消费模式。其具备的轻量级,无状态,无队列独占等特点,对于消息积压场景,Streaming 消费场景等都非常友好。在介绍 POP Consumer 之前,我们先回顾一下目前使用较多的 Push Consumer。
Push Consumer
熟悉 RocketMQ 的同学对 Push Consumer 肯定不会陌生,客户端消费一般都会使用这种消费模式,使用这种消费模式也比较简单。我们只需简单设置,并在回调方法 ConsumeMessage 中写好业务逻辑即可,启动客户端应用就可以正常消费消息了。
public class PushConsumer { public static void main(String[] args) throws InterruptedException, MQClientException { DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("CID_JODIE_1"); consumer.subscribe("test_topic", "*"); consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET); consumer.registerMessageListener(new MessageListenerConcurrently() { @Override public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) { System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), msgs); return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; } }); consumer.start(); System.out.printf("Consumer Started.%n"); } }
那么 Push Consumer 是如何消费消息的呢?
当然,Consumer 收到消息的前提是 Producer 先发消息发到 Topic 当中。Producer 使用轮询的方式分别向每个 Queue 中发送消息,一般消费端都不止一个,客户端启动的时候会在 Topic,Consumer group 维度发生负载均衡,为每个客户端分配需要处理的 Queue。负载均衡过程中每个客户端都获取到全部的的 ConsumerID 和所有 Queue 并进行排序,每个客户端使用相同负责均衡算法,例如平均分配的算法,这样每个客户端都会计算出自己需要消费那些 Queue,每当 Consumer 增加或减少就会触发负载均衡,所以我们可以通过 RocketMQ 负载均衡机制实现动态扩容,提升客户端收发消息能力。
这里有个小问题:可以一直增加客户端的数量提升消费能力吗?当然不可以,因为 Queue 数量有限,客户端数量一旦达到 Queue 数量,再扩容新节点无法提升消费能力,因为会有节点分配不到 Queue 而无法消费。
客户端负责均衡为客户端分配好 Queue 后,客户端会不断向 Broker 拉取消息,在客户端进行消费。不是 Push 客户端吗?怎么会是客户端向 Broker 拉消息,不应该是 Broker 推消息到客户端吗?这是一个很有意思的点,因为 RocketMQ 无论是 Push Consumer,