我有一个Azure功能(基于新的C#功能而不是旧的.csx功能),只要有消息进入Azure服务总线队列,就会触发该功能。触发该功能后,它开始处理服务总线消息。它解码消息,读取一堆数据库,更新一堆其他数据等......有时可能需要30分钟以上。
因为,这不是一个时间敏感的过程,30分钟甚至60分钟不是问题。问题是,与此同时,Azure功能似乎再次启动并一次又一次地接收相同的消息并重新处理它。这是一个问题,并导致我们的业务逻辑出现问题。
所以,问题是,我们可以强制Azure功能以单件模式运行吗?或者,如果不可能,我们如何更改轮询间隔?
答案 0 :(得分:3)
问题与服务总线设置有关...
正在发生的事情是将消息添加到队列中,然后将消息提供给该函数并对该消息进行锁定,以便在您锁定消息时没有其他消费者可以看到/处理该消息
如果在该锁定期内您没有告诉服务总线您已经处理了该文件,或者为了扩展锁定,则会从消息中删除锁定,然后它将对其他服务可见,然后这些服务将处理该消息,这就是你所看到的。
幸运的是,Azure Functions可以自动为您更新锁定。在host.json
文件中有一个autoRenewTimeout
设置,指定您希望Azure功能在多长时间内保持更新锁定。
https://github.com/Azure/azure-webjobs-sdk-script/wiki/host.json
"serviceBus": {
// the maximum duration within which the message lock will be renewed automatically.
"autoRenewTimeout": "00:05:00"
},
答案 1 :(得分:2)
AutoRenewTimeout
没有建议的那么好。它有一个缺点,你需要注意。这是not a guaranteed operation。作为客户端启动的操作,可以,有时将失败,使您处于与现在相同的状态。
您可以采取的措施是审核您的设计。如果您有一个长时间运行的进程,那么您将处理该消息,并将处理切换到运行时间超过MaxLockDuration
的内容。你的功能花了这么长时间的事实表明你有一个漫长的过程。消息传递不是为此而设计的。
其中一个潜在的解决方案是获取消息,在存储表中注册处理意图。有另一个存储表触发功能启动可能需要X分钟的处理。将其标记为单身人士。通过这样做,您将并行处理消息,将“长时间运行处理请求”写入存储表,完成Service Bus消息传递,从而不会触发重新处理。通过长时间运行的处理,您可以决定如何处理故障情况。
希望有所帮助。
答案 2 :(得分:0)
因此,您的问题在于如何使Azure Function消息触发器一次处理一条消息,而一条消息只需要处理一次。
使用以下host.json
配置,我已经能够实现相同的功能。
{
"serviceBus": {
"maxConcurrentCalls": 1,
"autoRenewTimeout": "23:59:59",
"autoComplete": true
}
}
请注意,我将autoRenewTimeout
设置为24小时,这对于一个非常长时间的运行过程来说足够长。否则,您可以将其更改为适合您需要的持续时间。
许多人会争论将Azure函数用于长时间运行的操作是否合适。但这不是这里需要回答的问题。
答案 3 :(得分:0)
我也遇到相同的问题,我所做的是删除默认规则,并在订阅服务器上添加了自定义规则。
(OriginalTopic='name-of-topic' AND OriginalSubscription='name-of-subcription-sub') OR (NOT Exists([OriginalTopic]))