“MaxAutoRenewDuration”在 Azure 服务总线中的作用是啥?

Posted

技术标签:

【中文标题】“MaxAutoRenewDuration”在 Azure 服务总线中的作用是啥?【英文标题】:What is the role of "MaxAutoRenewDuration" in azure service bus?“MaxAutoRenewDuration”在 Azure 服务总线中的作用是什么? 【发布时间】:2020-06-08 04:22:22 【问题描述】:

我正在使用Microsoft.Azure.ServiceBus。 (doc)

我得到了一个例外:

提供的锁无效。要么锁过期,要么消息 已从队列中移除。

借助这些问题:

1,2,3,

我可以通过将 AutoComplete 设置为 false 并将 Azure 的队列锁定持续时间增加到其最大值(从 30 秒到 5 分钟)来避免 Exception

_queueClient.RegisterMessageHandler(ProcessMessagesAsync, new 
                         MessageHandlerOptions(ExceptionReceivedHandler)
                         
                             MaxConcurrentCalls = 1,
                             MaxAutoRenewDuration = TimeSpan.FromSeconds(10),
                             AutoComplete = false
                         
);

private async Task ProcessMessagesAsync(Message message, CancellationToken token)

    await ProccesMessage(message);


private async Task ProccesMessage(Message message)

    //The complete should be closed before long-timed process
    await _queueClient.CompleteAsync(message.SystemProperties.LockToken);
    await DoFoo(message.Body); //some long running process

我的问题是:

    此answer 建议引发异常,因为锁定在长时间进程之前已过期,但在我的情况下,我将消息标记为立即完成(在长期进程之前),所以我不是确定为什么从 azure 更改锁定持续时间会有所不同?当我将它改回 30 秒时,我可以再次看到异常。
    不确定它是否与问题有关,但MaxAutoRenewDuration 的目的是什么,官方文档是The maximum duration during which locks are automatically renewed.。如果在我的情况下,我只有一个应用程序接收器从该队列排队,那么是否不需要它,因为我不需要锁定来自另一个应用程序的消息来捕获它?以及为什么这个值应该大于最长的消息锁定持续时间?

【问题讨论】:

【参考方案1】:

您需要考虑一些事项。

    锁定持续时间 自从代理获取消息以来的总时间

锁定持续时间很简单 - 单个竞争消费者可以在不将该消息租给任何其他竞争消费者的情况下租用消息多长时间。

总时间有点复杂。您注册以接收消息的回调ProcessMessagesAsync 并不是唯一涉及的事情。在您提供的代码示例中,您将并发设置为 1。如果配置了预取(队列在每次请求一条或多条消息时获取多条消息),服务器上的锁定持续时间时钟开始计时所有这些消息。因此,如果您的处理稍微低于MaxLockDuration,但对于相同的示例,最后一个预取消息等待处理的时间过长,即使它在小于锁定持续时间的时间内完成,它也可能会失去锁定并且异常将尝试完成该消息时抛出。

这就是MaxAutoRenewDuration 进入游戏的地方。它所做的是与代理延长消息租约,为当前正在处理消息的竞争消费者“重新锁定”它。 MaxAutoRenewDuration 应设置为“可能需要租约的最长处理时间”。在您的示例中,它设置为 TimeSpan.FromSeconds(10),这是非常低的。它需要设置为至少比MaxLockDuration 长,并调整为ProccesMessage 需要运行的最长时间。考虑预取。

为了帮助将其可视化,请考虑客户端有一个内存队列,当您在处理程序中一一执行消息的串行处理时,可以在其中存储消息。租赁从消息从代理到达该内存队列的那一刻开始。如果内存队列加上处理的总时间超过锁定持续时间,则租约丢失。您的选择是:

    通过设置MaxConcurrentCalls > 1来启用并发处理 增加MaxLockDuration 减少消息预取(如果使用的话) 配置MaxAutoRenewDuration 以更新锁定并克服MaxLockDuration 约束

注意#4 - 这不是保证操作。因此,对代理的调用可能会失败并且消息锁定不会被延长。我建议设计您的解决方案以在锁定持续时间限制内工作。或者,保留消息信息,这样您的处理就不必受到​​消息的限制。

【讨论】:

嘿@sean 很好的答案,关于调整到 ProccesMessage 需要运行的最长时间,为什么它与我的情况相关?我之前将其标记为完成。 谢谢。在您的情况下,MaxAutoRenewDuration = TimeSpan.FromSeconds(10), 应该被省略并且根本不配置。这样 SDK 就不会尝试延长锁。此外,当MaxAutoRenewDuration 设置为比MaxLockDuraitons 更短的时间段时,我看到了副作用。 @SeanFeldman 关于***.com/questions/63171548/…的任何想法 添加了答案。您只需要两条消息是关键。它不能是并发的,而是批处理的。 It needs to be set to be at least longer than the MaxLockDuration 这意味着您希望锁在运行时过期,这似乎与文档指定其用途的方式相反

以上是关于“MaxAutoRenewDuration”在 Azure 服务总线中的作用是啥?的主要内容,如果未能解决你的问题,请参考以下文章

为啥“a+++++b”不能在gcc中编译,而“a+++b”、“a++ + ++b”、“a+++ ++b”可以? [复制]

在装配中找到最大值和最小值

在 a = +a || 0、'='后面的'+'有啥作用? [复制]

a在英语单词中有几种发音?

如何在 React Native 中添加按钮网格样式?

在 Python 中是 a, b, = 0, 0 在语义上等同于 a = b = 0