延迟消息流程

总结
关于延迟消息的投递和重试:
1、延迟期内没收到是正常的 - 消息存储在SCHEDULE_TOPIC中,对消费者不可见
2、到期后没收到会重试 - 遵循普通消息的重试机制(最多16次)
3、处理失败会自动重试 - 重试间隔逐渐增加,最终进入死信队列
关于清理策略:
基础机制相同" - 都基于文件创建时间和磁盘使用率
SCHEDULE_TOPIC有特殊策略" - 可能更早被清理,因为只是中间状态
转投后的消息按目标Topic策略清理" - 延迟消息到期后变成普通消息
死信队列
当消息消费失败达到最大重试次数后,消息就会被发送到死信队列,
死信队列(Dead Letter Queue,DLQ)是存储所有重试后仍然消费失败的消息的特殊队列。
// 死信队列的命名规则
String deadLetterTopic = "%DLQ%" + consumerGroup;
// 示例:消费者组"order_group"的死信队列为"%DLQ%order_group"
以下是消息进入死信队列的条件和过程:
最大重试次数:RocketMQ默认允许每条消息最多重试16次。如果消息在重试16次后仍然失败,那么这条消息就会被放入死信队列。
重试次数配置:可以通过设置Consumer的maxReconsumeTimes属性来改变最大重试次数。当重试次数超过这个设置的值时,消息就会进入死信队列。
死信队列的特征:
死信队列是一个特殊的Topic,名称为%DLQ% + ConsumerGroup。例如,消费者组为my_consumer_group,则对应的死信队列Topic为%DLQ%my_consumer_group。
死信队列中的消息不会再被消费者正常消费。需要人工干预,比如查看失败原因,修复问题后,重新发送消息到原来的Topic。
进入死信队列的消息不会自动重试,需要人工处理。
死信队列的消息存储时间与普通消息相同,默认72小时后自动删除(可配置)。
只有集群模式(CLUSTERING)下才有重试和死信队列,广播模式(BROADCASTING)下没有重试机制,所以也不会进入死信队列。
如果消费者在消费消息时抛出异常,返回RECONSUME_LATER,或者返回null(相当于成功),或者超时(默认15分钟),都会触发重试。
死信队列的使用:开发人员可以订阅死信队列,来监控哪些消息处理失败,然后进行人工处理或者自动补偿。
DefaultMQPushConsumer deadLetterConsumer = new DefaultMQPushConsumer("dead_letter_consumer_group");
deadLetterConsumer.subscribe("%DLQ%my_consumer_group", "*");
deadLetterConsumer.registerMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
for (MessageExt msg : msgs) {
// 打印死信消息的内容和原始消息ID
System.out.println("收到死信消息: " + new String(msg.getBody()));
System.out.println("原始消息ID: " + msg.getProperty(MessageConst.PROPERTY_ORIGIN_MESSAGE_ID));
// 可以在这里进行人工处理,比如记录日志、发送告警、将消息重新发送到正常的Topic等
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
注意:死信队列的消息属性中会包含原始消息的一些信息,比如原始Topic、原始消息ID等,可以通过msg.getProperty来获取。
820

被折叠的 条评论
为什么被折叠?



