在 Azure 服务总线上自动正确更新锁
Autotmatically renewing locks correctly on Azure Service Bus
所以我正在尝试了解服务总线时序...尤其是锁的工作原理。可以选择手动调用 CompleteAsync,这正是我们正在做的。也可能是处理需要一些时间。在这些情况下,我们要确保我们不会得到不必要的 MessageLockLostException
.
似乎有几个数字与:
- 锁定时间(在 bus 上的 azure portal 中找到,目前设置为 1 分钟,这是默认值)
- AutoRenewTimeout(属性 onMessageOptions,当前设置为 1 分钟)
- 自动完成(属性 onMessageOptions,当前设置为 false)
假设处理 运行 大约 2 分钟,然后要么成功要么崩溃(现在哪种情况都无所谓)。假设这是正常情况,那么这意味着处理每条消息大约需要 2 分钟。
还有,确实是队列,不是话题。我们只有一个消费者异步处理 MaxConcurrentCalls
设置为 100 的消息。我们使用 OnMessageAsync
和 ReceiveMode.PeekLock
。
作为单个消费者,我现在应该如何设置才能稳健地处理所有消息?
我认为将锁定持续时间保留为 1 分钟会很好,因为这是默认设置,为了安全起见,将我的 AutoRenewTimeout 设置为 5 分钟,因为据我所知,这个值应该是它花费的最长时间处理消息 ()。性能对于这个系统来说并不重要,所以我认为将消息锁定一些不必要的 1、2 或 3 分钟并不是坏事,只要我们没有得到 LockedException,因为这些没有实际价值。
This thread and this thread 给出了如何手动更新锁的很好的例子,但我认为有一种方法可以自动更新锁。
What should my settings now be as a single consumer to robustly process all messages?
除了 LockDuration
、MaxConcurrentCalls
、AutoRenewTimeout
和 AutoComplete
之外,您可能还需要查看 Azure 服务总线客户端的一些配置。例如,不创建 MaxConcurrentCalls
设置为 100 的单个客户端,而是创建几个具有分布在客户端之间的总并发级别的客户端。请注意,您需要使用 不同的 MessagingFactory
实例来创建这些客户端,以确保您有多个 "pipe" 来接收消息。即便如此,横向扩展并拥有相互竞争的消费者比让一个消费者处理所有负载要好得多。
现在回到设置。如果您的正常处理时间是 2 分钟,最好将实体上的 MaxLockDuration
设置为这个时间而不是 1 分钟。这将删除对代理的不必要的锁定扩展调用并消除 MessageLockLostException
.
此外,请记住 AutoRenewTimeout
是基于客户端的操作,而不是代理,因此无法保证。你会 运行 遇到即使 AutoRenewTimeout
时间还没有过去,锁也会丢失的情况。
AutoRenewTimeout
应始终设置为比 MaxLockDuration
长,因为让它们相等会适得其反。让它比 MaxLockDuration
稍微大一点,因为这是客户端的 "insurance",当处理时间超过 MaxLockDuration
时,消息锁不会丢失。从本质上讲,让这两个相等是禁用此回退。
所以我正在尝试了解服务总线时序...尤其是锁的工作原理。可以选择手动调用 CompleteAsync,这正是我们正在做的。也可能是处理需要一些时间。在这些情况下,我们要确保我们不会得到不必要的 MessageLockLostException
.
似乎有几个数字与:
- 锁定时间(在 bus 上的 azure portal 中找到,目前设置为 1 分钟,这是默认值)
- AutoRenewTimeout(属性 onMessageOptions,当前设置为 1 分钟)
- 自动完成(属性 onMessageOptions,当前设置为 false)
假设处理 运行 大约 2 分钟,然后要么成功要么崩溃(现在哪种情况都无所谓)。假设这是正常情况,那么这意味着处理每条消息大约需要 2 分钟。
还有,确实是队列,不是话题。我们只有一个消费者异步处理 MaxConcurrentCalls
设置为 100 的消息。我们使用 OnMessageAsync
和 ReceiveMode.PeekLock
。
作为单个消费者,我现在应该如何设置才能稳健地处理所有消息?
我认为将锁定持续时间保留为 1 分钟会很好,因为这是默认设置,为了安全起见,将我的 AutoRenewTimeout 设置为 5 分钟,因为据我所知,这个值应该是它花费的最长时间处理消息 (
This thread and this thread 给出了如何手动更新锁的很好的例子,但我认为有一种方法可以自动更新锁。
What should my settings now be as a single consumer to robustly process all messages?
除了 LockDuration
、MaxConcurrentCalls
、AutoRenewTimeout
和 AutoComplete
之外,您可能还需要查看 Azure 服务总线客户端的一些配置。例如,不创建 MaxConcurrentCalls
设置为 100 的单个客户端,而是创建几个具有分布在客户端之间的总并发级别的客户端。请注意,您需要使用 不同的 MessagingFactory
实例来创建这些客户端,以确保您有多个 "pipe" 来接收消息。即便如此,横向扩展并拥有相互竞争的消费者比让一个消费者处理所有负载要好得多。
现在回到设置。如果您的正常处理时间是 2 分钟,最好将实体上的 MaxLockDuration
设置为这个时间而不是 1 分钟。这将删除对代理的不必要的锁定扩展调用并消除 MessageLockLostException
.
此外,请记住 AutoRenewTimeout
是基于客户端的操作,而不是代理,因此无法保证。你会 运行 遇到即使 AutoRenewTimeout
时间还没有过去,锁也会丢失的情况。
AutoRenewTimeout
应始终设置为比 MaxLockDuration
长,因为让它们相等会适得其反。让它比 MaxLockDuration
稍微大一点,因为这是客户端的 "insurance",当处理时间超过 MaxLockDuration
时,消息锁不会丢失。从本质上讲,让这两个相等是禁用此回退。