RocketMQ原理学习--消费者消费消息

版权声明:欢迎转载 https://blog.csdn.net/qq924862077/article/details/84797525

        在之前的一篇博客《RocketMQ原理学习--消息类型》中我们有介绍过RocketMQ的消息类型,这篇博客我们简单介绍一下RocketMQ消费者是如何消费消息的。

一、Pull or Push

        简单来说RocketMQ给我们提供了两种消息消费方式,Pull模式和Push模式,简单理解我们可能会认为Pull模式是消费者主动去拉取消息,Push模式是RocketMQ的Broker主动将消息推送过来,其实RocketMQ对于这两种方式都是采用的Pull拉取的方式,Push模式不过是通过回调来实现的,让我们理解为推送模式

1、Push示例:

提供一个MessageListenerConcurrently监听器,当存在消息时会回调这个类的consumeMessage方法。

public class PushConsumer {

    public static void main(String[] args) throws InterruptedException, MQClientException {
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("rmq-group");
        consumer.setNamesrvAddr("localhost:9876");
        //consumer.setInstanceName("rmq-instance2");
        consumer.subscribe("TopicA-test", "TagA");

        consumer.registerMessageListener(new MessageListenerConcurrently() {
            public ConsumeConcurrentlyStatus consumeMessage(
                    List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
                for (MessageExt msg : msgs) {
                    System.out.println(new String(msg.getBody()));
                }
                return ConsumeConcurrentlyStatus.RECONSUME_LATER;
            }
        });
        consumer.start();
        System.out.println("Consumer Started.");
    }

2、Pull模式:

维护MessageQueue和消息offset不断的去拉取消息。

public class PullConsumer {


    private static final Map<MessageQueue, Long> OFFSE_TABLE = new HashMap<>();

    public static void main(String [] args) throws Exception{


        DefaultMQPullConsumer consumer = new DefaultMQPullConsumer("rmq-group");

        consumer.start();

        Set<MessageQueue> mqs = consumer.fetchSubscribeMessageQueues("TopicA-test");
        for (MessageQueue mq : mqs) {
            System.out.printf("Consume from the queue: %s%n", mq);
            SINGLE_MQ:
            while (true) {
                try {
                    PullResult pullResult =
                            consumer.pullBlockIfNotFound(mq, null, getMessageQueueOffset(mq), 32);
                    System.out.printf("%s%n", pullResult);
                    putMessageQueueOffset(mq, pullResult.getNextBeginOffset());
                    switch (pullResult.getPullStatus()) {
                        case FOUND:
                            break;
                        case NO_MATCHED_MSG:
                            break;
                        case NO_NEW_MSG:
                            break SINGLE_MQ;
                        case OFFSET_ILLEGAL:
                            break;
                        default:
                            break;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        consumer.shutdown();
    }

    private static long getMessageQueueOffset(MessageQueue mq) {
        Long offset = OFFSE_TABLE.get(mq);
        if (offset != null)
            return offset;

        return 0;
    }

    private static void putMessageQueueOffset(MessageQueue mq, long offset) {
        OFFSE_TABLE.put(mq, offset);
    }


}

二、执行流程

1、Push模式:

对于Push模式,RocketMQ提供了PullMessageService线程,定时不断的从RocketMQ中拉取消息,最终来回调MessageListener的consumeMessage方法来消费消息,如下执行流程图:

猜你喜欢

转载自blog.csdn.net/qq924862077/article/details/84797525