RocketMQ发送批量消息后消费端Tag被异常篡改问题咨询
RocketMQ批量消息Tag异常拼接问题
问题表现
- 生产端向RocketMQ发送批量消息时,单条消息预设Tag值为
batch - 消费端获取到的消息Tag实际为
batchCLUSTERt0,存在非预期的字符串拼接 - 生产端使用的发送代码如下:
public SendResult send(Collection<Message> msgs, MessageQueue messageQueue) throws MQClientException, RemotingException, MQBrokerException, InterruptedException { return this.defaultMQProducerImpl.send(batch(msgs), messageQueue); }
问题根因
该问题是RocketMQ 4.9.4及更早版本客户端的已知序列化缺陷:
- 调用内部
batch()方法组装批量消息时,单条消息的Tag字段序列化完成后,没有正确更新字节缓冲区的写入偏移标记 - 后续写入的集群名称(对应异常字符串中的
CLUSTER)、队列序号(对应异常字符串中的t0)等系统属性内容,直接追加到了Tag字段的字节数组尾部 - 消费端反序列化时按照错误的字段长度读取Tag,就会把后续拼接的系统属性内容一并读出,出现Tag值异常的现象
修复方案
- 优先升级RocketMQ客户端依赖版本到4.9.5及以上,官方在该版本修复了批量消息序列化的偏移计算逻辑,可彻底解决该问题
- 若暂时无法升级版本,不要直接调用
defaultMQProducerImpl的内部发送方法,改用官方对外暴露的标准批量发送接口defaultMQProducer.send(Collection<Message> msgs, MessageQueue mq),标准接口内部会自动做消息属性的边界校验,避免字段越界 - 临时规避可在批量消息组装前,遍历所有待发送消息重新调用
setTags()设置一次Tag值,触发属性字段的长度重新计算,绕过序列化逻辑的缺陷
内容的提问来源于stack exchange,提问作者John_Lin
相关产品推荐
相关产品推荐

