在 Azure Function 中按顺序处理服务总线消息(无并发调用)

Ren*_*eno 2 c# concurrency azure azure-servicebus-queues azure-functions

我需要通过“Azure 函数”读取和处理来自 Azure 服务总线队列的消息。消息应该以正确的顺序处理,因此我需要避免并发调用。

我为此使用 Azure Function 服务总线触发器(它是队列的唯一订阅者)。根据文档,我将“servicebus/maxConcurrentCalls”(在 host.json 中)设置配置为 1。在此之上,我用“Singleton”属性装饰了该函数。除此之外,不同线程似乎以随机顺序处理消息。我在这里想念什么?或者我误解了什么?

我使用的文档: https ://github.com/Azure/azure-webjobs-sdk/wiki/Singleton

主机.json:

{
  "serviceBus": {
    "maxConcurrentCalls": 1
  }
}
Run Code Online (Sandbox Code Playgroud)

蔚蓝功能:

using System;
using System.Threading.Tasks;
using Microsoft.ServiceBus.Messaging;

[Singleton]
public static void Run(BrokeredMessage myQueueItem, TraceWriter log)
{
    Stream stream = myQueueItem.GetBody<Stream>();
    StreamReader reader = new StreamReader(stream);
    string messageContentStr = reader.ReadToEnd();

    log.Info($"New TEST message: {messageContentStr} on thread {System.Threading.Thread.CurrentThread.ManagedThreadId}");   

    System.Threading.Thread.Sleep(2000);     
}
Run Code Online (Sandbox Code Playgroud)

这是日志记录的摘录。正如您所看到的,有不同的线程。并且,例如,“消息19”出现在“消息10”之前。是的,我确信我将消息按正确的顺序放入队列中。

....
2018-05-09T09:09:33.686 [Info] New TEST message: Message 19 on thread 33
2018-05-09T09:09:35.702 [Info] Function completed (Success, Id=007eccd0-b5db-466a-91c1-4f53ec5a7b3a, Duration=2013ms)
2018-05-09T09:09:36.390 [Info] Function started (Id=b7160487-d10d-47a6-bab3-78da68a93498)
2018-05-09T09:09:36.420 [Info] New TEST message: Message 10 on thread 39
...
Run Code Online (Sandbox Code Playgroud)

Rob*_*gan 5

查看并确保您的服务总线队列未分区。如果是分区的,则有多个消息代理为请求提供服务,并且无法保证消息传递的顺序。您可以在这里阅读更多相关信息:https://learn.microsoft.com/en-us/azure/service-bus-messaging/service-bus-partitioning#not-using-a-partition-key

具体来说:

如果没有分区键,服务总线会以循环方式将消息分发到分区队列或主题的所有片段。如果所选片段不可用,服务总线会将消息分配给不同的片段。这样,尽管消息存储暂时不可用,发送操作仍会成功。但是,您将无法实现分区键提供的保证排序。

  • 为了完整性。经过一些测试后,我可以说: 1/ 在“host.json”中将“servicebus/maxConcurrentCalls”设置为 1 确实使该函数一个接一个地同步处理它们。否则,一条消息仍然可以在前一条消息之前完成。 2/ [Singleton] 属性对这些服务总线触发功能没有影响。 (2认同)