Azure函数多次运行同一服务总线队列消息

时间:2017-07-11 22:36:48

标签: c# azure singleton azureservicebus azure-functions

我有一个Azure功能(基于新的C#功能而不是旧的.csx功能),只要有消息进入Azure服务总线队列,就会触发该功能。触发该功能后,它开始处理服务总线消息。它解码消息,读取一堆数据库,更新一堆其他数据等......有时可能需要30分钟以上。

因为,这不是一个时间敏感的过程,30分钟甚至60分钟不是问题。问题是,与此同时,Azure功能似乎再次启动并一次又一次地接收相同的消息并重新处理它。这是一个问题,并导致我们的业务逻辑出现问题。

所以,问题是,我们可以强制Azure功能以单件模式运行吗?或者,如果不可能,我们如何更改轮询间隔?

4 个答案:

答案 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]))