天蓝色服务总线 maxConcurrentCalls 完全被忽略

kos*_*kov 5 azure azureservicebus azure-servicebus-topics azure-functions

我的 host.json 中有这些,但每次我运行该函数时,它都会并行运行比 1 更多的线程(队列中有消息)

{
  "version": "2.0",
  "extensions": {
    "serviceBus": {
      "prefetchCount": 1,
      "messageHandlerOptions": {
        "maxConcurrentCalls": 1
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

我的职能

 [FunctionName(nameof(ResourceEventProcessorFunction))]
    public async Task Run([ServiceBusTrigger("%TopicName%", "%SubscriptionName%", Connection = "ServiceBusConnection", IsSessionsEnabled = true)]Message message, IMessageSession messageSession, ILogger log)
Run Code Online (Sandbox Code Playgroud)

Ale*_*AIT 6

利用会话

由于您使用的是会话,因此您可以对所有消息使用相同的 sessionId,并且无论您的 host.json 中的设置如何,它们都将由单个实例按顺序处理。

https://learn.microsoft.com/en-us/azure/service-bus-messaging/message-sessions

使用Singleton属性

如果您无法使用 sessionId 来达到您的目的,您应该尝试[Singleton]在您的函数中使用该属性。这将确保所有函数实例中只有一个实例将处理该请求。

我们已经在生产环境中的 WebJobs 中成功实现了此功能,并且它对于 Azure Functions 也应该同样有效。如果您有专用的应用程序服务计划,则使用此属性应该足够了。不建议将其用于消费计划

[Singleton] 确实适用于函数。Azure Function 主机将在 Azure 存储帐户中创建或等待锁定。锁是主机 ID,对于所有实例中应用程序的所有主机而言,该 ID 应该相同 - 因此所有实例共享此锁,并且一次只允许执行一次。

为了测试这一点,我使用 [Singleton] 在函数上一次放置 1000 条队列消息。该函数将唤醒、发出调用 ID、休眠,然后发出调用 ID。处理完所有 1000 个之后,我查看了日志,但从未发现调用 ID 重叠。全局一次只会发生一次调用。

https://github.com/Azure/azure-functions-host/issues/912#issuecomment-419608830

 [Singleton]
 [FunctionName(nameof(ResourceEventProcessorFunction))]
    public async Task Run([ServiceBusTrigger("%TopicName%", "%SubscriptionName%", Connection = "ServiceBusConnection", IsSessionsEnabled = true)]Message message, IMessageSession messageSession, ILogger log)
Run Code Online (Sandbox Code Playgroud)

在消费计划中

继续上面的引用:

话虽如此,我认为建议是:不建议将 [Singleton] 用于消费托管功能计划。如果您有专用的应用程序服务计划,那就没问题(因为无论如何您都要为实例付费)。如果您想在消费计划中强制实施类似 [Singleton] 的行为,您可能最好:

  1. 设置WEBSITE_MAX_DYNAMIC_APPLICATION_SCALE_OUT为 1,这样您就不会扩展到多个实例
  2. 将文件设置host.json为该触发器一次仅允许 1 个并发执行(例如,Azure 队列的批处理大小为 1)。

https://github.com/Azure/azure-functions-host/issues/912#issuecomment-419608830

{
  "version": "2.0",
  "extensions": {
    "serviceBus": {
      "prefetchCount": 1,
      "messageHandlerOptions": {
        "maxConcurrentCalls": 1
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)


kos*_*kov 0

所以问题是每条消息都有不同的 sessionId。在 azure 中禁用订阅上的 sessionId 解决了这个问题。

下面详细介绍了赏金:D azure 文档并没有确切说明如何限制线程数量,但我看起来有点像。

存在MessageRecievePump 并且 SessionRecievePump 一个使用MaxConcurrentCalls另一个MaxConcurrentSessions并且MaxConcurrentAcceptSessionCalls

如果您在订阅中包含会话(MaxConcurrentCalls 不起作用),请注意这一点,它仅在会话 ID 相同时才起作用。当会话不同时尝试使用 MaxConcurrentSessions 或 MaxConcurrentAcceptSessionCalls 但请注意没有关于此的文档....