当前位置: 首页 > 知识库问答 >
问题:

引发TaskCanceledException时Azure ServiceBus队列不重试消息

胡永逸
2023-03-14

我有一个Azure WebJob函数,用于侦听Azure ServiceBus队列上的消息。通常,当我在代码中遇到异常时,会根据Azure WebJobs SDK文档放弃该消息:

SDK在PeekLock模式下接收消息,如果函数成功完成,则调用消息完成,如果函数失败,则调用放弃。如果函数运行时间超过PeekLock超时时间,锁将自动更新。

根据Azure ServiceBus文档,这意味着该消息将再次可用,并将重试:

如果应用程序由于某种原因无法处理消息,它可以对收到的消息调用放弃异步方法(而不是CompleteAsync)。此方法使服务总线能够解锁消息,并使其可供同一消费者或另一竞争消费者再次接收。其次,有一个与锁相关的超时,如果应用程序在锁超时过期之前无法处理消息(例如,如果应用程序崩溃),那么服务总线将解锁消息并使其可再次接收(默认情况下基本上执行放弃异步操作)。

上面描述的行为是通常会发生的,但是我发现了这个规则的一个例外。如果我的代码特别抛出了一个Task取消异常,消息不会像它应该的那样被放弃:

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

当通过web作业运行此函数时,我看到错误消息以day格式清晰地打印出来,但是消息会被消耗掉,不会重试,也不会进入死信队列。如果我将上面的TaskCanceledException替换为invalidooperationexception,则消息将被保留并按其应该的方式重试(我已根据实际的ServiceBus队列对此进行了验证)。

对于这种行为,我一直找不到任何解释。目前,我在另一个异常中包装了Task取消异常来解决这个问题。

我遇到的是Azure WebJobs SDK中的错误吗?TaskCanceledException在这方面是否特别,或者其他类型的异常是否具有类似的行为?

我正在使用以下Nuget软件包:

  • 微软。蔚蓝色的WebJobs 2.3.0

共有1个答案

云瑞
2023-03-14

如果执行不成功,函数应该放弃消息。如果您说消息没有被放弃和重试,即使它应该被放弃和重试(假设MaxDeliveryCount设置为大于1,接收模式为PeekLock),那么很可能是函数的问题,而不是Azure的问题服务总线。您可以通过运行控制台应用程序并执行相同的操作来验证这一点,检查消息在哪里完成并从队列中删除,或者仍然在队列中并可供使用。

此外,看起来你正在使用旧版本的WebJobs(和Azure服务总线)。执行验证时,需要使用旧的Azure服务总线客户端(WindowsAzure。ServiceBus)而不是新的(Microsoft.天青。ServiceBus)。

 类似资料:
  • 我在使用新的0.3.0-beta版WebJobs SDK的WebJob中有以下逻辑。当我的代码处理消息失败时,Azure仪表板将显示聚合异常(这是有意义的,因为这是异步的)。但是,它不会重试处理消息。 我能找到的非常小的留档表明消息应该在失败后10分钟内重试。新的SDK不是这样吗? 我得到的异常源于SQL超时异常(在我的代码中是针对SQL Azure的db查询):

  • 解决方案#3:使用AWS SQS标准队列和AWS ElasticCache(Redis或Memcached)。对于每条消息,“messageID”字段将保存在缓存服务器中,并在以后检查是否重复。存在意味着此消息已被处理。(顺便说一下,“MessageID”在缓存服务器中应该存在多长时间。AWS SQS文档没有提到消息可以重复到多长时间。)

  • 如何修复ProbableAuthenticationError? 主机是Debian7和Python 2.7.3和pika 0.9.14,来宾是Ubuntu 15.04和rabbitmq-server 3.4.3-2

  • 我有一个使用Spring和RabbitMQ的项目设置。目前,我的应用程序可能会收到一条amqp消息,在另一个异步进程完成之前无法处理该消息(遗留和完全分离,我无法控制)。因此,结果是我可能不得不等待处理消息一段时间。其结果是变压器出现异常。 当消息被NACK回rabbitMQ时,它会将其放回队列的头部,并立即重新拉入队列。如果我收到的无法处理的消息等于并发侦听器的数量,我的工作流就会被锁定。它转动

  • 为什么已经拥有了共享内存时需要消息队列呢? 这将是多种原因,让我们将其分解为多个点来简化 - 据了解,一旦消息被一个进程接收到,它将不再可用于任何其他进程。 而在共享内存中,数据可供多个进程访问。 如果想使用小信息格式进行通信。 当多个进程同时进行通信时,共享内存数据需要同步保护。 使用共享内存的写入和读取频率很高,那么实现功能将会非常复杂。 在这种情况下不值得使用。 如果所有的进程不需要访问共享

  • 一、消息模型 点对点 发布/订阅 二、使用场景 异步处理 流量削锋 应用解耦 三、可靠性 发送端的可靠性 接收端的可靠性 参考资料 一、消息模型 点对点 消息生产者向消息队列中发送了一个消息之后,只能被一个消费者消费一次。 发布/订阅 消息生产者向频道发送一个消息之后,多个消费者可以从该频道订阅到这条消息并消费。 发布与订阅模式和观察者模式有以下不同: 观察者模式中,观察者和主题都知道对方的存在;