本文将详细介绍RocketMq原理项目实战,包括消息生产者与消费者的运作机制、消息发布与订阅的实际操作以及集群部署与监控等内容。RocketMq原理项目实战涵盖了从环境搭建到实际项目应用的全过程,帮助读者全面了解RocketMq的核心原理和实际应用。文章还将深入讲解RocketMq的集群部署和监控方法,确保读者能够掌握RocketMq的高级使用技巧。
RocketMq简介与环境搭建RocketMq的基本概念
RocketMq是一款基于Java语言开发的开源消息中间件,由阿里巴巴开源并贡献给Apache基金会,主要应用于分布式应用中高性能的消息传递,具有高吞吐量、高可用、高可扩展性等特性。它支持多种消息类型,包括单向消息、发布/订阅消息、顺序消息、事务消息等。
RocketMq的核心组件包括Broker、NameServer和Client。NameServer主要负责路由信息的管理和同步,而Broker是消息的生产和消费的路由器。消息的生产者和消费者通过NameServer来获取消息的路由信息,从而实现消息的可靠传递。
关键术语解释
- NameServer:负责NameServer集群的路由信息保存以及路由信息的广播,NameServer集群的任意节点宕机都不会影响其功能。
- Broker:消息中转角色,负责消息的存储、转发、消费,一个Broker上有多个消息队列。
- Producer:生产者,负责向指定Topic发送消息。
- Consumer:消费者,负责消费消息,从Topic消费消息。
- Topic:消息类型,定位具体的应用场景。
- Queue:消息队列,是消息物理存储的单位,一个Topic可以包含多个queue。
- Message:消息体,包含用户信息数据部分和消息属性。
开发环境搭建与配置
搭建开发环境
首先,你需要确保你的开发环境已经安装了Java 8及以上版本。RocketMQ基于Java开发,因此需要Java环境。此外,还需要下载并安装RocketMQ的最新版本。RocketMQ的最新版本可以从其官方仓库或Apache官方网站下载。
配置开发环境
- 下载RocketMq
wget https://archive.apache.org/dist/rocketmq/rocketmq-all-4.9.1-bin-release.zip
unzip rocketmq-all-4.9.1-bin-release.zip
cd rocketmq-all-4.9.1
- 启动NameServer
nohup sh bin/mqnamesrv &
- 启动Broker
nohup sh bin/mqbroker -n localhost:9876 &
- 验证环境
运行以下命令来验证RocketMQ是否安装成功,并检查NameServer和Broker是否正常运行。
sh bin/mqadmin clusterList localhost
输出信息应包含NameServer和Broker的相关信息,表明RocketMQ已经成功安装和启动。
配置RocketMq
RocketMQ的配置文件主要位于conf
目录下,包括broker.properties
、server.properties
等。这些文件中定义了RocketMQ的一些基本配置,如Broker的名称、IP地址、端口等。
- broker.properties
brokerClusterName=DefaultCluster
brokerName=broker-a
brokerId=0
deleteWhen=04
fileReservedDays=7
flushDiskType=ASYNC_FLUSH
brokerRole=ASYNC_MASTER
- server.properties
storePathRootDir=/home/rocketmq/store
storePathCommitLog=/home/rocketmq/store/commitlog
storePathConsumeQueue=/home/rocketmq/store/consumequeue
storePathIndex=/home/rocketmq/store/index
storePathLog=/home/rocketmq/store/log
storePathMeta=/home/rocketmq/store/meta
storePathCommitLog=/home/rocketmq/store/commitlog
storePathIndex=/home/rocketmq/store/index
配置完成后,可以使用RocketMQ提供的工具进行消息的发送和接收。
主题与队列的概念
Topic
Topic
是RocketMQ中消息的分类,可以理解为消息的类型或主题。生产者发送的消息需要指定一个Topic,消费者消费消息也需要指定一个Topic。Topic是唯一的,不同的Topic代表不同的消息类型。
Message msg = new Message(
"TopicTest", // Topic
"TagA", // Tag
("Hello RocketMQ "+i).getBytes(RemotingHelper.DEFAULT_CHARSET));
Queue
Queue
是消息在Broker上的物理存储单位。一个Topic可以包含多个Queue,每个Queue都有自己的索引文件和消息文件。RocketMQ通过Queue来实现消息的并发消费。
Message msg = new Message(
"TopicTest", // Topic
"TagA", // Tag
("Hello RocketMQ "+i).getBytes(RemotingHelper.DEFAULT_CHARSET));
集群部署的基础步骤
部署NameServer
- 启动NameServer
nohup sh bin/mqnamesrv &
部署Broker
- 配置Broker
在conf/broker.properties
文件中进行配置。
brokerClusterName=DefaultCluster
brokerName=broker-0
brokerId=0
deleteWhen=04
fileReservedDays=7
flushDiskType=ASYNC_FLUSH
brokerRole=ASYNC_MASTER
- 启动Broker
nohup sh bin/mqbroker -c conf/broker.properties &
部署多个Broker
- 配置多个Broker
在不同的Broker中分别配置broker.properties
文件,并设置不同的brokerId
。
- 启动Broker
nohup sh bin/mqbroker -c conf/broker-0.properties &
nohup sh bin/mqbroker -c conf/broker-1.properties &
监控工具的使用及详解
监控RocketMq
RocketMQ提供了多种监控工具,包括RocketMQ自带的mqadmin
命令和第三方监控工具如Prometheus等。
- 使用RocketMQ自带的监控工具
sh bin/mqadmin clusterList localhost
-
使用Prometheus监控RocketMq
- 安装Prometheus
下载并安装Prometheus。
wget https://github.com/prometheus/prometheus/releases/download/v2.35.0/prometheus-2.35.0.linux-amd64.tar.gz
tar -xvf prometheus-2.35.0.linux-amd64.tar.gz
cd prometheus-2.35.0.linux-amd64
- 配置RocketMQ与Prometheus集成
在prometheus.yml
文件中添加RocketMQ的监控配置。
scrape_configs:
- job_name: 'rocketmq-broker'
static_configs:
- targets: ['localhost:10911']
- job_name: 'rocketmq-namesrv'
static_configs:
- targets: ['localhost:10912']
- 启动Prometheus
./prometheus --config.file=prometheus.yml &
- 访问Prometheus
打开浏览器,访问http://localhost:9090
,可以查看RocketMQ的相关监控指标。
监控指标详解
RocketMQ提供的监控指标包括但不限于以下内容:
- Broker状态
{
"brokerAddr": "127.0.0.1:10911",
"brokerName": "broker-0",
"brokerVersion": "4.9.1",
"consumerNums": 1,
"producerNums": 1,
"diskUsedSize": 100,
"queueNums": 10,
"registerTopicNums": 5
}
- Topic状态
{
"topic": "TopicTest",
"queueNums": 10,
"queueSize": 50,
"consumerNums": 1,
"produceNums": 1,
"queueSizeMax": 200
}
RocketMq核心原理讲解
消息生产者与消费者的运作机制
消息生产者
消息生产者(Producer)是RocketMQ系统中的消息发送方,它负责将消息发送到指定的Topic中。生产者需要先连接到NameServer获取Broker的路由信息,然后通过Broker将消息发送到指定的Topic中。
- 建立连接
DefaultMQProducer producer = new DefaultMQProducer("ProducerGroupName");
producer.setNamesrvAddr("localhost:9876");
producer.start();
- 发送消息
Message msg = new Message(
"TopicTest", // Topic
"TagA", // Tag
("Hello RocketMQ "+i).getBytes(RemotingHelper.DEFAULT_CHARSET));
SendResult sendResult = producer.send(msg);
消息消费者
消息消费者(Consumer)是RocketMQ系统中的消息接收方,它从指定的Topic中消费消息。消费者需要先连接到NameServer获取Broker的路由信息,然后通过Broker从指定的Topic中消费消息。
- 建立连接
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("ConsumerGroupName");
consumer.setNamesrvAddr("localhost:9876");
consumer.subscribe("TopicTest", "*");
consumer.start();
- 消费消息
consumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> {
for (Message msg : msgs) {
System.out.printf("Received message: %s %n", new String(msg.getBody(), RemotingHelper.DEFAULT_CHARSET));
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
});
消息处理的优化建议
消息重试机制
在RocketMQ中,如果消费消息时失败,可以通过设置ConsumeConcurrentlyStatus.RECONSUME_LATER
来实现消息的重试机制,消息会重新放回队列并等待下次消费。
consumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> {
for (MessageExt msg : msgs) {
try {
System.out.printf("Received message: %s %n", new String(msg.getBody(), RemotingHelper.DEFAULT_CHARSET));
// 模拟消息处理失败
if (new String(msg.getBody(), RemotingHelper.DEFAULT_CHARSET).equals("test")) {
return ConsumeConcurrentlyStatus.RECONSUME_LATER;
}
} catch (Exception e) {
e.printStackTrace();
}
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
});
消息过滤
可以通过设置消费者的消息过滤规则来减少不必要的消息消费。
consumer.subscribe("TopicTest", "*");
consumer.setMessageModel(MessageModel.BROADCASTING); // 设置消息模型
consumer.setMessageListener((MessageListenerConcurrently) (msgs, context) -> {
for (MessageExt msg : msgs) {
System.out.printf("Received message: %s %n", new String(msg.getBody(), RemotingHelper.DEFAULT_CHARSET));
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
});
消息消费的幂等性
为了确保消息的唯一性和避免重复消费,RocketMQ提供了消息消费的幂等性处理机制。可以通过设置消息的唯一标识(如消息ID)来确保消息的唯一性。
consumer.setMessageListener((MessageListenerConcurrently) (msgs, context) -> {
for (MessageExt msg : msgs) {
String msgId = msg.getMsgId();
if (msgId != null && !msgId.isEmpty()) {
System.out.printf("Received message: %s %n", new String(msg.getBody(), RemotingHelper.DEFAULT_CHARSET));
}
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
});
RocketMq项目实战一:消息发布与订阅
实现简单的消息发布与订阅功能
消息发布(生产者)
- 生产者配置
DefaultMQProducer producer = new DefaultMQProducer("ProducerGroupName");
producer.setNamesrvAddr("localhost:9876");
producer.start();
- 发送消息
Message msg = new Message(
"TopicTest", // Topic
"TagA", // Tag
("Hello RocketMQ "+i).getBytes(RemotingHelper.DEFAULT_CHARSET));
SendResult sendResult = producer.send(msg);
消息订阅(消费者)
- 消费者配置
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("ConsumerGroupName");
consumer.setNamesrvAddr("localhost:9876");
consumer.subscribe("TopicTest", "*");
consumer.start();
- 消费消息
consumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> {
for (Message msg : msgs) {
System.out.printf("Received message: %s %n", new String(msg.getBody(), RemotingHelper.DEFAULT_CHARSET));
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
});
实战代码示例
生产者代码示例
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.common.RemotingHelper;
public class Producer {
public static void main(String[] args) throws Exception {
DefaultMQProducer producer = new DefaultMQProducer("ProducerGroupName");
producer.setNamesrvAddr("localhost:9876");
producer.start();
for (int i = 0; i < 100; i++) {
Message msg = new Message(
"TopicTest", // Topic
"TagA", // Tag
("Hello RocketMQ "+i).getBytes(RemotingHelper.DEFAULT_CHARSET));
SendResult sendResult = producer.send(msg);
System.out.printf("%s %s%n", sendResult.getSendStatus(), sendResult.getMessageId());
}
producer.shutdown();
}
}
消费者代码示例
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.apache.rocketmq.remoting.common.RemotingHelper;
public class Consumer {
public static void main(String[] args) throws Exception {
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("ConsumerGroupName");
consumer.setNamesrvAddr("localhost:9876");
consumer.subscribe("TopicTest", "*");
consumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> {
for (MessageExt msg : msgs) {
System.out.printf("Received message: %s %n", new String(msg.getBody(), RemotingHelper.DEFAULT_CHARSET));
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
});
consumer.start();
}
}
RocketMq项目实战二:消息消费与处理
详细介绍消息消费的流程
接收消息
消费者从指定的Topic中接收消息的过程需要通过NameServer获取Broker的路由信息,然后由Broker将消息推送给消费者。RocketMQ支持同步和异步两种模式的消息消费。
- 同步消费
consumer.subscribe("TopicTest", "*");
consumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> {
for (MessageExt msg : msgs) {
System.out.printf("Received message: %s %n", new String(msg.getBody(), RemotingHelper.DEFAULT_CHARSET));
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
});
- 异步消费
consumer.subscribe("TopicTest", "*");
consumer.setMessageListener((MessageListenerOrderly) (msgs, context) -> {
for (MessageExt msg : msgs) {
System.out.printf("Received message: %s %n", new String(msg.getBody(), RemotingHelper.DEFAULT_CHARSET));
}
return ConsumeOrderlyStatus.SUCCESS;
});
消息处理的优化建议
消息重试机制
在RocketMQ中,如果消费消息时失败,可以通过设置ConsumeConcurrentlyStatus.RECONSUME_LATER
来实现消息的重试机制,消息会重新放回队列并等待下次消费。
consumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> {
for (MessageExt msg : msgs) {
try {
System.out.printf("Received message: %s %n", new String(msg.getBody(), RemotingHelper.DEFAULT_CHARSET));
// 模拟消息处理失败
if (new String(msg.getBody(), RemotingHelper.DEFAULT_CHARSET).equals("test")) {
return ConsumeConcurrentlyStatus.RECONSUME_LATER;
}
} catch (Exception e) {
e.printStackTrace();
}
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
});
消息过滤
可以通过设置消费者的消息过滤规则来减少不必要的消息消费。
consumer.subscribe("TopicTest", "*");
consumer.setMessageModel(MessageModel.BROADCASTING); // 设置消息模型
consumer.setMessageListener((MessageListenerConcurrently) (msgs, context) -> {
for (MessageExt msg : msgs) {
System.out.printf("Received message: %s %n", new String(msg.getBody(), RemotingHelper.DEFAULT_CHARSET));
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
});
消息消费的幂等性
为了确保消息的唯一性和避免重复消费,RocketMQ提供了消息消费的幂等性处理机制。可以通过设置消息的唯一标识(如消息ID)来确保消息的唯一性。
consumer.setMessageListener((MessageListenerConcurrently) (msgs, context) -> {
for (MessageExt msg : msgs) {
String msgId = msg.getMsgId();
if (msgId != null && !msgId.isEmpty()) {
System.out.printf("Received message: %s %n", new String(msg.getBody(), RemotingHelper.DEFAULT_CHARSET));
}
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
});
RocketMq项目实战三:集群部署与监控
集群部署的基础步骤
部署NameServer
- 启动NameServer
nohup sh bin/mqnamesrv &
部署Broker
- 配置Broker
在conf/broker.properties
文件中进行配置。
brokerClusterName=DefaultCluster
brokerName=broker-0
brokerId=0
deleteWhen=04
fileReservedDays=7
flushDiskType=ASYNC_FLUSH
brokerRole=ASYNC_MASTER
- 启动Broker
nohup sh bin/mqbroker -c conf/broker.properties &
部署多个Broker
- 配置多个Broker
在不同的Broker中分别配置broker.properties
文件,并设置不同的brokerId
。
- 启动Broker
nohup sh bin/mqbroker -c conf/broker-0.properties &
nohup sh bin/mqbroker -c conf/broker-1.properties &
监控工具的使用及详解
监控RocketMq
RocketMQ提供了多种监控工具,包括RocketMQ自带的mqadmin
命令和第三方监控工具如Prometheus等。
- 使用RocketMQ自带的监控工具
sh bin/mqadmin clusterList localhost
-
使用Prometheus监控RocketMq
- 安装Prometheus
下载并安装Prometheus。
wget https://github.com/prometheus/prometheus/releases/download/v2.35.0/prometheus-2.35.0.linux-amd64.tar.gz
tar -xvf prometheus-2.35.0.linux-amd64.tar.gz
cd prometheus-2.35.0.linux-amd64
- 配置RocketMQ与Prometheus集成
在prometheus.yml
文件中添加RocketMQ的监控配置。
scrape_configs:
- job_name: 'rocketmq-broker'
static_configs:
- targets: ['localhost:10911']
- job_name: 'rocketmq-namesrv'
static_configs:
- targets: ['localhost:10912']
- 启动Prometheus
./prometheus --config.file=prometheus.yml &
- 访问Prometheus
打开浏览器,访问http://localhost:9090
,可以查看RocketMQ的相关监控指标。
监控指标详解
RocketMQ提供的监控指标包括但不限于以下内容:
- Broker状态
{
"brokerAddr": "127.0.0.1:10911",
"brokerName": "broker-0",
"brokerVersion": "4.9.1",
"consumerNums": 1,
"producerNums": 1,
"diskUsedSize": 100,
"queueNums": 10,
"registerTopicNums": 5
}
- Topic状态
{
"topic": "TopicTest",
"queueNums": 10,
"queueSize": 50,
"consumerNums": 1,
"produceNums": 1,
"queueSizeMax": 200
}
通过监控这些指标,可以及时发现RocketMQ集群中的问题,提高系统的可靠性和稳定性。
解决常见问题与技巧分享遇到的问题及解决方法
问题1:消费者消费不到消息
- 原因:消费者与生产者之间的路由信息不一致,或者Broker未正确启动。
- 解决方法:确保NameServer和Broker已经正确启动,并且消费者能够正确获取到Broker的路由信息。
问题2:消息重复消费
- 原因:消息的消费机制未设置幂等性。
- 解决方法:在消息消费的处理逻辑中设置消息的幂等性处理机制,确保消息的唯一性。
问题3:消息发送失败
- 原因:生产者与Broker之间的网络连接异常,或者生产者配置不当。
- 解决方法:检查生产者与Broker之间的网络连接是否正常,并确保生产者配置正确。
项目实战中的技巧与注意事项
技巧1:持久化消息
- 说明:RocketMQ支持消息的持久化存储,可以确保消息不丢失。
- 实现:设置
flushDiskType
为ASYNC_FLUSH
或SYNC_FLUSH
,确保消息的持久化存储。
技巧2:消息过滤
- 说明:通过设置消息的过滤规则,可以减少不必要的消息消费。
- 实现:在消费者中设置消息的过滤规则,只消费符合规则的消息。
技巧3:消息重试机制
- 说明:通过设置消息的重试机制,可以确保消息的可靠性。
- 实现:在消息消费失败时,设置
ConsumeConcurrentlyStatus.RECONSUME_LATER
,实现消息的重试机制。
注意事项
- 性能优化:合理设置Broker的数量和配置,确保RocketMQ集群的性能。
- 监控与报警:通过RocketMQ的监控工具,及时发现并解决集群中的异常问题。
- 高可用性:合理设置NameServer和Broker的集群配置,确保RocketMQ集群的高可用性。
通过以上技巧和注意事项,可以更好地利用RocketMQ进行消息的发布与订阅,保证消息的可靠性和系统的稳定性。
共同学习,写下你的评论
评论加载中...
作者其他优质文章