问题描述
我在 C# 中使用带有 EasyNetQ 库的 RabbitMQ.我在这里使用 pub/sub 模式.我还有一些问题希望有人能帮助我解决:
I'm using RabbitMQ in C# with the EasyNetQ library. I'm using a pub/sub pattern here. I still have a few issues that I hope anyone can help me with:
- 当使用消息时出现错误,它会自动移到错误队列中.如何实现重试(以便将其放回原始队列,并且当它无法处理 X 次时,它会被移至死信队列)?
- 据我所知,总是有 1 个错误队列用于转储来自所有其他队列的消息.如何为每种类型设置 1 个错误队列,以便每个队列都有自己关联的错误队列?
- 如何轻松重试错误队列中的消息?我尝试了软管,但它只是将消息重新发布到错误队列而不是原始队列.我也不太喜欢这个选项,因为我不想在控制台中摆弄.我最好只针对错误队列进行编程.
有人吗?
推荐答案
您在使用 EasyNetQ/RabbitMQ 时遇到的问题是,与 SQS 或 Azure 服务总线/队列等其他消息传递服务相比,它更加原始",但我会尽力为您指明正确的方向.
The problem you are running into with EasyNetQ/RabbitMQ is that it's much more "raw" when compared to other messaging services like SQS or Azure Service Bus/Queues, but I'll do my best to point you in the right direction.
问题 1.
这将由您来完成.最简单的方法是你可以在 RabbitMQ/EasyNetQ 中 No-Ack 一条消息,它会被放在队列的头部让你重试.这并不是真正可取的,因为它几乎会立即重试(没有时间延迟),并且还会阻止其他消息被处理(如果您有一个预取计数为 1 的单个订阅者).
This will be on you to do. The simplest way is that you can No-Ack a message in RabbitMQ/EasyNetQ, and it will be placed at the head of the queue for you to retry. This is not really advisable because it will be retried almost immediately (With no time delay), and will also block other messages from being processed (If you have a single subscriber with a prefetch count of 1).
我见过使用MessageEnvelope"的其他实现.所以一个包装类,当消息失败时,您在 MessageEnvelope 上增加一个重试变量并将消息重新传递回队列.您必须这样做并在消息处理程序周围编写包装代码,这不是 EasyNetQ 的功能.
I've seen other implementations of using a "MessageEnvelope". So a wrapper class that when a message fails, you increment a retry variable on the MessageEnvelope and redeliver the message back onto the queue. YOU would have to do this and write the wrapping code around your message handlers, it would not be a function of EasyNetQ.
使用上述方法,我还看到人们使用信封,但允许邮件是死信.一旦它进入死信队列,就会有另一个应用程序/工作人员从死信队列中读取项目.
Using the above, I've also seen people use envelopes, but allow the message to be dead lettered. Once it's on the dead letter queue, there is another application/worker reading items from the dead letter queue.
上述所有这些方法都有一个小问题,即在处理消息时实际上没有任何好的方法可以使对数/指数/任何类型的延迟增加.在将消息返回队列之前,您可以在代码中保留"消息一段时间,但这不是一个好方法.
All of these approaches above have a small issue in that there isn't really any nice way to have a logarithmic/exponential/any sort of increasing delay in processing the message. You can "hold" the message in code for some time before returning it to the queue, but it's not a nice way around.
在所有这些选项中,您自己的自定义应用程序读取死信队列并根据包含重试计数的信封决定是否重新路由消息可能是最好的方法.
Out of all of these options, your own custom application reading the dead letter queue and deciding whether to reroute the message based on an envelope that contains the retry count is probably the best way.
问题 2.
您可以使用高级 API 指定每个队列的死信交换.(https://github.com/EasyNetQ/EasyNetQ/wiki/The-Advanced-API#declaring-queues).然而,这意味着您将不得不在几乎所有地方使用高级 API,因为使用订阅/发布的简单 IBus 实现查找基于消息类型和订阅者名称命名的队列.使用自定义队列声明意味着您将自己处理队列的命名,这意味着当您订阅时,您需要知道您想要的名称等.不再为您自动订阅!
You can specify a dead letter exchange per queue using the advanced API. (https://github.com/EasyNetQ/EasyNetQ/wiki/The-Advanced-API#declaring-queues). However this means you will have to use the advanced API pretty much everywhere as using the simple IBus implementation of subscribe/publish looks for queues that are named based on both the message type and subscriber name. Using a custom declare of queue means you are going to be handling the naming of your queues yourself, which means when you subscribe, you will need to know the name of what you want etc. No more auto subscribing for you!
问题 3
错误队列/死信队列只是另一个队列.您可以收听此队列并使用它做您需要做的事情.但实际上并没有任何开箱即用的解决方案听起来适合您的需求.
An Error Queue/Dead Letter Queue is just another queue. You can listen to this queue and do what you need to do with it. But there is not really any out of the box solution that sounds like it would fit your needs.
这篇关于如何使用 EasyNetQ/RabbitMQ 进行错误处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!