文章目录
- 1. 需求
- 1.1. 配置
- 1.2 . 代码
- 1.3 问题:
- 2. 结合redis解决
1. 需求
在rabbitmq消息确认设置为手动提交的时候,消息怎么在重试一定次数的情况下才放入死信队列。
1.1. 配置
- rabbitmq的配置:消费端手动应答
spring:
rabbitmq:
listener:
simple:
acknowledge-mode: manual # 消费方手动应答
direct:
retry:
enabled: true # 开启消费重试机制
max-attempts: 3 # 最大重试机制,默认为3
initial-interval: 1000 # 重试间隔,单位毫秒,默认1000
1.2 . 代码
手动确认提交,当不确认消息,设置重新放回队列的时候
channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
1.3 问题:
在手动确认的条件下,使用如上配置消息在重试三次之后,就会放入死信队列,事实上手动提交的时候,basicNack的最后一个参数requeue = true时,消息会被无限次的放入消费队列重新消费,直至回送ACK。但是当requeue = false 的时候,此时消息就会立马进入到死信队列。
那么手动提交怎么去设置消息消费失败后回到队列的思路呢?
2. 结合redis解决
使用redis 存储消息的重试次数,redis 的key 就是消息的Id, value为消息的重试次数,代码如下:
//消费失败重试3次,3次失败后放入死信队列
msgId = (String) message.getMessageProperties().getHeaders().get("spring_returned_message_correlation");
int retryCount = (int) redisUtil.get(msgId);
System.out.println("------ retryCount : " + retryCount);
if (retryCount >= MAX_RECONSUME_COUNT) {
//requeue = false 放入死信队列
channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
} else {
//requeue = true 放入消费队列重试消费
channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
redisUtil.set(msgId, retryCount + 1);
}