带有spring amqp的rabbitmq-在AmqpException情况下卡住的消息 [英] rabbitmq with spring amqp - messages stuck in case of AmqpException

查看:280
本文介绍了带有spring amqp的rabbitmq-在AmqpException情况下卡住的消息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用者内抛出了AmqpException. 我的期望是,该消息将按FIFO顺序返回到队列,并在将来的某个时间重新处理.

I am throwing an AmqpException inside of my consumer. My expectation is that the message will return back to the queue in FIFO order and will be reprocessed sometime in the future.

似乎Spring AMQP不会将消息释放回队列.但是相反,它会尝试一遍又一遍地重新处理失败的消息. 这将阻止新到达的消息被处理.被卡住的文件永远在AMQP控制台内部以未打包"状态显示.

It seems as if Spring AMQP does not release the message back to the queue. But instead tries to reprocess the failed messages over and over again. This blocks the newly arrived messages from being processed. The ones that are stuck appear in the "unpacked" state forever inside of the AMQP console.

有什么想法吗?

推荐答案

rabbitmq/Spring AMQP就是这样工作的;如果邮件被拒绝(引发任何异常),则默认情况下将对邮件重新排队,并将其放回队列的开头,以便立即对其进行重试.

That's the way rabbitmq/Spring AMQP works; if a message is rejected (any exception is thrown) the message is requeued by default and is put back at the head of the queue so it is retried immediately.

...在将来的某个时间重新处理.

... reprocessed sometime in the future.

您必须适当地配置一些东西才能实现这一目标.

You have to configure things appropriately to make that happen.

首先,您必须告诉代理不要重新排队该消息.这是通过在侦听器容器上将defaultRequeueRejected设置为false(默认情况下为true)来完成的.或者,您可以抛出AmqpRejectAndDontRequeueException来指示容器拒绝(而不是重新排队)单个消息.

First, you have to tell the broker to NOT requeue the message. That is done by setting defaultRequeueRejected on the listener container to false (it's true by default). Or, you can throw an AmqpRejectAndDontRequeueException which instructs the container to reject (and not requeue) an individual message.

但这还不是终点.这样做只会导致被拒绝的邮件被丢弃.

But that's not the end of it; just doing that will simply cause the rejected message to be discarded.

为避免这种情况,您必须为死信交换/队列队列-被拒绝的消息然后被发送到DLX/DLQ而不是被丢弃.通常建议使用策略而不是队列参数.

To avoid that, you have to set up a Dead Letter Exchange/Queue for the queue - rejected messages are then sent to the DLX/DLQ instead of being discarded. Using a policy rather than queue arguments is generally recommended.

最后,您可以设置一条消息时间以保留在DLQ上,这样,在那之后,该消息将从队列中删除.如果您在那个队列(DLQ)上设置了另一个合适的死信交换,则可以使时间到期后将消息重新排队回到原始队列.

Finally, you can set a message time to live on the the DLQ so, after that time, the message is removed from the queue. If you set up an another appropriate dead letter exchange on that queue (the DLQ), you can cause the message to be requeued back to the original queue after the time expires.

请注意,这仅适用于原始队列中被拒绝的交货;在该队列中的邮件到期时将不起作用.

Note that this will only work for rejected deliveries from the original queue; it will not work when expiring messages in that queue.

请参见

See this answer and some of the links from its question for more details.

您可以使用x-death标头的内容来确定是否应该在经过多次尝试后完全放弃(捕获异常并以某种方式处理不良消息;不要引发异常,容器将确认消息).

You can use the contents of the x-death header to decide if you should give up completely after some number of attempts (catch the exception and somehow dispose of the bad message; don't thrown an exception and the container will ack the message).

这篇关于带有spring amqp的rabbitmq-在AmqpException情况下卡住的消息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆