0


RabbitMQ 消费端异常重复循环小记

RabbitMQ 消费端异常

背景

测试项目消费者功能,因为随意输入的message,导致消费端转对象时报错,此时很离谱的事就出现了,消费端一直在循环 消费消>报错->消费. 问题点也能想的来,因为默认是自动应答,异常了相当于是没有应答,然后就一直异常重新抛回队列进行投递.

思路

1.将抛异常的地方干掉,自己处理异常的机制,这样每次都是自动应答

​ 显而易见这样就解决了,但是相当于报异常的时候自己要去写方案去处理,否则这条消息就丢了,因为MQ认为消息已经是消费成功了

2.try catch需要处理的异常,直接抛出来,交给MQ,到上限进入死信队列

spring:rabbitmq:listener:simple:default-requeue-rejected:true# 不丢弃retry:enabled:true# 开启消费者进行重试max-attempts:5# 最大重试次数initial-interval:3000# 重试时间间隔   

这种方式需要配置最大重试次数,MQ在尝试足够次数后,这条消息就不会再被处理了,如果是因为网络抖动等不可抗力原因,那么这种方式是有效的,只能说是无能为力的失败,但是如果是因为业务处理抛出来的异常,那不管执行几次都不会成功,相当于消费失败了.

这里有个

default-requeue-rejected: true

其实跟这个没关系,主要是靠消费重试来解决的,因为默认的就是true,如果只设置

default-requeue-rejected: false

那么效果就是只会处理一次,异常了就是异常了.

然后在前面的基础上如果有死信队列那就入死信队列.

3.配置消息过期时间,这样时间到期就会直接进入死信队列

这种方式有三种配置方式

1. 消息过期时间 每个消息有自己单独的过期时间,如果指定时间内没有被消费,则会自动过期对应    message.expiration
2. 队列消息过期时间  每个消息过期时间进入队列的过期时间是一致的,到期则会过期 (x-message-ttl)
3. 指定队列的过期时间,对象是队列,将队列删除了.消息自然全部都过期了 (x-expires)
   前提是当前队列没有消费者,也没有被重新声明,并且没有使用channel.basicGet调,如果在过期时间内有消费者,在消费者断开之后会重置过期时间

但是会有一点,RabbitMQ只会对队列头部的消息进行过期淘汰。如果单独给消息设置TTL,先入队列的消息过期时间 如果设置比较长,后入队列的设置时间比较短。会造成消息不会及时地过期淘汰,导致消息的堆积

4.设置死信队列

暂略

总结

1. 最好是有死信队列托底
2. 先把能知道出错的地方都catch住, catch里看是自行处理还是抛出异常交给MQ
3. 不确定的地方那就让他重试也就是配置default-requeue-rejected为true,一定次数后,进入死信队列
4. 如果需要设置成手动应答的形式那更好,我们知道什么时候能处理异常,什么时候能返回ack
5. 如果消息配置了过期时间,那到时间就回到死信队列中去,不管是什么机制的异常处理
6. 死信队列最好有相关逻辑的处理方案,要不然无脑推就会嘣爆炸

所以这里根据业务采用了直接抛出异常的形式,重试次数5,生产者发送消息的时候并设置Message.expiration 过期时间, 超出标准重试次数或者到期的消息,进入死信队列等待处理


本文转载自: https://blog.csdn.net/minchangzy/article/details/125739960
版权归原作者 毁人不倦zy 所有, 如有侵权,请联系我们删除。

“RabbitMQ 消费端异常重复循环小记”的评论:

还没有评论