文章目录
在分布式系统中,消息队列(Message Queue, MQ)是系统间通信、解耦的重要工具。通过标签(Tag)过滤,RocketMQ 可以让消费者有选择性地订阅感兴趣的消息,从而大大降低系统的通信成本和复杂度。本文将通过实例代码演示如何使用 RocketMQ 实现基于标签过滤的消息生产和消费。
1. 环境准备
在开始之前,请确保以下准备工作已完成:
- 安装并启动 RocketMQ 服务(包括 NameServer 和 Broker)。
- 在项目中引入 RocketMQ 的相关依赖。
假设我们已经在 pom.xml
文件中添加了以下依赖:
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
<version>4.9.3</version>
</dependency>
我们还需要在项目中定义 NameServer 地址。可以使用一个常量类 MqConstant
来存储该信息:
package com.takumilove.constant;
public class MqConstant {
public static final String NAME_SRV_ADDR = "localhost:9876"; // 替换为实际的 NameServer 地址
}
请将 localhost
替换为你的服务器地址,并确保防火墙已放行相关端口。
2. 生产者代码示例
生产者的主要任务是将消息发送到指定的主题(Topic)中,并为消息指定不同的标签(Tag),从而实现标签过滤。
以下是一个简单的消息生产者示例代码,它发送两条消息到 tagTopic
主题中,分别携带 vip1
和 vip2
标签。
package com.takumilove.demo;
import com.takumilove.constant.MqConstant;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.common.message.Message;
import org.junit.Test;
/**
* 标签过滤生产者示例
*/
public class GTagTest {
@Test
public void tagProducer() throws Exception {
// 1. 创建生产者实例并指定生产者组名
DefaultMQProducer producer = new DefaultMQProducer("tag_producer_group");
// 2. 设置 NameServer 地址
producer.setNamesrvAddr(MqConstant.NAME_SRV_ADDR);
// 3. 启动生产者
producer.start();
// 4. 创建并发送带有标签的消息
Message message1 = new Message("tagTopic", "vip1", "我是vip1的文章".getBytes());
Message message2 = new Message("tagTopic", "vip2", "我是vip2的文章".getBytes());
producer.send(message1);
producer.send(message2);
System.out.println("消息发送成功");
// 5. 关闭生产者
producer.shutdown();
}
}
说明
- 创建
DefaultMQProducer
实例,并指定生产者组名tag_producer_group
。 - 设置 NameServer 地址,并启动生产者。
- 创建消息,并为每条消息指定标签
vip1
和vip2
,然后将消息发送到tagTopic
主题中。 - 成功发送消息后,关闭生产者。
3. 消费者代码示例
接下来,我们编写两个消费者实例来消费不同标签的消息。
3.1 消费者1:只订阅 vip1
标签的消息
package com.takumilove.demo;
import com.takumilove.constant.MqConstant;
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.common.message.MessageExt;
import org.junit.Test;
import java.util.List;
public class GTagConsumerTest {
@Test
public void tagConsumer1() throws Exception {
// 1. 创建消费者实例并指定消费者组名
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("tag-consumer-group-a");
// 2. 设置 NameServer 地址
consumer.setNamesrvAddr(MqConstant.NAME_SRV_ADDR);
// 3. 订阅指定主题和标签
consumer.subscribe("tagTopic", "vip1");
// 4. 注册消息监听器
consumer.registerMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,
ConsumeConcurrentlyContext context) {
System.out.println("我是vip1的消费者,我正在消费消息: " + new String(msgs.get(0).getBody()));
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
// 5. 启动消费者
consumer.start();
System.out.println("vip1 消费者启动成功");
// 阻塞当前线程,保持消费者运行
System.in.read();
}
}
3.2 消费者2:订阅 vip1
和 vip2
标签的消息
@Test
public void tagConsumer2() throws Exception {
// 1. 创建消费者实例并指定消费者组名
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("tag-consumer-group-b");
// 2. 设置 NameServer 地址
consumer.setNamesrvAddr(MqConstant.NAME_SRV_ADDR);
// 3. 订阅指定主题和多个标签(使用 `||` 分隔符)
consumer.subscribe("tagTopic", "vip1||vip2");
// 4. 注册消息监听器
consumer.registerMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,
ConsumeConcurrentlyContext context) {
System.out.println("我是vip1或vip2的消费者,我正在消费消息: " + new String(msgs.get(0).getBody()));
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
// 5. 启动消费者
consumer.start();
System.out.println("vip1 和 vip2 消费者启动成功");
// 阻塞当前线程,保持消费者运行
System.in.read();
}
说明
tagConsumer1
只订阅vip1
标签的消息,并打印消费结果。tagConsumer2
订阅vip1
和vip2
标签的消息,并对所有匹配标签的消息进行消费和打印。
4. 运行示例
- 启动 RocketMQ 的 NameServer 和 Broker。
- 运行生产者方法
tagProducer()
发送消息。 - 分别运行
tagConsumer1()
和tagConsumer2()
,观察控制台输出。
通过上述步骤,可以看到 tagConsumer1
只消费了 vip1
标签的消息,而 tagConsumer2
消费了 vip1
和 vip2
标签的消息。
5. 总结
本文通过实际代码示例,详细介绍了如何使用 RocketMQ 实现基于标签过滤的消息生产和消费。通过标签过滤,消费者可以只接收感兴趣的消息,从而降低无用消息的传输,提高系统的性能和效率。