将消息移动到Azure服务总线中的“死信”

6ojccjat  于 2023-03-03  发布在  其他
关注(0)|答案(2)|浏览(150)

我已经实现了后退指数重试。所以基本上,如果有任何异常,我克隆消息,然后我通过添加一些延迟重新提交到队列。
现在我面临着两个问题-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() };

                }

请帮我一下

8ftvxx2r

8ftvxx2r1#

当你克隆一个消息时,它会变成一个新消息,这意味着系统属性不会被克隆,这会给克隆的消息一个新的传递计数,重新从1开始。
你可以查看Azure Service Bus的***Peek Lock功能***。使用PeekLock时,消息在队列中不可见,直到你显式放弃它(将其放回队列,并增加传递计数)或在处理消息时完成(如果一切按预期进行)。另一个选项是显式死信此消息。
该功能记录如下:https://learn.microsoft.com/en-us/azure/service-bus-messaging/message-transfers-locks-settlement#peeklock
但重要的是,如果您***不执行***上述任何操作(如***克隆),***Azure服务总线将*在定义的时间间隔(LockDuration属性)后或您放弃消息时*自动使消息再次可见。
因此,要获得
延迟重试和死信行为
(当达到最大传递计数时),您可以使用以下选项:

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

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

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

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

注意:如果选择选项2.),请确保重试周期符合定义的LockDuration,以便在仍在重试处理消息时,消息不会再次出现在队列中。还可以通过在重试之间对消息调用 RenewLock() 方法来在重试之间续订锁定。

如果你在代码中实现了重试策略,我建议你使用Polly.Net,它已经给你提供了很好的特性,比如重试和断路器策略。

72qzrwbm

72qzrwbm2#

我们使用“Azure.Messaging.ServiceBus”库通过Azure服务总线实现了类似的重试功能。
对我们有效的方法是使用ProcessMessageEventArgs.DeadLetterMessageAsync(服务总线接收消息)

{
var sbClient = new ServiceBusClient($"{servicebusNamespace}.servicebus.windows.net", tokenCredential);

var serviceBusProcessor = sbClient.CreateProcessor(topicName, subscriptionName, null);

 serviceBusProcessor.ProcessMessageAsync += HandleMessageAsync;
}

protected async Task HandleMessageAsync(ProcessMessageEventArgs args)
{
     await args.DeadLetterMessageAsync(args.Message);
}

相关问题