我有一个 Azure WebJob 项目,正在我的开发计算机上本地运行。它正在监听 Azure 服务总线消息队列。没有像 Topics 这样的东西,只是最基本的消息队列。
它多次接收/处理同一条消息,在收到消息时立即启动两次,然后在处理消息时间歇性地启动。
问题:
- 为什么我会立即多次收到同一条消息?看起来是在应用 PeekLock 之前重新获取的?
- 为什么消息仍在处理中却被重新接收?我可以设置 PeekLock 持续时间,或者以某种方式锁定消息仅处理一次
- 如何确保队列中的每条消息仅处理一次?
- 我希望能够一次处理多条消息,只是不能多次处理同一条消息,因此将 MaxConcurrentCalls 设置为 1 似乎不是我的答案,还是我误解了该属性?
我使用的是异步函数、简单注入(inject)器和自定义 JobActivator,因此我的函数签名不是静态 void 方法,而是:
public async Task ProcessQueueMessage([ServiceBusTrigger("AnyQueue")] MediaEncoderQueueItem message, TextWriter log) {...}
在作业内部,它在 Blob 服务上移动一些文件,并从媒体服务调用(并等待)媒体编码器。因此,虽然网络作业本身没有进行大量处理,但它需要相当长的时间(对于某些文件来说需要 15 分钟)。
应用程序正在启动,当我向队列发布消息时,它会做出响应。然而,一旦收到消息,它就会多次接收消息:
Executing: 'Functions.ProcessQueueMessage' - Reason: 'New ServiceBus message detected on 'MyQueue'.'
Executing: 'Functions.ProcessQueueMessage' - Reason: 'New ServiceBus message detected on 'MyQueue'.'
此外,当任务正在运行时(并且我看到媒体服务功能的输出),它将从队列中获取另一个“副本”。
最终在任务完成后,它仍然间歇性地处理相同的消息。
最佳答案
我怀疑发生的事情如下:
DurationLock
最长可为 5 分钟。如果消息处理在 5 分钟内完成,消息将被标记为已完成并从代理中删除。否则,如果处理时间超过 5 分钟(我们失去了消息的锁定),消息将重新出现,并将再次被消耗。您可以通过查看 DeliveryCount
来验证这一点您的消息。
要解决此问题,您可以在消息锁定即将过期之前使用 BrokeredMessage.RenewLockAsync()
更新消息锁定。 .
关于azure - 如何防止Azure Web作业同时多次处理同一消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38742584/