问题描述
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]的行为,则最好执行以下操作:
- 将
WEBSITE_MAX_DYNAMIC_APPLICATION_SCALE_OUT
设置为1,这样就永远不会扩展到一个以上实例- 将
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并未完全指定如何限制线程数,但我看起来有点像北斗七星。
有MessageRecievePump
和
SessionRecievePump
一个使用MaxConcurrentCalls
,另一个使用MaxConcurrentSessions
和MaxConcurrentAcceptSessionCalls
请注意,如果您在订阅中包含会话(MaxConcurrentCalls不起作用),则仅当会话ID相同时,该选项才起作用。 当会话不同时,请尝试使用MaxConcurrentSessions或MaxConcurrentAcceptSessionCalls,但要注意没有关于此的文档。