[英]Re-queue message on exception
我正在尋找一種可靠的方法來重新排隊無法正確處理的消息 - 目前。
我一直在關注http://dotnetcodr.com/2014/06/16/rabbitmq-in-net-c-basic-error-handling-in-receiver/ ,似乎支持在RabbitMQ中重新排隊消息API。
else //reject the message but push back to queue for later re-try
{
Console.WriteLine("Rejecting message and putting it back to the queue: {0}", message);
model.BasicReject(deliveryArguments.DeliveryTag, true);
}
但是我正在使用EasyNetQ。 所以想知道我將如何做類似的事情。
bus.Subscribe<MyMessage>("my_subscription_id", msg => {
try
{
// do work... could be long running
}
catch ()
{
// something went wrong - requeue message
}
});
這甚至是一個好方法嗎? 沒有ACK
消息是否會導致問題do work
超過了等待ACK
由RabbitMQ的服務器超時。
所以我提出了這個解決方案。 這取代了EasyNetQ的默認錯誤策略。
public class DeadLetterStrategy : DefaultConsumerErrorStrategy
{
public DeadLetterStrategy(IConnectionFactory connectionFactory, ISerializer serializer, IEasyNetQLogger logger, IConventions conventions, ITypeNameSerializer typeNameSerializer)
: base(connectionFactory, serializer, logger, conventions, typeNameSerializer)
{
}
public override AckStrategy HandleConsumerError(ConsumerExecutionContext context, Exception exception)
{
object deathHeaderObject;
if (!context.Properties.Headers.TryGetValue("x-death", out deathHeaderObject))
return AckStrategies.NackWithoutRequeue;
var deathHeaders = deathHeaderObject as IList;
if (deathHeaders == null)
return AckStrategies.NackWithoutRequeue;
var retries = 0;
foreach (IDictionary header in deathHeaders)
{
var count = int.Parse(header["count"].ToString());
retries += count;
}
if (retries < 3)
return AckStrategies.NackWithoutRequeue;
return base.HandleConsumerError(context, exception);
}
}
你這樣替換它:
RabbitHutch.CreateBus("host=localhost", serviceRegister => serviceRegister.Register<IConsumerErrorStrategy, DeadLetterStrategy>())
您必須使用AdvancedBus
因此您必須手動設置所有內容。
using (var bus = RabbitHutch.CreateBus("host=localhost", serviceRegister => serviceRegister.Register<IConsumerErrorStrategy, DeadLetterStrategy>()))
{
var deadExchange = bus.Advanced.ExchangeDeclare("exchange.text.dead", ExchangeType.Direct);
var textExchange = bus.Advanced.ExchangeDeclare("exchange.text", ExchangeType.Direct);
var queue = bus.Advanced.QueueDeclare("queue.text", deadLetterExchange: deadExchange.Name);
bus.Advanced.Bind(deadExchange, queue, "");
bus.Advanced.Bind(textExchange, queue, "");
bus.Advanced.Consume<TextMessage>(queue, (message, info) => HandleTextMessage(message, info));
}
這將死信3次失敗。 之后,它將轉到EasyNetQ提供的默認錯誤隊列以進行錯誤處理。 您可以訂閱該隊列。
當異常傳播出您的使用者方法時,消息將被刪除。 所以這會引發一封死信。
static void HandleTextMessage(IMessage<TextMessage> textMessage, MessageReceivedInfo info)
{
throw new Exception("This is a test!");
}
據我所知,沒有辦法手動ack
, nack
或reject
與EasyNetQ的消息。
我看到你已經與EasyNetQ團隊開了一張發票 ,關於這個...但是沒有答案。
FWIW,這是一件非常合適的事情。 我使用的所有庫都支持此功能集(在NodeJS中),這很常見。 我很驚訝EasyNetQ不支持這個。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.