首页 > 解决方案 > 将消息移动到 azure servicebus 中的“deadletter”

问题描述

我已经实现了退避指数重试。因此,基本上,如果有任何异常,我会克隆消息,然后通过添加一些延迟将其重新提交到队列中。

现在我面临 2 个问题 - 1)当我克隆并重新提交回队列时,我发现交付计数没有增加 2)如果达到最大交付计数,我想将其移至死信。

代码 :

catch (Exception ex)
                {
                    _logger.Error(ex, $"Failed to process request {requestId}");
                    var clone = messageResult.Message.Clone();
                    clone.ScheduledEnqueueTimeUtc = DateTime.UtcNow.AddSeconds(45);
                    
                    await messageResult.ResendMessage(clone);
                    if (retryCount == MaxAttempts)
                    {
                        //messageResult.dea
                    }
                    return new PdfResponse { Error = ex.ToString() };

                }

请帮助我

标签: c#azureasp.net-core.net-coreazureservicebus

解决方案


当您克隆一条消息时,它会变成一条新消息,这意味着系统属性不会被克隆,这会为克隆的消息提供从 1 开始的新传递计数。另见https://docs.azure.cn/zh-cn/dotnet/api/microsoft.azure.servicebus.message.clone?view=azure-dotnet

您可以查看 Azure 服务总线的Peek Lock 功能。使用 PeekLock 时,消息在队列中不可见,直到您明确放弃它(将其放回队列并增加传递计数)或在处理消息时一切按预期工作时完成。另一种选择是明确地死信这条消息。

此处记录了该功能:https ://docs.microsoft.com/en-us/azure/service-bus-messaging/message-transfers-locks-settlement#peeklock

但重要的是,如果您不执行上述任何操作(例如克隆), Azure 服务总线将在定义的时间间隔(LockDuration 属性)或您放弃它时自动使消息再次可见。

因此,要获得延迟重试和死信行为(当达到最大传递计数时),您可以使用以下选项:

选项 1. 通过 Azure 服务总线自动解锁重试

当由于某种原因暂时无法执行消息处理时,捕获异常并确保没有执行任何提到的操作(放弃、完成或死信)。这将使消息在剩余时间内保持不可见,并在达到配置的锁定持续时间后使其再次可见。Azure 服务总线也将按预期增加交付计数。

选项 2. 实施您自己的重试策略

在您的代码中执行您自己的重试策略并重试处理消息。如果已达到最大重试次数,请放弃该消息,在达到重试时间后,该消息将在下一个队列读取步骤中再次可见。在这种情况下,交货计数也会增加。

注意:如果您选择选项 2.) 确保您的重试周期符合定义的 LockDuration,这样如果您仍在重试处理它,您的消息将不会再次出现在队列中。您还可以通过在重试之间的消息上调用RenewLock()方法来更新重试之间的锁。

如果您在代码中实施重试策略,我建议您使用Polly .Net,它已经为您提供了强大的功能,例如重试和断路器策略。见https://github.com/App-vNext/Polly


推荐阅读