RocketMQ 2:集群消费、广播消费-推模式


推模式
代码上使用 DefaultMQPushConsumer
这种模型下,系统收到消息后自动调用处理函数来处理消息,自动保存 Offset,并且加入新的消费者后会自动做负载均衡。
底层实现上,推模式还是使用的 pull 来实现的,pull 就是拉取,push 方式是 Server 端接收到消息后,主动把消息推给 Client 端,实时性高。但是使用 Push 方式有很多弊端,首先加大 Server 端的工作量,其次不同的 Client 端处理能力不同,Client 的状态不受 Server 控制,如果 Client 不能及时处理 Server 推送过来的消息,会造成各种潜在问题。
所以 RocketMQ 是通过“长轮询”的方式,同时通过 Client 端和 Server 端的配合,达到既拥有 Pull 的优点,又能达到确保实时性的目的。
集群
使用相同 Group ID 的订阅者属于同一个集群。同一个集群下的订阅者消费逻辑必须完全一致(包括 Tag 的使用),这些订阅者在逻辑上可 以认为是一个消费节点。

集群消费

当使用集群消费模式时,消息队列 RocketMQ 认为任意一条消息只需要被集群内的任意一个消费者处理即可。

1.创建消费者PushConsumerA,PushConsumerB,PushConsumerC,内部代码完全一样,消费同一个群组group1

在这里插入图片描述

package org.example.normal;

import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
import org.apache.rocketmq.common.message.MessageExt;

import java.util.List;

/**
 * 消费者-推模式
 **/
public class PushConsumerA {
    public static void main(String[] args) throws MQClientException {
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("group1");
        consumer.subscribe("TopicA", "*");
        consumer.setNamesrvAddr("192.168.42.112:9876");
        consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET);//每次从最后一次消费的偏移量开始消费
        consumer.registerMessageListener(new MessageListenerConcurrently() {
            public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
                System.out.println("queueID:"+list.get(0).getQueueId());
                System.out.println("ThreadName:"+Thread.currentThread().getName());
                System.out.println("Messages:" + new String(list.get(0).getBody()));
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            }
        });
        consumer.start();
        System.out.println("ConsumerPartOrder Started.");
    }
}
2.启动3个消费者

在这里插入图片描述

3.使用单向发送生产10条消息

在这里插入图片描述

4.查看打印,一个queue只能被一个消费者消费

PushConsumerA

ConsumerPartOrder Started.
queueID:3
ThreadName:ConsumeMessageThread_4
Messages:Hello RocketMQ3
queueID:3
ThreadName:ConsumeMessageThread_5
Messages:Hello RocketMQ7

PushConsumerB

ConsumerPartOrder Started.
queueID:0
ThreadName:ConsumeMessageThread_1
Messages:Hello RocketMQ0
queueID:1
ThreadName:ConsumeMessageThread_2
Messages:Hello RocketMQ1
queueID:0
ThreadName:ConsumeMessageThread_3
Messages:Hello RocketMQ4
queueID:0
ThreadName:ConsumeMessageThread_4
Messages:Hello RocketMQ8
queueID:1
ThreadName:ConsumeMessageThread_5
Messages:Hello RocketMQ5
queueID:1
ThreadName:ConsumeMessageThread_6
Messages:Hello RocketMQ9

PushConsumerC

ConsumerPartOrder Started.
queueID:2
ThreadName:ConsumeMessageThread_1
Messages:Hello RocketMQ2
queueID:2
ThreadName:ConsumeMessageThread_2
Messages:Hello RocketMQ6

广播消费

当使用广播消费模式时,消息队列 RocketMQ 会将每条消息推送给集群内所有注册过的客户端,保证消息至少被每台机器消费一次。

5.创建消费者BroadConsumerA,BroadConsumerB,BroadConsumerC,代码完全一样,设置消费模式为广播模式

在这里插入图片描述

package org.example.broadcast;

import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.protocol.heartbeat.MessageModel;

import java.util.List;

/**
 * 消费者-广播消费
 **/
public class BroadConsumerA {
    public static void main(String[] args) throws MQClientException {
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("group1");
        consumer.subscribe("TopicA", "*");
        consumer.setNamesrvAddr("192.168.42.112:9876");
        consumer.setMessageModel(MessageModel.BROADCASTING);//设置消费模式为广播模式
        consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET);//每次从最后一次消费的偏移量开始消费
        consumer.registerMessageListener(new MessageListenerConcurrently() {
            public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
                System.out.println("queueID:"+list.get(0).getQueueId()+",ThreadName:"+Thread.currentThread().getName()
                        +",Messages:" + new String(list.get(0).getBody()));
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            }
        });
        consumer.start();
        System.out.println("ConsumerPartOrder Started.");
    }
}
6.启动3个消费者

在这里插入图片描述

7.使用单向发送生产10条消息

在这里插入图片描述

8.查看打印,3个消费都消费了10条消息

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值