c# - "MaxAutoRenewDuration"在azure service bus中的作用是什么?

标签 c# azure .net-core azureservicebus

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

我得到了一个异常(exception):

The lock supplied is invalid. Either the lock expired, or the message has already been removed from the queue.



通过这些问题的帮助:

1 , 2 , 3 ,

我可以通过将 Exception 设置为 AutoComplete 并将 Azure 的队列锁定持续时间增加到最大值(从 30 秒到 5 分钟)来避免 false
_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. 。如果在我的情况下,我只有一个应用程序接收器从这个队列中排队,那么它是否不需要,因为我不需要锁定来自另一个应用程序的消息来捕获它?为什么这个值应该大于最长消息锁定持续时间?
  • 最佳答案

    您需要考虑一些事项。

  • 锁定持续时间
  • 从代理获取消息后的总时间

  • 锁定持续时间很简单 - 单个竞争消费者可以租用多长时间,而无需将该消息租给任何其他竞争消费者。

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

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

    为了帮助可视化它,请考虑客户端有一个内存队列,当您在处理程序中逐个执行消息的串行处理时,可以在其中存储消息。当消息从代理到达内存队列时,租用就开始了。如果内存队列中的总时间加上处理时间超过锁定持续时间,则租约丢失。您的选择是:
  • 通过设置 MaxConcurrentCalls > 1
  • 启用并发处理
  • 增加MaxLockDuration
  • 减少消息预取(如果使用)
  • 配置 MaxAutoRenewDuration 更新锁并克服 MaxLockDuration 约束

  • 注意#4 - 这不是一个有保证的操作。因此,对代理的调用可能会失败并且消息锁不会被扩展。我建议将您的解决方案设计为在锁定持续时间限制内工作。或者,保留消息信息,以便您的处理不必受到消息传递的限制。

    关于c# - "MaxAutoRenewDuration"在azure service bus中的作用是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60377595/

    相关文章:

    c# - 如何计算文本框中输入的字符数?

    c# - SignalR自主机连接重置

    c# - 向温莎城堡注册 AutoMapper 5.1.1

    带有 SAS token 的 Azure Blob 存储

    .net-core - 在 Visual Studio 代码中创建类库

    linux - 无法在某些目录下运行 dotnet?

    c# - 在 C# 中每天运行一次

    azure - 如何在使用容器应用服务启动的容器上远程运行命令?

    security - 从企业到 windows azure 的 VPN 连接

    c# - 在Dockerfile中公开具有不同名称的环境变量