【问题标题】:Processing Service Bus messages in order (without concurrent calls) in an Azure Function在 Azure 函数中按顺序处理服务总线消息(无并发调用)
【发布时间】:2018-10-19 08:42:31
【问题描述】:

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

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

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

host.json:

{
  "serviceBus": {
    "maxConcurrentCalls": 1
  }
}

Azure 函数:

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);     
}

这里是日志的摘录。如您所见,有不同的线程。 例如,“消息 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
...

【问题讨论】:

  • 您是否尝试将队列配置为Enforce Message Ordering?我使用这个工具来配置服务总线:Service Bus Explorer
  • “强制消息排序”仅适用于基于会话的消息传递,这在我的情况下不是一个选项。事实上,我并不太担心订单,而是更担心并发调用。感谢分享这个工具,顺便说一句。
  • 您能否检查一下您是否有一个或多个实例在运行这些并发请求?接受 ExecutionContext 并记录实例 ID。
  • 根据这个线程,单例属性不起作用:github.com/Azure/azure-functions-host/issues/912。似乎唯一的选择是使用专门的应用服务计划,不知道您是否可以选择?
  • 您的服务总线队列是否已分区?如果是分区的,你将无法保证排序。

标签: c# azure concurrency azure-functions azure-servicebus-queues


【解决方案1】:

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

具体来说:

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

【讨论】:

  • 为了完整起见。经过一些测试后,我可以说: 1/ 在“host.json”中将“servicebus/maxConcurrentCalls”设置为 1 确实使该函数一个接一个地同步处理它们。否则一条消息仍然可以在前一条之前完成 2/ [Singleton] 属性对这些服务总线触发功能没有影响。
  • 无限制功能为1并发,只能Message Sessions下单发货。在标准层上使用非分区队列有一个显着的缺点 - 可用性受到影响。使用消息会话,队列可以分区或不分区,这无关紧要。
猜你喜欢
  • 2013-05-22
  • 2020-07-20
  • 2021-09-22
  • 2021-03-10
  • 2017-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多