首页 > 解决方案 > 在 Azure 服务总线 SubscriptionClient 中,什么样的异常会重试?

问题描述

我正在努力处理以死信队列结束的消息太快。我已经指定了这样的 ExponentialRetry 策略:

        private readonly RetryExponential _retryPolicy = new RetryExponential(
            TimeSpan.FromSeconds(1),
            TimeSpan.FromMinutes(20),
            10);

当 SQL Server 暂时关闭 (" because its replica role is RESOLVING which does not allow connections. Try the operation again later.") 时,消息将在死信队列中结束,无需重试。

我该怎么做才能重试?

我查看了 SDK 的源代码,似乎只有瞬态 ServiceBusException 才会重试,但我觉得这很奇怪。

更新:

在与我的同事讨论并在 Application Insights 中查看更多信息后,我可以看到它实际上已经重试了 10 次,但都在 2 秒内完成。这是在订阅本身上设置的最大传递计数,而不是在客户端上。此交付不受我想要和需要的任何指数退避的影响。

订阅的最大交付计数为 10

标签: azureservicebusazure-servicebus-queues

解决方案


我查看了 SDK 的源代码,似乎只有瞬态 ServiceBusException 才会重试,但我觉得这很奇怪。

这是正确的并且符合设计。当错误是暂时性错误(连接问题、限制等)时,客户端将使用RetryPolicy. 否则,重试无济于事,因此重试相同的操作也无济于事。

对于您的具体情况 - 您拥有的代码被执行并处理消息。客户和经纪人之间没有问题。这就是该策略没有生效的原因。此外,您确认这是一个应用程序问题,因为您的进程重试了消息并最终进入死信队列。

我正在努力处理以死信队列结束的消息太快。

您需要的是应用程序重试和回退,以确保消息不会立即重试多次,从而导致它成为死信。这部分可能有点棘手,具体取决于您的 SQL 服务器关闭了多长时间。有几个选项:

  1. 将消息安排在将来让 SQL Server 恢复。此选项将需要安排新消息。
  2. 推迟消息并稍后处理。这意味着您需要保留延迟消息SequenceNumber的记录。实现此选项的一种方法是使用原始消息的序列号调度新消息。
  3. 在服务总线之上使用抽象,提供高级概念/功能来执行重试,例如MassTransit或 NServiceBus(可恢复性)。

推荐阅读