一、RocketMQ 客户端基本流程
RocketMQ 客户端分为生产者(Producer) 和消费者(Consumer) ,核心流程围绕 "消息生产 - 发送 - 存储 - 消费 - 确认" 展开,依赖 NameServer 进行服务发现,Broker 进行消息存储和转发。
1、生产者(Producer)核心流程
- 初始化与启动 :
- 创建
DefaultMQProducer实例,指定生产者组(Producer Group)(同类生产者的逻辑分组,用于事务消息回溯、负载均衡优化)。 - 配置 NameServer 地址(通过
setNamesrvAddr("启动服务的地址")),生产者通过 NameServer 获取 Broker 的路由信息(Topic 对应的队列分布、Broker 状态)。 - 调用
start()方法启动生产者,底层完成 Netty 客户端初始化、与 NameServer 建立连接、拉取并缓存路由信息(后续会定时更新路由)。
- 创建
- 消息构建与发送 :
- 构建
Message对象,指定Topic(消息主题,消息分类标识)、Tag(消息子分类,用于消息过滤)、Key(消息唯一标识,用于查询追踪)和消息体(二进制字节数组)。 - 调用发送方法(同步
send()、异步sendAsync()、单向sendOneway()),生产者根据路由信息,通过负载均衡策略(默认轮询,支持一致性哈希等)选择对应的 Broker 和消息队列(Message Queue)。 - 底层通过 Netty 将消息发送到 Broker,消息经过 Broker 的校验、存储后,返回发送结果(成功 / 失败、消息偏移量等)。
- 构建
- 关闭资源 :使用完成后调用
shutdown(),关闭 Netty 连接、释放缓存资源,避免内存泄漏。
2、费者(Consumer)核心流程
RocketMQ 消费者分为两种模式:推模式(PushConsumer,默认) 和拉模式(PullConsumer),核心流程如下:
- 初始化与启动 :
- 创建
DefaultMQPushConsumer(推模式)或DefaultMQPullConsumer(拉模式)实例,指定消费者组(Consumer Group)(同类消费者的逻辑分组,用于负载均衡、消息重试机制)。 - 配置 NameServer 地址、订阅的 Topic(可指定 Tag,如
TopicTest:TagA||TagB)。 - 推模式需注册消息监听处理器(
MessageListenerConcurrently并发消费 /MessageListenerOrderly顺序消费),拉模式需手动实现拉取逻辑。 - 调用
start()方法启动消费者,底层完成与 NameServer 建立连接、拉取路由信息、与 Broker 建立长连接、向 Broker 注册消费者组信息。
- 创建
- 消息获取与消费 :
- 推模式:Broker 主动将消息推送给消费者(底层仍是消费者定时拉取,封装为 "推" 的体验),消息到达后触发监听处理器的
consumeMessage()方法执行消费业务逻辑。 - 拉模式:消费者主动调用
pull()方法,指定队列和偏移量(Offset)拉取消息,手动处理消费和偏移量提交。
- 推模式:Broker 主动将消息推送给消费者(底层仍是消费者定时拉取,封装为 "推" 的体验),消息到达后触发监听处理器的
- 关闭资源 :调用
shutdown()关闭连接、释放资源,停止消息拉取 / 消费。
3、依赖关系
- 生产者 / 消费者不直接与 Broker 耦合,通过 NameServer 获取动态路由,实现 Broker 的水平扩展。
- 每个 Topic 对应多个 Message Queue(队列),队列是 RocketMQ 负载均衡和顺序消息的核心载体。
二、消息确认机制(ACK)
RocketMQ 的消息确认机制用于保证消息消费的可靠性,避免消息丢失或重复消费,核心分为「Broker 对生产者的 ACK」和「消费者对 Broker 的 ACK」,其中消费者 ACK 是核心重点。
1、生产者发送的 ACK(Broker 回执)
- 同步发送:Broker 接收消息并完成持久化(写入 CommitLog)后,立即返回
SendResult(包含发送状态SEND_OK、消息 ID、队列偏移量等),生产者收到 ACK 后才认为发送成功。 - 异步发送:生产者发送消息后无需阻塞等待,Broker 处理完成后通过回调函数返回 ACK 结果。
- 单向发送:生产者只发送消息,不接收任何 ACK 回执,适用于对可靠性要求较低的场景(如日志采集)。
2、消费者消费的 ACK(核心)
RocketMQ 消费者的 ACK 机制分并发消费 和顺序消费两种场景,默认采用「自动 ACK」,也支持手动 ACK,核心是通过「偏移量(Offset)」标记消费进度。
(1) 偏移量(Offset)
- 每个 Message Queue 都有独立的 Offset,分为「存储偏移量」(Broker 中消息的物理偏移量,标记消息存储位置)和「消费偏移量」(标记消费者已消费到该队列的哪个位置)。
- 消费者的消费进度由 Consumer Group 维护,Broker 会定期持久化 Consumer Group 的消费 Offset(默认存储在 Broker 的
consumer_offset主题中)。
(2) 并发消费场景(默认)
- 自动 ACK:消费者成功执行
consumeMessage()方法(业务逻辑无异常)后,框架自动向 Broker 提交 Offset,Broker 更新该 Consumer Group 对应队列的消费进度。若消费过程中抛出异常,框架不会提交 ACK,该消息会被重新投递(进入重试队列),默认重试 16 次后进入死信队列(DLQ)。 - 手动 ACK:通过设置
consumer.setAutoCommit(false)关闭自动提交,消费成功后手动调用MessageListenerConcurrently的返回结果ConsumeConcurrentlyStatus.CONSUME_SUCCESS提交 ACK;消费失败返回RECONSUME_LATER,触发消息重试。
(3) 顺序消费场景
- 顺序消费的 ACK 更严格,采用「阻塞式提交」:消费者消费完一条消息并返回
ConsumeOrderlyStatus.SUCCESS后,才会提交该消息的 Offset,然后继续消费下一条消息。 - 若消费失败返回
SUSPEND_CURRENT_QUEUE_AWAITING,该队列会被暂停消费(默认暂停 5 秒),避免后续消息阻塞,同时该消息会被重试,保证消息的有序性不被破坏。
(4) 关键特性
- RocketMQ 的 ACK 机制是「至少一次(At Least Once)」语义:消息不会丢失,但可能因网络抖动、消费异常导致重复消费,需要业务层实现幂等性(如基于消息 Key 去重)。
- 不支持「恰好一次(Exactly Once)」语义,需结合业务层或分布式事务实现。
三、广播消息
1、定义
广播消息(Broadcast)是指:同一条消息会被同一个 Consumer Group 中的所有消费者实例都消费一次,而非默认的集群消费(Clustering)中消息只会被 Consumer Group 中的一个实例消费。
2、与集群消费的核心区别
| 特性 | 集群消费(默认) | 广播消息 |
|---|---|---|
| 消费目标 | 消息被 Consumer Group 中一个实例消费 | 消息被 Consumer Group 中所有实例消费 |
| 消费进度维护 | 由 Broker 统一维护消费 Offset | 每个消费者实例独立维护自己的 Offset |
| 重试机制 | 支持,未消费成功的消息重试投递 | 不支持重试,消费失败则消息丢失 |
| 适用场景 | 大部分业务场景(如订单通知) | 配置推送、全局通知、广播日志等 |
3、实现方式
只需在消费者初始化时,将消费模式设置为广播模式即可:
java
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("CONSUMER_GROUP_BROADCAST");
// 设置为广播模式(默认是集群模式:MessageModel.CLUSTERING)
consumer.setMessageModel(MessageModel.BROADCASTING);
4、注意事项
- 广播模式下,Broker 不维护消费 Offset,每个消费者重启后会从队列的起始位置或最新位置开始消费(取决于配置),可能重复消费历史消息。
- 不支持消息重试、死信队列,消费失败需业务层自行处理容错。
- 广播模式下,顺序消费不生效,消息会被并发推送给所有消费者实例。
四、顺序消息机制
RocketMQ 的顺序消息是指:保证消息按照发送的顺序被消费,分为「全局顺序消息」和「分区顺序消息」,核心依赖「Message Queue 的有序性」和「消费者的顺序消费逻辑」。
1、两种顺序消息类型
(1) 全局顺序消息
- 定义:整个 Topic 下的所有消息都按照发送顺序消费,无任何乱序。
- 实现条件:Topic 只能创建1 个 Message Queue ,且 Consumer Group 只能有1 个消费者实例(避免负载均衡分发消息)。
- 局限性:性能极低,无法水平扩展,仅适用于消息量极小、对全局有序要求极高的场景(如全局序列号生成)。
(2) 分区顺序消息(主流)
- 定义:将消息按照某个关键字(如订单 ID)进行分组,同一个分组的消息发送到同一个 Message Queue,而同一个 Message Queue 的消息是有序的,从而保证「分组内有序」(局部有序)。
- 实现核心:
- 生产者发送消息时,通过
MessageQueueSelector自定义队列选择策略,将相同关键字的消息路由到同一个队列(如根据订单 ID 哈希取模)。 - 消费者使用
MessageListenerOrderly(顺序消息监听器),保证对同一个队列的消息采用「单线程消费」,避免并发消费导致乱序。
- 生产者发送消息时,通过
- 优势:支持水平扩展(增加 Message Queue 数量),性能优于全局顺序消息,满足大部分业务场景(如订单创建→支付→发货→完成的流程有序)。
2、实现流程(分区顺序消息)
(1) 生产者端:指定队列选择策略
java
// 生产者发送消息时,指定订单ID作为分区关键字,相同订单ID的消息进入同一个队列
SendResult sendResult = producer.send(message, new MessageQueueSelector() {
@Override
public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
// arg 传入的是订单ID
Long orderId = (Long) arg;
// 哈希取模,保证相同订单ID路由到同一个队列
long index = orderId % mqs.size();
return mqs.get((int) index);
}
}, orderId); // 传入分区关键字(订单ID)
(2) 消费者端:使用顺序消息监听器
java
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("CONSUMER_GROUP_ORDER");
// 注册顺序消息监听器(MessageListenerOrderly)
consumer.registerMessageListener(new MessageListenerOrderly() {
@Override
public ConsumeOrderlyStatus consumeMessage(List<MessageExt> msgs, ConsumeOrderlyContext context) {
// 单线程消费同一个队列的消息,保证顺序
MessageExt msg = msgs.get(0);
try {
// 执行业务消费逻辑(如订单流程处理)
System.out.println("消费顺序消息:" + new String(msg.getBody(), StandardCharsets.UTF_8));
// 消费成功,提交ACK,继续消费下一条
return ConsumeOrderlyStatus.SUCCESS;
} catch (Exception e) {
// 消费失败,暂停当前队列消费,后续重试
return ConsumeOrderlyStatus.SUSPEND_CURRENT_QUEUE_AWAITING;
}
}
});
3、注意事项
- 顺序消息依赖 Broker 的消息存储有序性(CommitLog 按写入顺序存储)和队列的有序分发,若 Broker 宕机切换主从,需保证主从数据同步有序(同步复制)。
- 顺序消费时,消费者对同一个队列采用单线程处理,若某个消息消费耗时过长,会阻塞该队列后续消息的消费,需优化业务逻辑性能。
- 顺序消息的重试机制与并发消费不同,失败后会暂停队列而非立即重试,避免乱序,重试次数可配置。
五、延迟消息
1、定义
延迟消息(Delayed Message)是指:生产者发送消息后,不希望消费者立即消费,而是等待指定的延迟时间后,才被消费者拉取和消费,RocketMQ 不支持任意时间精度的延迟,在4.x版本仅支持「固定等级的延迟」,在5.x版本已经支持"自定义时间的延迟消息",不再仅限固定等级level。
2、固定延迟等级
-
RocketMQ 默认定义了 18 个延迟等级(可通过 Broker 配置文件
rocketmq-broker.conf修改),对应关系如下(核心等级):plaintext
1: 1s, 2: 5s, 3: 10s, 4: 30s, 5: 1m, 6: 2m, 7: 3m, 8: 4m, 9: 5m, 10: 6m, ... 18: 2h -
生产者发送消息时,只需指定延迟等级(而非具体时间),Broker 收到消息后,不会立即将其投入正常队列,而是先存储在「延迟队列」中,等待对应延迟时间到达后,再将消息转发到目标 Topic 的正常队列,供消费者消费。
3、自定义时间的延迟消息
支持按时间戳(或延迟毫秒数)投递消息,也就是不再依赖delay level,可以精确指定投递时间。
java
消息写入 CommitLog
↓
记录到 TimerLog(带时间戳)
↓
时间轮调度
↓
到期后投递到真实 Topic
4、实现方式
(1)固定延迟等级
生产者构建消息时,通过setDelayTimeLevel()指定延迟等级即可:
Message message = new Message("TOPIC_DELAY", "TAG_DELAY", "KEY_DELAY".getBytes(), "延迟消息内容".getBytes());
// 设置延迟等级为5,对应延迟1分钟
message.setDelayTimeLevel(5);
// 同步发送延迟消息
SendResult sendResult = producer.send(message);
(2)自定义延迟消息时间
java
Message message = new Message("TopicTest", body);
// 设置绝对投递时间(时间戳)
message.setDeliveryTimestamp(System.currentTimeMillis() + 30_000);
5、对比
| 维度 | 4.x | 5.x |
|---|---|---|
| 延迟方式 | delay level | delivery timestamp |
| 存储 | SCHEDULE_TOPIC | TimeWheel / TimerLog |
| 调度精度 | 秒级 | 毫秒级 |
| 实现复杂度 | 低 | 高 |
| 灵活性 | 低 | 高 |
六、批量消息
1、定义
批量消息(Batch Message)是指:生产者将多条消息打包成一个批次,一次性发送给 Broker,而非单条发送,核心优势是减少网络通信次数、提高消息发送吞吐量。
2.、核心限制
- 批量发送的所有消息必须属于同一个 Topic、同一个 Tag,且不能是延迟消息、事务消息。
- 单个批量消息批次的总大小不能超过4MB(RocketMQ 默认的消息传输最大限制),若超过需进行分片处理。
- 批量消息中的每条消息可以有独立的 Key,但队列选择策略对整个批次生效(即批次内所有消息会被路由到同一个 Message Queue)。
3、实现方式
(1) 基础批量发送(消息量小,总大小 < 4MB)
java
// 构建多条消息,统一Topic和Tag
List<Message> messageList = new ArrayList<>();
messageList.add(new Message("TOPIC_BATCH", "TAG_BATCH", "KEY1".getBytes(), "批量消息1".getBytes()));
messageList.add(new Message("TOPIC_BATCH", "TAG_BATCH", "KEY2".getBytes(), "批量消息2".getBytes()));
messageList.add(new Message("TOPIC_BATCH", "TAG_BATCH", "KEY3".getBytes(), "批量消息3".getBytes()));
// 批量发送消息
SendResult sendResult = producer.send(messageList);
(2) 大批次消息分片(总大小 > 4MB)
当批量消息总大小超过 4MB 时,需要使用MessageBatch的split()方法进行分片,将大批次拆分为多个小批次,逐个发送:
java
// 构建大量消息(总大小>4MB)
List<Message> largeMessageList = new ArrayList<>();
// ... 向列表中添加大量消息
// 分片处理,每个分片不超过4MB
Iterator<List<Message>> iterator = MessageBatch.split(largeMessageList, 4 * 1024 * 1024).iterator();
while (iterator.hasNext()) {
List<Message> subList = iterator.next();
// 逐个发送分片批次
SendResult sendResult = producer.send(subList);
}
4、注意事项
- 批量消息的发送 ACK 与单条消息一致,同步发送时需等待整个批次的消息都被 Broker 持久化后,才返回整体的
SendResult。 - 若批量消息中某一条消息发送失败(如格式错误),整个批次都会被 Broker 拒绝,生产者需要重新处理该批次消息。
- 批量消息消费时,消费者会收到整个批次的消息列表,需遍历处理每条消息,ACK 机制对整个批次生效(消费成功则批量提交 Offset)。
七、过滤消息
RocketMQ 支持在「Broker 端」对消息进行过滤,只将符合条件的消息推送给消费者,减少网络传输和消费者的无效处理,分为「Tag 过滤」和「SQL92 过滤」两种核心方式。
1、Tag 过滤(推荐,高性能)
(1)特性
- Tag 是消息的子分类,属于轻量级过滤方式,性能极高(Broker 在存储和分发时已对 Tag 进行优化,基于哈希索引)。
- 每个消息只能设置一个 Tag,消费者订阅时可以指定单个 Tag、多个 Tag(用
||分隔)或所有 Tag(用*表示)。
(2)实现方式
-
生产者端:构建消息时指定 Tag:
javaMessage message = new Message("TOPIC_FILTER", "TAG_A", "KEY_FILTER".getBytes(), "TagA过滤消息".getBytes()); -
消费者端:订阅 Topic 时指定需要的 Tag:
java// 方式1:订阅单个Tag(TAG_A) consumer.subscribe("TOPIC_FILTER", "TAG_A"); // 方式2:订阅多个Tag(TAG_A 或 TAG_B) consumer.subscribe("TOPIC_FILTER", "TAG_A||TAG_B"); // 方式3:订阅所有Tag consumer.subscribe("TOPIC_FILTER", "*");
2、SQL92 过滤(灵活,性能略低)
(1)特性
-
SQL92 过滤是基于消息的「用户属性(User Property)」进行的复杂过滤,支持
AND、OR、NOT、>、<、=等 SQL 语法,灵活性极高。 -
性能略低于 Tag 过滤(需执行 SQL 表达式解析和匹配),默认关闭,需要在 Broker 配置文件中开启:
XML# 开启SQL92过滤支持 enablePropertyFilter=true
(2) 实现方式
-
生产者端:构建消息时添加用户属性(
putUserProperty()):javaMessage message = new Message("TOPIC_SQL_FILTER", "TAG_SQL", "KEY_SQL".getBytes(), "SQL过滤消息".getBytes()); // 添加用户属性:订单金额、订单状态 message.putUserProperty("orderAmount", "100"); message.putUserProperty("orderStatus", "PAID"); -
消费者端:使用
MessageSelector.sql()指定 SQL 过滤表达式:java// 订阅消息,过滤条件:订单金额>50 且 订单状态为PAID consumer.subscribe("TOPIC_SQL_FILTER", MessageSelector.sql("orderAmount > 50 AND orderStatus = 'PAID'"));
3、注意事项
- 优先使用 Tag 过滤,仅在 Tag 无法满足需求时(如多条件组合过滤)才使用 SQL92 过滤。
- SQL92 过滤仅支持对消息的用户属性进行操作,不支持对消息体进行过滤(消息体是二进制数据,无法解析)。
- 消费者端的过滤条件一旦设置,后续修改需要重启消费者实例。
八、事务消息
1、定义与场景
事务消息(Transactional Message)用于解决「分布式事务」问题,保证「本地事务」和「消息发送」的原子性(要么两者都成功,要么两者都失败),适用于跨系统的数据一致性场景(如订单创建成功后,发送消息通知库存扣减)。
2、两阶段提交(2PC)+ 事务回查
RocketMQ 事务消息采用「半消息(Half Message)」+「两阶段提交」+「事务回查」的机制,保证分布式事务一致性,核心分为「生产者(事务生产者)」和「Broker(事务协调者)」两个角色。
3、核心流程
(1) 第一步:发送半消息(Half Message)
- 事务生产者向 Broker 发送一条「半消息」,该消息被 Broker 接收并持久化,但不会被投递到目标 Topic 的队列中,消费者无法感知和消费。
- 半消息的核心作用是 "占坑",保证消息发送的可靠性,同时标记该消息为事务待确认状态。
(2)第二步:执行本地事务
- 生产者发送半消息成功后,执行本地业务事务(如数据库操作:创建订单)。
- 本地事务执行完成后,生产者向 Broker 发送「事务确认请求」,包含三种状态:
COMMIT_MESSAGE:本地事务执行成功,确认提交消息,Broker 将半消息转为正常消息,投递到目标 Topic,供消费者消费。ROLLBACK_MESSAGE:本地事务执行失败,确认回滚消息,Broker 删除半消息,不进行投递。UNKNOWN:本地事务执行结果未知(如网络抖动、服务宕机),Broker 会触发「事务回查」机制。
(3)第三步:Broker 事务回查(容错机制)
- 若 Broker 长时间未收到生产者的事务确认请求,或收到
UNKNOWN状态,会定期(默认 60 秒)向事务生产者发送「事务回查请求」,查询对应半消息的本地事务执行结果。 - 生产者需要实现「事务回查接口」,根据半消息的 Key 或消息 ID,查询本地事务的最终执行状态,然后向 Broker 返回最终的确认结果(COMMIT/ROLLBACK)。
- 事务回查有重试次数限制(默认 15 次),超过重试次数后,Broker 默认回滚消息。
4、实现方式
(1) 创建事务生产者并实现事务接口
java
// 1. 创建事务生产者,指定生产者组
TransactionMQProducer producer = new TransactionMQProducer("PRODUCER_GROUP_TRANSACTION");
// 2. 配置NameServer地址
producer.setNamesrvAddr("127.0.0.1:9876");
// 3. 注册事务监听器(实现本地事务执行和事务回查逻辑)
producer.setTransactionListener(new TransactionListener() {
// 实现:执行本地事务
@Override
public LocalTransactionState executeLocalTransaction(Message msg, Object arg) {
try {
// 执行本地业务事务(如:插入订单数据到数据库)
String orderId = new String(msg.getKeys(), StandardCharsets.UTF_8);
orderService.createOrder(orderId);
// 本地事务成功,返回提交消息
return LocalTransactionState.COMMIT_MESSAGE;
} catch (Exception e) {
// 本地事务失败,返回回滚消息
return LocalTransactionState.ROLLBACK_MESSAGE;
}
}
// 实现:事务回查(查询本地事务执行结果)
@Override
public LocalTransactionState checkLocalTransaction(MessageExt msg) {
// 根据消息Key查询本地事务状态
String orderId = new String(msg.getKeys(), StandardCharsets.UTF_8);
Order order = orderService.getOrderById(orderId);
if (order != null && order.getStatus() == 1) {
// 本地事务已成功,返回提交消息
return LocalTransactionState.COMMIT_MESSAGE;
} else if (order == null) {
// 本地事务未执行完成,返回未知,触发再次回查
return LocalTransactionState.UNKNOW;
} else {
// 本地事务失败,返回回滚消息
return LocalTransactionState.ROLLBACK_MESSAGE;
}
}
});
// 4. 启动事务生产者
producer.start();
(2) 发送事务消息
java
Message message = new Message("TOPIC_TRANSACTION", "TAG_TRANSACTION", "ORDER_001".getBytes(), "订单创建事务消息".getBytes());
// 发送事务消息
SendResult sendResult = producer.sendMessageInTransaction(message, null);
5、注意事项
- 事务消息仅支持同步发送,不支持异步发送和单向发送。
- 事务消息不支持延迟消息、批量消息,也不支持 SQL92 过滤。
- 本地事务执行逻辑需保证幂等性,避免事务回查时重复执行导致数据不一致。
- RocketMQ 事务消息保证「最终一致性」,而非强一致性,适用于可以容忍短暂数据不一致的业务场景。
九、ACL 权限控制
1、定义与作用
ACL(Access Control List,访问控制列表)是 RocketMQ 的安全机制,用于控制客户端(生产者 / 消费者)对 Broker 的访问权限,防止未授权的客户端发送、消费或修改消息,保护 RocketMQ 集群的安全性。
2、核心功能
- 基于「账号」的身份认证:客户端连接 Broker 时,需要提供合法的 Access Key 和 Secret Key,Broker 验证通过后才允许建立连接。
- 基于「权限」的访问控制:对不同账号分配不同的权限,支持的核心权限包括:
PUB:发送消息权限(生产者权限)。SUB:消费消息权限(消费者权限)。ALL:拥有 PUB 和 SUB 权限(管理员权限)。DENY:拒绝所有访问。
- 支持细粒度的资源控制:可以针对具体的 Topic、Consumer Group 分配权限,实现 "某个账号仅能发送消息到 TopicA,仅能消费 TopicB"。
3、配置与启用
(1) Broker 端启用 ACL
-
修改 Broker 配置文件
rocketmq-broker.conf,添加以下配置:# 开启ACL权限控制 aclEnable=true -
配置账号与权限:RocketMQ 默认的 ACL 配置文件为
${ROCKETMQ_HOME}/conf/plain_acl.yml,核心配置内容如下:XML# 全局配置(默认权限) globalWhiteRemoteAddresses: - 127.0.0.1 # 白名单IP,无需认证即可访问 # 账号列表 accounts: - accessKey: RocketMQ # 访问密钥(用户名) secretKey: 12345678 # 密钥(密码) whiteRemoteAddresses: # 该账号的白名单IP admin: false # 是否为管理员账号(true:拥有所有权限) defaultTopicPerm: SUB # 默认Topic权限 defaultGroupPerm: SUB # 默认Group权限 # 细粒度资源权限配置 topicPerms: - TopicTest=PUB|SUB # 该账号对TopicTest拥有PUB和SUB权限 - TopicA=PUB # 该账号对TopicA仅拥有PUB权限 groupPerms: - ConsumerGroupTest=SUB # 该账号对ConsumerGroupTest仅拥有SUB权限 -
重启 Broker,使 ACL 配置生效。
(2)客户端配置账号信息
生产者和消费者需要配置 Access Key 和 Secret Key,才能通过 Broker 的 ACL 认证:
java
// 生产者配置ACL
DefaultMQProducer producer = new DefaultMQProducer("PRODUCER_GROUP_ACL");
producer.setNamesrvAddr("127.0.0.1:9876");
// 配置Access Key和Secret Key
producer.setAccessKey("RocketMQ");
producer.setSecretKey("12345678");
// 消费者配置ACL
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("CONSUMER_GROUP_ACL");
consumer.setNamesrvAddr("127.0.0.1:9876");
// 配置Access Key和Secret Key
consumer.setAccessKey("RocketMQ");
consumer.setSecretKey("12345678");
4、注意事项
- ACL 机制仅对客户端与 Broker 的通信进行认证和授权,不对 NameServer 进行控制(NameServer 无状态,不存储消息)。
- 生产环境中,应避免使用默认账号和密码,定期更换 Secret Key,提高安全性。
- 若客户端未配置账号信息,或账号权限不足,连接 Broker 时会抛出
NoPermissionException异常。 - ACL 权限控制会带来轻微的性能损耗(认证和权限校验),但对大部分业务场景影响可忽略。