完全忽略了azure servicebus maxConcurrentCalls 利用会话使用Singleton属性在消费计划中

问题描述

host.json中包含这些字符,但是每次运行该函数时,它并行运行的线程数要多于1(因为队列中有消息)

{
  "version": "2.0","extensions": {
    "serviceBus": {
      "prefetchCount": 1,"messageHandlerOptions": {
        "maxConcurrentCalls": 1
      }
    }
  }
}

我的功能

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

解决方法

也许您可以将WEBSITE_MAX_DYNAMIC_APPLICATION_SCALE_OUT设置为1,以使该函数一次仅运行一个实例。

如果在本地开发,则可以在local.settings.json中进行设置,如果在Azure portal中进行开发,则可以在Configuration -> Application settings中进行设置。

注意:

1。。如果将WEBSITE_MAX_DYNAMIC_APPLICATION_SCALE_OUT设置为1,则您的函数将无法扩展,只能在一个实例中运行。

2。。除了设置WEBSITE_MAX_DYNAMIC_APPLICATION_SCALE_OUT,您还需要将maxConcurrentCalls设置为1

3。。此设置处于预览状态。 An app property for function max scale out已添加,是限制横向扩展的推荐方法。

有关更多详细信息,您可以参考此official document

,

利用会话

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

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

使用Singleton属性

如果不能出于目的使用sessionId,则应尝试在函数上使用[Singleton]属性。这样可以确保所有功能实例中只有一个实例可以处理请求。

我们已经在生产中的WebJobs上成功完成了这项工作,并且它对于Azure Functions应该也是如此。如果您有专门的应用服务计划,则使用此属性就足够了。 不建议将其用于消费计划

[Singleton] 可以使用功能。 Azure功能主机将创建或等待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)

在消费计划中

继续以上引用:

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

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

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

{
  "version": "2.0","extensions": {
    "serviceBus": {
      "prefetchCount": 1,"messageHandlerOptions": {
        "maxConcurrentCalls": 1
      }
    }
  }
}
,

所以问题是每条消息都有一个不同的net sessionId。 在天蓝色的订阅中禁用sessionId可以解决此问题。

在下面的赏金详情:D azure docs并未完全指定如何限制线程数,但我看起来有点像北斗七星。

MessageRecievePumpSessionRecievePump 一个使用MaxConcurrentCalls,另一个使用MaxConcurrentSessionsMaxConcurrentAcceptSessionCalls

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