【问题标题】:Deferring and re-receiving a deferred message in an IHostBuilder hosted service在 IHostBuilder 托管服务中延迟和重新接收延迟消息
【发布时间】:2023-04-03 08:29:01
【问题描述】:

如果 Azure 服务总线消息的处理依赖于另一个资源,例如API 或数据库服务,而该资源不可用,不调用CompleteMessageAsync() 不是一个选项,因为消息会立即再次接收,直到达到 Max Delivery Count,然后放入 DLQ。如果某个 API 因维护而停机,我们希望在重试之前稍等片刻。

this question 的答案之一具有延迟和接收延迟消息的一般步骤。这比 Microsoft 的文档好一点,但不足以让我理解 API 的意图,以及如何在基本上整天位于 ServiceBusProcessor.StartProcessingAsync 中的托管服务中实现它。

这是我的服务的基本结构:

public class ServiceBusWatcher : IHostedService, IDisposable
{
    public Task StartAsync(CancellationToken stoppingToken)
    {
        ReceiveMessagesAsync();
        return Task.CompletedTask;
    }

    private async void ReceiveMessagesAsync()
    {
        ServiceBusClient client = new ServiceBusClient(connectionString);
        processor = client.CreateProcessor(queueName, new ServiceBusProcessorOptions());
        processor.ProcessMessageAsync += MessageHandler;
        await processor.StartProcessingAsync();
    }

    async Task MessageHandler(ProcessMessageEventArgs args)
    {
         // a dependency is not available that allows me to process a message. so:
         await args.DeferMessageAsync(args.Message);       

一旦消息被延迟,我的理解是处理器将不再处理它(或者会吗?)。相反,我必须使用 ReceiveDeferredMessageAsync() 来接收它,以及最初收到的消息的序列号。

就我而言,在重试之前等待几分钟或几小时是有意义的。 这可以通过使用计时器和显式调用ReceiveDeferredMessageAsync() 的单独服务来完成,而不是使用ServiceBusProcessor。我还假设延迟的消息序列号必须保存在非易失性存储中,以免丢失。

这听起来像是一种可行的方法吗?我不喜欢记住它的序列号,以便以后可以收到消息。它与使用消息队列带来的一切背道而驰。

或者,我可以使用序列号发布一条新的“内部”消息,并使用ScheduledEnqueueTimeUtc 属性来延迟接收它,而不是推迟。收到此消息后,我可以使用该序列号调用ReceiveDeferredMessageAsync() 以获取原始消息。这表面上看起来很优雅,但如果依赖项的中断时间较长,消息可能会迅速增加。

另一个可以在没有其他服务的情况下工作的想法:我可以完成并重新发布消息的有效负载并将ScheduledEnqueueTimeUtc 设置为将来的某个时间,如the question I mentioned earlier 的另一个答案中所述。假设这行得通(微软的文档没有提到这个属性的用途),它看起来简单干净,我喜欢简单。

你是怎么解决这个问题的?有没有更好/首选的方法来平衡低复杂性和高鲁棒性而不需要大量代码?

【问题讨论】:

    标签: c# azure .net-core message-queue azureservicebus


    【解决方案1】:

    当您知道稍后要检索什么消息并且您的接收者将保存消息序列号以检索延迟消息时,延迟消息有效。如果接收者没有能力保存消息序列号,延迟消息是一个更好的选择。延迟消息意味着将原始消息数据复制到新安排的消息中并完成原始消息。这样,消费者既不必保留消息序列号,也不必启动特定消息的检索。

    【讨论】:

    • 谢谢,我得出了同样的结论。坚持序列号意味着我必须建立一个影子队列,违背了使用服务总线的目的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-07
    • 1970-01-01
    • 2018-05-14
    • 1970-01-01
    • 2011-03-27
    • 2018-10-11
    • 1970-01-01
    相关资源
    最近更新 更多