rabbitmq消息重回队列

当出现异常时,我们需要把这个消息回滚到消息队列,有两种方式:
//ack返回false,并重新回到队列,api里面解释得很清楚
channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
//拒绝消息
channel.basicReject(message.getMessageProperties().getDeliveryTag(), true);
经过开发中的实际测试,当消息回滚到消息队列时,这条消息不会回到队列尾部,而是仍是在队列头部,这时消费者会立马又接收到这条消息进行处理,接着抛出异常,进行 回滚,如此反复进行。这种情况会导致消息队列处理出现阻塞,消息堆积,导致正常消息也无法运行。对于消息回滚到消息队列,我们希望比较理想的方式时出现异常的消息到 达消息队列尾部,这样既保证消息不会丢失,又保证了正常业务的进行,因此我们采取的解决方案是,将消息进行应答,这时消息队列会删除该消息,同时我们再次发送该消息 到消息队列,这时就实现了错误消息进行消息队列尾部的方案。

复制代码
//手动进行应答
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
//重新发送消息到队尾
channel.basicPublish(message.getMessageProperties().getReceivedExchange(),
message.getMessageProperties().getReceivedRoutingKey(), MessageProperties.PERSISTENT_TEXT_PLAIN,
JSON.toJSONBytes(new Object()));
复制代码
如果一个消息体本身有误,会导致该消息体,一直无法进行处理,而服务器中刷出大量无用日志。解决这个问题可以采取两种方案:

1.一种是对于日常细致处理,分清哪些是可以恢复的异常,哪些是不可以恢复的异常。对于可以恢复的异常我们采取第三条中的解决方案,对于不可以处理的异常,我们采用记录日志,直接丢弃该消息方案。

2.另一种是我们对每条消息进行标记,记录每条消息的处理次数,当一条消息,多次处理仍不能成功时,处理次数到达我们设置的值时,我们就丢弃该消息,但需要记录详细的日志。

消息监听内的异常处理有两种方式:
1.内部catch后直接处理,然后使用channel对消息进行确认

2.配置RepublishMessageRecoverer将处理异常的消息发送到指定队列专门处理或记录。监听的方法内抛出异常貌似没有太大用处。因为抛出异常就算是重试也非常有可能会继续出现异常,当重试次数完了之后消息就只有重启应用才能接收到了,很有可能导致消息消费不及时。当然可以配置RepublishMessageRecoverer来解决,但是万一RepublishMessageRecoverer发送失败了呢。。那就可能造成消息消费不及时了。所以即使需要将处理出现异常的消息统一放到另外队列去处理,个人建议两种方式:
①catch异常后,手动发送到指定队列,然后使用channel给rabbitmq确认消息已消费
②给Queue绑定死信队列,使用nack(requque为false)确认消息消费失败

猜你喜欢

转载自blog.csdn.net/qq_30845665/article/details/88531794