azure servicebus maxConcurrentCalls 完全被忽略
azure servicebus maxConcurrentCalls totally ignored
我的 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]
does work on functions. The Azure Function host will create or wait for a lock in the Azure Storage account. The lock is the host ID which should be the same for all hosts of an app across all instances - so all instances share this lock and will only allow one execution to occur at a time.
To test this I put 1000 queue messages at once on a function with [Singleton]. The function would wake up, emit the invocation ID, sleep, and then emit the invocation ID. After processing all 1000 I looked at logs and never saw invocation IDs overlap. Only one invocation would happen globally at a time.
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)
在消费计划中
继续上面的引用:
With that said I think the recommendation is: [Singleton] isn't recommended for consumption hosted function plans. If you have a dedicated app service plan it's fine (as you are paying for the instance anyway). If you want to enforce [Singleton] like behavior in a consumption plan you are likely best to:
- Set
WEBSITE_MAX_DYNAMIC_APPLICATION_SCALE_OUT
to 1 so you never scale to more than one instance
- Set the
host.json
file to only allow 1 concurrent execution at a time for that trigger (for instance a batch size of 1 for Azure Queues).
https://github.com/Azure/azure-functions-host/issues/912#issuecomment-419608830
{
"version": "2.0",
"extensions": {
"serviceBus": {
"prefetchCount": 1,
"messageHandlerOptions": {
"maxConcurrentCalls": 1
}
}
}
}
所以问题是每条消息都有不同的 sessionId。
在 azure 中禁用订阅的 sessionId 解决了这个问题。
赏金详情如下:D
azure docs并没有具体说明如何限制线程数,但我看起来有点不对劲。
有MessageRecievePump
和
SessionRecievePump
一个使用 MaxConcurrentCalls
另一个使用 MaxConcurrentSessions
和 MaxConcurrentAcceptSessionCalls
如果您在订阅中包含会话(MaxConcurrentCalls 不起作用)请注意这一点,它仅在会话 ID 相同时才有效。
当会话不同时尝试使用 MaxConcurrentSessions 或 MaxConcurrentAcceptSessionCalls 但请注意没有关于此的文档....
我的 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]
does work on functions. The Azure Function host will create or wait for a lock in the Azure Storage account. The lock is the host ID which should be the same for all hosts of an app across all instances - so all instances share this lock and will only allow one execution to occur at a time.To test this I put 1000 queue messages at once on a function with [Singleton]. The function would wake up, emit the invocation ID, sleep, and then emit the invocation ID. After processing all 1000 I looked at logs and never saw invocation IDs overlap. Only one invocation would happen globally at a time.
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)
在消费计划中
继续上面的引用:
With that said I think the recommendation is: [Singleton] isn't recommended for consumption hosted function plans. If you have a dedicated app service plan it's fine (as you are paying for the instance anyway). If you want to enforce [Singleton] like behavior in a consumption plan you are likely best to:
- Set
WEBSITE_MAX_DYNAMIC_APPLICATION_SCALE_OUT
to 1 so you never scale to more than one instance- Set the
host.json
file to only allow 1 concurrent execution at a time for that trigger (for instance a batch size of 1 for Azure Queues).
https://github.com/Azure/azure-functions-host/issues/912#issuecomment-419608830
{
"version": "2.0",
"extensions": {
"serviceBus": {
"prefetchCount": 1,
"messageHandlerOptions": {
"maxConcurrentCalls": 1
}
}
}
}
所以问题是每条消息都有不同的 sessionId。 在 azure 中禁用订阅的 sessionId 解决了这个问题。
赏金详情如下:D azure docs并没有具体说明如何限制线程数,但我看起来有点不对劲。
有MessageRecievePump
和
SessionRecievePump
一个使用 MaxConcurrentCalls
另一个使用 MaxConcurrentSessions
和 MaxConcurrentAcceptSessionCalls
如果您在订阅中包含会话(MaxConcurrentCalls 不起作用)请注意这一点,它仅在会话 ID 相同时才有效。 当会话不同时尝试使用 MaxConcurrentSessions 或 MaxConcurrentAcceptSessionCalls 但请注意没有关于此的文档....