简体   繁体   English

抛出TaskCanceledException时,Azure ServiceBus队列不会重试消息

[英]Azure ServiceBus queue not retrying messages when TaskCanceledException is thrown

I have an Azure WebJob function that listens to messages on an Azure ServiceBus queue. 我有一个Azure WebJob函数,用于侦听Azure ServiceBus队列上的消息。 Usually when I encounter an exception in my code, the message is abandoned as per the Azure WebJobs SDK documentation : 通常,当我在代码中遇到异常时,将根据Azure WebJobs SDK文档放弃该消息:

The SDK receives a message in PeekLock mode and calls Complete on the message if the function finishes successfully, or calls Abandon if the function fails. SDK以PeekLock模式接收消息,如果函数成功完成,则在消息上调用Complete;如果函数失败,则调用Abandon。 If the function runs longer than the PeekLock timeout, the lock is automatically renewed. 如果该函数的运行时间超过PeekLock超时,则会自动更新锁定。

According to the Azure ServiceBus documentation this should mean that the message becomes available again, and will be retried: 根据Azure ServiceBus文档,这应该意味着消息再次可用,并将重试:

If the application is unable to process the message for some reason, it can call the AbandonAsync method on the received message (instead of CompleteAsync). 如果应用程序由于某种原因无法处理消息,则可以对收到的消息(而不是CompleteAsync)调用AbandonAsync方法。 This method enables Service Bus to unlock the message and make it available to be received again, either by the same consumer or by another competing consumer. 此方法使服务总线能够解锁消息并使其可由同一消费者或其他竞争消费者再次接收。 Secondly, there is a timeout associated with the lock and if the application fails to process the message before the lock timeout expires (for example, if the application crashes), then Service Bus unlocks the message and makes it available to be received again (essentially performing an AbandonAsync operation by default). 其次,存在与锁相关联的超时,并且如果应用程序在锁定超时到期之前未能处理该消息(例如,如果应用程序崩溃),则服务总线解锁该消息并使其可用于再次接收(实质上默认情况下执行AbandonAsync操作)。

The behavior described above is what usually happens, but I have found an exception to this rule. 上面描述的行为通常会发生,但我发现此规则有例外。 If my code throws a TaskCanceledException specifically, the message is not abandoned as it should: 如果我的代码专门抛出TaskCanceledException ,则消息不会被放弃,因为它应该:

public void ProcessQueueMessage([ServiceBusTrigger("queue")] BrokeredMessage message, TextWriter log)
{
     throw new TaskCanceledException();
}

When running this function through a web job, I see the error message printed out clear as day, but the message is consumed without any retries and without entering the dead-letter queue. 通过Web作业运行此功能时,我看到错误消息打印出来当天,但消息没有任何重试而没有进入死信队列。 If I replace the TaskCanceledException above with InvalidOperationException , the message is abondened and retried as it should (I have verified this against an actual ServiceBus queue). 如果我用InvalidOperationException替换上面的TaskCanceledException ,则消息将被删除并按原样重试(我已经针对实际的ServiceBus队列验证了这一点)。

I have not been able to find any explanation for this behavior. 我无法找到任何有关此行为的解释。 Currently I am wrapping the TaskCanceledException in another exception to work around the issue. 目前,我将TaskCanceledException包装在另一个例外中以解决此问题。

The question 这个问题

Is what I am experiencing a bug in the Azure WebJobs SDK? 我在Azure WebJobs SDK中遇到错误了吗? Is TaskCanceledException special in this regard, or do other types of exceptions have similar behavior? TaskCanceledException在这方面是特殊的,还是其他类型的异常有类似的行为?


I am using the following NuGet packages: 我使用以下NuGet包:

  • Microsoft.Azure.WebJobs 2.3.0 Microsoft.Azure.WebJobs 2.3.0
  • Microsoft.Azure.WebJobs.ServiceBus 2.3.0 Microsoft.Azure.WebJobs.ServiceBus 2.3.0

Functions are supposed to abandon the message if execution was not successful. 如果执行不成功,函数应该放弃消息。 If you're saying the message was not abandoned and retried even though it should be (assuming MaxDeliveryCount was set to larger than 1 and the receive mode was PeekLock ), then it's likely to be the issue with the Functions and not Azure Service Bus. 如果您说消息未被放弃MaxDeliveryCount试,即使它应该是(假设MaxDeliveryCount设置为大于1且接收模式为PeekLock ),那么它可能是函数而不是Azure Service Bus的问题。 You could verify that by running a console application and performing the same, checking wherever the message is completed and removed from the queue or still on the queue and available for consumption. 您可以通过运行控制台应用程序并执行相同操作来验证,检查消息完成的任何位置,并从队列中删除或仍然在队列中并可供使用。

Also, looks like you're using the older version of WebJobs (and Azure Service Bus). 此外,看起来您正在使用旧版本的WebJobs(和Azure Service Bus)。 When performing verification, you'd need to use the older Azure Service Bus client ( WindowsAzure.ServiceBus ) and not the new one ( Microsoft.Azure.ServiceBus ). 执行验证时,您需要使用较旧的Azure Service Bus客户端( WindowsAzure.ServiceBus )而不是新的客户端( Microsoft.Azure.ServiceBus )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM