在分布式系统中,消息队列是实现异步通信、解耦服务、削峰填谷的关键组件。RocketMQ 作为阿里巴巴开源的分布式消息中间件,凭借卓越的性能、高可靠性和丰富功能,在电商、金融、社交等众多领域广泛应用。它能够支撑海量消息的高并发处理,确保消息不丢失、不重复,为分布式系统的稳定运行提供坚实保障。
组件交互 | 交互流程 | 应用场景 |
---|---|---|
Producer 与 NameServer | Producer 启动时向所有 NameServer 注册自身信息,并定时拉取最新 Broker 路由数据 | 电商下单场景中,订单服务(Producer)需实时知晓消息存储位置,确保订单消息准确发送 |
Producer 与 Broker | Producer 根据路由信息,选择 Broker 发送消息。发送成功后,Broker 返回确认响应 | 在物流通知场景中,订单系统(Producer)向物流消息队列(Broker)发送发货消息,需确认消息已成功存储 |
Consumer 与 NameServer | Consumer 启动时从 NameServer 获取订阅 Topic 的 Broker 地址列表,并定期更新 | 用户评论系统(Consumer)需持续获取评论消息队列(Broker)地址,保证及时消费新评论消息 |
Consumer 与 Broker | Consumer 按一定策略从 Broker 拉取消息,处理成功后向 Broker 发送确认 | 在积分系统中,消费订单支付成功消息(从 Broker 拉取),处理后确认消息已消费,防止重复处理 |
RocketMQ 提供三种消息发送模式,满足不同业务对可靠性和性能的需求。以下是各模式的详细解析:
描述:发送消息后同步等待 Broker 确认响应,确保消息发送成功,适用于对可靠性要求极高的场景。
适用场景:金融交易、订单创建等不能容忍消息丢失的核心业务。
代码示例:
DefaultMQProducer producer = new DefaultMQProducer("producerGroup");
producer.setNamesrvAddr("nameserver1:9876;nameserver2:9876");
producer.start();
Message message = new Message(
"OrderTopic", // Topic名称
"CREATE", // Tag(用于消息过滤)
"ORDER_1001", // 消息键(唯一标识)
"订单创建成功,商品ID=1001".getBytes() // 消息体
);
// 同步发送,获取发送结果
SendResult sendResult = producer.send(message);
System.out.println("发送状态:" + sendResult.getSendStatus());
System.out.println("消息队列:" + sendResult.getMessageQueue());
producer.shutdown();
描述:发送消息后不阻塞等待响应,通过回调函数处理结果,提升发送性能,适用于高并发非核心业务。
适用场景:日志采集、监控指标上报、通知类消息。
代码示例:
DefaultMQProducer producer = new DefaultMQProducer("producerGroup");
producer.setNamesrvAddr("nameserver1:9876;nameserver2:9876");
producer.start();
Message message = new Message("LogTopic", "INFO", "LOG_001", "系统启动日志".getBytes());
// 异步发送,设置回调函数
producer.send(message, new SendCallback() {
@Override
public void onSuccess(SendResult sendResult) {
System.out.println("异步发送成功:" + sendResult.getSendStatus());
}
@Override
public void onException(Throwable e) {
System.err.println("异步发送失败:" + e.getMessage());
}
});
// 保持Producer运行,确保回调执行
Thread.sleep(1000);
producer.shutdown();
描述:发送消息后忽略响应,追求极致性能,不保证消息一定到达 Broker。
适用场景:对可靠性要求极低的场景(如非核心指标上报)。
代码示例:
DefaultMQProducer producer = new DefaultMQProducer("producerGroup");
producer.setNamesrvAddr("nameserver1:9876;nameserver2:9876");
producer.start();
Message message = new Message("MetricTopic", "TPS", "METRIC_001", "当前TPS=1000".getBytes());
// 单向发送(无响应)
producer.sendOneway(message);
producer.shutdown();
当发送失败(如网络波动)时,RocketMQ 自动重试发送,可通过参数调整重试策略:
DefaultMQProducer producer = new DefaultMQProducer("producerGroup");
producer.setNamesrvAddr("nameserver1:9876;nameserver2:9876");
producer.setRetryTimesWhenSendFailed(3); // 失败后重试3次
producer.setSendMsgTimeout(5000); // 单次发送超时5秒
producer.start();
// 发送消息代码...
RocketMQ 支持两种核心消费模式,配合消息过滤机制,满足多样化的消费需求。
描述:同一消费组内的消费者平均分摊消息,适用于负载均衡场景,是最常用的消费模式。
核心特性:
代码示例:
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("consumerGroup");
consumer.setNamesrvAddr("nameserver1:9876;nameserver2:9876");
consumer.setMessageModel(MessageModel.CLUSTERING); // 集群消费模式
consumer.subscribe("OrderTopic", "CREATE"); // 订阅Topic及Tag
consumer.registerMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(
List<MessageExt> msgs, ConsumeConcurrentlyContext context
) {
for (MessageExt msg : msgs) {
String messageBody = new String(msg.getBody());
System.out.println("消费消息:" + messageBody);
// 业务处理逻辑
processOrder(msg);
}
// 批量确认消费成功
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
consumer.start();
描述:每个消费者实例都会收到全量消息,适用于需要所有消费者处理相同消息的场景。
核心特性:
代码示例:
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("consumerGroup");
consumer.setNamesrvAddr("nameserver1:9876;nameserver2:9876");
consumer.setMessageModel(MessageModel.BROADCASTING); // 广播消费模式
consumer.subscribe("NoticeTopic", "*"); // 订阅所有Tag
consumer.registerMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(
List<MessageExt> msgs, ConsumeConcurrentlyContext context
) {
for (MessageExt msg : msgs) {
String notice = new String(msg.getBody());
sendNotification(notice); // 发送短信、邮件等通知
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
consumer.start();
RocketMQ 支持两种过滤方式,精准筛选目标消息:
原理:发送消息时设置 Tag,消费时通过 subscribe(topic, tag)
过滤。
示例:
// 发送时设置Tag
Message message = new Message("OrderTopic", "PAY", "ORDER_1002", "支付成功".getBytes());
producer.send(message);
// 消费时过滤Tag为PAY的消息
consumer.subscribe("OrderTopic", "PAY");
原理:基于消息属性(User Property)进行 SQL92 表达式过滤(需在 Broker 配置 enablePropertyFilter=true
)。
示例:
// 发送时添加属性
message.putUserProperty("orderAmount", "200");
message.putUserProperty("region", "SH");
// 消费时过滤金额>100且地区为上海的消息
consumer.subscribe("OrderTopic", "orderAmount > 100 AND region = 'SH'");
维度 | 同步发送 | 异步发送 | 单向发送 | 集群消费 | 广播消费 |
---|---|---|---|---|---|
可靠性 | 高 | 中 | 低 | 负载均衡 | 全量消费 |
吞吐量 | 中 | 高 | 最高 | 高并发处理 | 广播通知 |
适用场景 | 核心交易 | 日志采集 | 指标上报 | 订单处理 | 系统通知 |
代码复杂度 | 简单 | 中等(回调) | 简单 | 中等(幂等性) | 简单 |
通过合理选择发送与消费模式,结合消息过滤机制,可在不同业务场景中发挥 RocketMQ 的最佳性能与可靠性。
TransactionMQProducer producer = new TransactionMQProducer("producerGroup");
producer.setNamesrvAddr("nameserver1:9876;nameserver2:9876");
TransactionListener transactionListener = new TransactionListener() {
@Override
public LocalTransactionState executeLocalTransaction(Message msg, Object arg) {
// 执行本地事务,如扣减库存
try {
// 本地业务逻辑
return LocalTransactionState.COMMIT_MESSAGE;
} catch (Exception e) {
return LocalTransactionState.ROLLBACK_MESSAGE;
}
}
@Override
public LocalTransactionState checkLocalTransaction(MessageExt msg) {
// 事务状态查询逻辑
return LocalTransactionState.COMMIT_MESSAGE;
}
};
producer.setTransactionListener(transactionListener);
producer.start();
Message message = new Message("TopicTest", "TagA", "Hello, RocketMQ!".getBytes());
TransactionSendResult sendResult = producer.sendMessageInTransaction(message, null);
producer.shutdown();
// 生产者发送顺序消息
DefaultMQProducer producer = new DefaultMQProducer("producerGroup");
producer.setNamesrvAddr("nameserver1:9876;nameserver2:9876");
producer.start();
Message message = new Message("TopicTest", "TagA", "Hello, RocketMQ!".getBytes());
SendResult sendResult = producer.send(message, new MessageQueueSelector() {
@Override
public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
// 根据业务逻辑选择Queue,如根据订单ID取模
Long orderId = (Long) arg;
long index = orderId % mqs.size();
return mqs.get((int) index);
}
}, orderId);
producer.shutdown();
// 消费者接收顺序消息
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("consumerGroup");
consumer.setNamesrvAddr("nameserver1:9876;nameserver2:9876");
consumer.subscribe("TopicTest", "TagA");
consumer.registerMessageListener(new MessageListenerOrderly() {
@Override
public ConsumeOrderlyStatus consumeMessage(List<MessageExt> msgs, ConsumeOrderlyContext context) {
for (MessageExt msg : msgs) {
System.out.println(new String(msg.getBody()));
}
return ConsumeOrderlyStatus.SUCCESS;
}
});
consumer.start();
pom.xml
中添加以下依赖:<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-stream-rocketmqartifactId>
dependency>
application.yml
中配置 RocketMQ 生产者相关参数,如 NameServer 地址、生产者组等:spring:
cloud:
stream:
rocketmq:
binder:
namesrv-addr: nameserver1:9876;nameserver2:9876
bindings:
orderOutput:
destination: orderTopic
group: orderProducerGroup
RocketMQTemplate
发送消息。例如,发送订单消息:import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
@Service
public class OrderProducer {
@Autowired
private RocketMQTemplate rocketMQTemplate;
public void sendOrder(Order order) {
rocketMQTemplate.send("orderOutput", MessageBuilder.withPayload(order).build());
}
}
application.yml
中配置消费者相关参数,如订阅的 Topic、消费组等:spring:
cloud:
stream:
rocketmq:
binder:
namesrv-addr: nameserver1:9876;nameserver2:9876
bindings:
orderInput:
destination: orderTopic
group: orderConsumerGroup
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.stereotype.Service;
@Service
public class OrderConsumer {
@StreamListener("orderInput")
public void handleOrder(Order order) {
// 处理订单逻辑,如更新订单状态、扣减库存等
}
}
在 Spring Cloud 中实现事务消息,需结合RocketMQTransactionManager
和自定义事务监听器,确保本地事务与消息发送的一致性。
import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.apache.rocketmq.spring.transaction.RocketMQTransactionListenerAdapter;
import org.apache.rocketmq.spring.transaction.TransactionSendResult;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
@Configuration
public class RocketMQConfig {
@Bean
public PlatformTransactionManager transactionManager() {
return new RocketMQTransactionManager(rocketMQTemplate());
}
@Bean
public RocketMQTemplate rocketMQTemplate(DefaultMQProducer producer) {
RocketMQTemplate template = new RocketMQTemplate();
template.setProducer(producer);
return template;
}
// 自定义事务监听器
@Component
@RocketMQTransactionListener(txProducerGroup = "order-producer-group")
public class OrderTransactionListener extends RocketMQTransactionListenerAdapter {
@Override
public LocalTransactionState executeLocalTransaction(Message message, Object arg) {
Order order = (Order) message.getPayload();
try {
// 执行本地事务(如创建订单、扣减库存)
orderService.createOrder(order);
inventoryService.deductStock(order.getProductId(), order.getQuantity());
return LocalTransactionState.COMMIT_MESSAGE;
} catch (Exception e) {
// 本地事务失败,回滚消息
return LocalTransactionState.ROLLBACK_MESSAGE;
}
}
@Override
public LocalTransactionState checkLocalTransaction(Message message) {
Order order = (Order) message.getPayload();
// 查询本地事务状态(如订单是否创建成功)
boolean orderExists = orderService.checkOrderExists(order.getId());
return orderExists ? LocalTransactionState.COMMIT_MESSAGE : LocalTransactionState.UNKNOWN;
}
}
}
@Service
public class OrderProducer {
@Autowired
private RocketMQTemplate rocketMQTemplate;
public void sendOrderWithTransaction(Order order) {
// 发送事务消息(半事务消息)
TransactionSendResult result = rocketMQTemplate.sendMessageInTransaction(
"orderOutput",
MessageBuilder.withPayload(order).build(),
order // 传递给事务监听器的参数(如订单对象)
);
// 处理发送结果
if (result.getLocalTransactionState() == LocalTransactionState.COMMIT_MESSAGE) {
log.info("事务消息提交成功");
}
}
}
在 Spring Cloud 中发送顺序消息,需通过RocketMQTemplate
的sendOrderly
方法指定队列选择策略,消费者使用MessageListenerOrderly
确保顺序消费。
@Service
public class OrderProducer {
@Autowired
private RocketMQTemplate rocketMQTemplate;
public void sendOrderInOrder(Order order) {
// 按订单ID选择队列(同一订单ID发送到同一队列)
rocketMQTemplate.sendOrderly(
"orderTopic",
MessageBuilder.withPayload(order).build(),
(mqs, msg, arg) -> {
Long orderId = (Long) arg;
int index = (int) (orderId % mqs.size());
return mqs.get(index); // 选择固定队列
},
order.getId() // 作为队列选择的参数
);
}
}
@Service
public class OrderConsumer {
@StreamListener("orderInput")
public void handleOrderInOrder(List<MessageExt> msgs, ConsumeOrderlyContext context) {
for (MessageExt msg : msgs) {
Order order = JSON.parseObject(msg.getBody(), Order.class);
// 按顺序处理订单(如订单创建→支付→发货)
processOrder(order);
// 手动确认消费(顺序消息需确保处理成功后再提交)
context.setStatus(ConsumeOrderlyStatus.SUCCESS);
}
}
private void processOrder(Order order) {
// 业务处理逻辑(需保证幂等性,避免重复处理)
if (!orderRepository.existsById(order.getId())) {
orderRepository.save(order);
}
}
}
事务消息注意点
transactionTimeout
(默认 60 秒),避免长时间占用事务资源checkLocalTransaction
方法返回UNKNOWN
的情况,需增加人工补偿接口顺序消息优化
maxReconsumeTimes
配置重试次数),需确保重试期间 Queue 被独占生产环境配置
spring:
cloud:
stream:
rocketmq:
binder:
namesrv-addr: nacos-nameserver:9876 # 集群地址
producer:
group: order-producer-group
send-message-timeout: 3000 # 发送超时3秒
retry-times-when-send-failed: 3 # 失败重试3次
consumer:
group: order-consumer-group
consume-thread-min: 16 # 最小消费线程数
consume-thread-max: 32 # 最大消费线程数
brokerRole=ASYNC_MASTER
(异步复制)或SYNC_MASTER
(同步复制)指标名称 | 监控目的 | 采集方式 | 阈值建议 |
---|---|---|---|
rocketmq_producer_send_success |
生产者发送成功率 | RocketMQ 内置 Metrics | ≥99.9% |
rocketmq_consumer_lag |
消费者消息堆积量(队列最小偏移量) | Broker 暴露的 HTTP 接口 | <1000 条(根据业务吞吐量调整) |
commitlog_disk_used_ratio |
磁盘使用率 | 操作系统监控 | <80% |
consumer_thread_pool_queue_size |
消费线程池等待任务数 | 消费者 JVM 监控 | <100 |
RocketMQ Console:可视化管理平台,支持 Topic/Queue 状态查看、消息轨迹追踪
mqadmin 命令:
# 查看消费者状态
sh mqadmin consumerStatus -g consumerGroup -n namesrvAddr
# 查看消息堆积量
sh mqadmin clusterList -n namesrvAddr
分布式链路追踪:结合 SkyWalking 或 Jaeger,通过消息 ID 关联生产者和消费者链路
RocketMQ 通过 “高性能存储 + 灵活消息模式 + 强一致性保障”,成为分布式系统异步通信的首选方案。在 Spring Cloud 生态中,其与 Nacos、Seata 等组件的深度整合,进一步提升了微服务架构的可靠性和可扩展性。
场景 | RocketMQ 特性匹配 | 典型案例 |
---|---|---|
异步解耦 | 高吞吐量、多语言支持 | 电商订单 - 库存异步同步 |
最终一致事务 | 事务消息 + 重试机制 | 金融转账异步对账 |
顺序处理 | 局部顺序消息 + 队列分区 | 物流状态机顺序更新 |
流量削峰 | 海量消息堆积能力 | 秒杀活动流量缓冲 |
通过本文的实战解析,开发者可在 Spring Cloud 项目中快速落地 RocketMQ 的高级特性,构建可靠的消息驱动微服务。