-
什么是消息轨迹
-
消息轨迹配置
-
消息轨迹的实现原理
-
消息轨迹Topic支持方式
-
用户自定义的TraceTopic实践
1. 什么是消息轨迹
RocketMQ的消息轨迹是一种用于追踪消息生产、存储、消费全链路状态的功能。它记录了消息从生产者发送到 Broker,再到消费者消费的完整生命周期信息,帮助开发者在分布式系统中快速定位消息问题(如消息丢失、重复消费、延迟等),并监控消息流转状态。
消息轨迹数据关键属性
Producer端 | Consumer端 | Broker端 |
---|---|---|
生产实例信息 | 消费实例信息 | 消息的Topic |
发送消息时间 | 投递时间,投递轮次 | 消息存储位置 |
消息是否发送成功 | 消息是否消费成功 | 消息的Key值 |
发送耗时 | 消费耗时 | 消息的Tag值 |
消息轨迹的核心作用
-
问题排查:快速定位消息是否成功发送、存储、消费,以及失败原因。
-
链路追踪:查看消息在生产者、Broker、消费者之间的流转路径和时间。
-
状态监控:统计消息的发送/消费延迟、成功率等关键指标。
-
数据审计:记录消息的完整生命周期,满足合规性要求。
2. 消息轨迹配置
如果RocketMQ 开启消息轨迹,增加这个配置:
traceTopicEnable=true
给大家贴出Broker端开启消息轨迹特性的properties配置文件内容(来源官网):
brokerClusterName=DefaultCluster
brokerName=broker-a
brokerId=0
deleteWhen=04
fileReservedTime=48
brokerRole=ASYNC_MASTER
flushDiskType=ASYNC_FLUSH
storePathRootDir=/data/rocketmq/rootdir-a-m
storePathCommitLog=/data/rocketmq/commitlog-a-m
autoCreateSubscriptionGroup=true
## if msg tracing is open,the flag will be true
traceTopicEnable=true
listenPort=10911
brokerIP1=XX.XX.XX.XX1
namesrvAddr=XX.XX.XX.XX:9876
RocketMQ的消息轨迹功能支持普通模式和物理IO隔离模式。
普通模式
-
消息轨迹数据与普通业务消息共享Broker节点,集群中的每个Broker节点均可存储消息轨迹数据。
-
部署简单,无需额外配置。可能存在IO竞争问题,可能影响高吞吐量场景的性能。
-
在Broker的配置文件中开启消息轨迹功能(traceTopicEnable=true),即可。
物理IO隔离模式
-
消息轨迹数据与业务消息的存储完全隔离,需指定专用Broker节点单独存储轨迹数据。
-
避免IO资源竞争,提升整体吞吐量和稳定性,适合消息轨迹数据量大或对性能要求高的场景
-
RocketMQ集群中至少有两个Broker节点,其中一个Broker节点定义为存储消息轨迹数据的服务端
3. 消息轨迹的实现原理
RocketMQ 的消息轨迹功能通过以下方式实现:
-
内置轨迹Topic:RocketMQ 会创建一个内部 Topic(默认名为 RMQ_SYS_TRACE_TOPIC),专门用于存储消息轨迹数据。
-
钩子机制:生产者和消费者在发送/消费消息时,通过 Hook(钩子)拦截消息事件,生成轨迹数据并发送到轨迹 Topic。
-
轨迹存储与查询:轨迹数据由 Broker 存储,用户可以通过 RocketMQ 控制台或 API 查询消息的完整轨迹。
流程简要总结就是:
-
生产者:业务消息发送 → 钩子记录轨迹 → 内存队列缓冲 → 异步上报轨迹。
-
消费者:消息消费 → 钩子记录轨迹 → 内存队列缓冲 → 异步上报轨迹。
-
最终轨迹数据统一存储到 RMQ_SYS_TRACE_TOPIC,通过控制台查询。
4. 消息轨迹Topic支持方式
有些伙伴可能有疑问,上图中,Broker 的 RMQ_SYS_TRACE_TOPIC是什么呀?其实,RocketMQ的消息轨迹特性支持两种存储轨迹数据的方式:
-
默认内置轨迹 Topic
-
自定义轨迹 Topic
4.1 默认内置轨迹 Topic
-
Topic的名称为
RMQ_SYS_TRACE_TOPIC
,它是RocketMQ 自动创建,无需用户手动配置。 -
默认开启,只要生产者或消费者启用了消息轨迹(setEnableMsgTrace(true)),轨迹数据会自动发送到此 Topic。
-
Broker 自动管理该 Topic 的队列和存储。
-
适用快速验证、测试环境或无需自定义轨迹管理的场景。
4.2 自定义轨迹 Topic
-
用户可指定一个自定义的Topic名称(如
MyApp_TraceTopic
),用于存储轨迹数据。 -
适用对轨迹数据有特殊存储或安全要求(如独立集群、分片策略)。
5. 用户自定义的TraceTopic代码实践
5.1 发送消息时开启消息轨迹
生产者代码示例(自定义轨迹Topic)
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.common.RemotingHelper;
public class CustomTraceProducer {
public static void main(String[] args) throws Exception {
// 1. 创建生产者实例,并开启消息轨迹,指定自定义轨迹Topic
// 参数说明:生产者组名, enableMsgTrace=true, 自定义轨迹Topic名称
DefaultMQProducer producer = new DefaultMQProducer("OrderProducerGroup", true, "MyApp_TraceTopic");
// 2. 设置NameServer地址(根据实际环境修改)
producer.setNamesrvAddr("localhost:9876");
producer.start();
try {
// 3. 构建订单消息(模拟业务场景)
Message msg = new Message(
"OrderTopic", // 业务Topic
"PayOrder", // Tag(用于消息过滤)
"Order_202307280001", // 业务唯一Key(Message Key)
"订单支付成功".getBytes(RemotingHelper.DEFAULT_CHARSET) // 消息体
);
// 4. 发送消息
SendResult sendResult = producer.send(msg);
System.out.println("消息发送结果: " + sendResult);
} finally {
// 5. 关闭生产者
producer.shutdown();
}
}
}
5.2 消费者代码示例(自定义轨迹Topic)
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
public class CustomTraceConsumer {
public static void main(String[] args) throws Exception {
// 1. 创建消费者实例,并开启消息轨迹,指定自定义轨迹Topic
// 参数说明:消费者组名, enableMsgTrace=true, 自定义轨迹Topic名称
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("OrderConsumerGroup", true, "MyApp_TraceTopic");
// 2. 设置NameServer地址(根据实际环境修改)
consumer.setNamesrvAddr("localhost:9876");
// 3. 订阅业务Topic(只消费PayOrder标签的消息)
consumer.subscribe("OrderTopic", "PayOrder");
// 4. 设置从队列头部开始消费(首次启动时)
consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
// 5. 注册消息监听器(处理业务逻辑)
consumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> {
System.out.println("收到订单消息: " + new String(msgs.get(0).getBody()));
// 模拟消费成功(若失败返回RECONSUME_LATER)
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
});
consumer.start();
System.out.println("消费者已启动,等待订单消息...");
}
}
5.3 轨迹数据验证
- 确保自定义轨迹Topic存在:
- 若 Broker 未开启自动创建 Topic(autoCreateTopicEnable=false),需手动创建:
sh mqadmin updateTopic -n localhost:9876 -t MyApp_TraceTopic -c DefaultCluster
- 发送测试消息:
运行生产者代码,发送一条订单消息到 OrderTopic,轨迹数据将写入 MyApp_TraceTopic。
- 查询消息轨迹:
使用 RocketMQ 控制台或命令行工具,输入消息的 MsgID 或 Message Key 查询轨迹:
sh mqadmin QueryMsgTraceById -n localhost:9876 -i "0A1234567890ABCDEF" # 替换为实际MsgID