【问题标题】:Azure function running multiple times for the same service bus queue message为同一服务总线队列消息多次运行的 Azure 函数
【发布时间】:2017-07-11 22:36:47
【问题描述】:

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

由于这不是一个时间敏感的过程,30 分钟甚至 60 分钟都不是问题。问题是与此同时,Azure Function 似乎又开始了,一次又一次地接收相同的消息并重新处理它。这是一个问题,会导致我们的业务逻辑出现问题。

那么,问题是,我们能否强制 Azure 函数以单例模式运行?或者如果这不可能,我们如何更改轮询间隔?

【问题讨论】:

  • 您的函数应用是在应用服务计划还是消费计划下创建的?在应用服务计划下,确保 AlwaysOn 已打开。在 Consumption Plan 下,Function App 会在 5 分钟后终止(可配置为延长至 10 分钟,请参阅github.com/Azure/azure-webjobs-sdk-script/wiki/host.json 处的“functionTimeout”值),这可以解释您所看到的行为。
  • 我有应用服务计划。我的功能没有终止。事实上,相反的情况正在发生。多个函数正在处理消息。

标签: c# azure singleton azureservicebus azure-functions


【解决方案1】:

问题与服务总线设置有关...

正在发生的事情是消息被添加到队列中,然后将消息提供给函数并在该消息上放置一个锁,以便在您锁定该消息时没有其他使用者可以看到/处理该消息.

如果在该锁定期内您没有告诉服务总线您已处理该文件或延长锁定,则该锁定将从消息中移除,并且它将对随后处理该消息的其他服务可见,这就是你所看到的。

幸运的是,Azure Functions 可以自动为您续订锁。在host.json 文件中有一个autoRenewTimeout 设置,它指定您希望Azure Functions 继续更新锁定多长时间。

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"
},

【讨论】:

    【解决方案2】:

    AutoRenewTimeout 没有建议的那么好。它有一个缺点,您需要注意。这是not a guaranteed operation。作为客户端发起的操作,它可能并且有时失败,使您处于与今天相同的状态。

    您可以做的就是检查您的设计。如果您有一个长时间运行的进程,那么您处理消息,并将处理移交给运行时间比MaxLockDuration 更长的东西。您的功能需要很长时间的事实表明您有一个长时间运行的过程。消息传递不是为此而设计的。

    一种可能的解决方案是获取消息,在存储表中注册处理意图。有另一个存储表触发功能来启动可能需要 X 分钟的处理。将其标记为单例。通过这样做,您将并行处理您的消息,将“长时间运行处理请求”写入存储表,完成服务总线消息传递,因此不会触发它们的重新处理。通过长时间运行的处理,您可以决定如何处理失败的情况。

    希望对您有所帮助。

    【讨论】:

    • 当您说“将其标记为单例”时,您指的是什么?以及如何将其标记为单例?
    • 其他存储表触发功能。我已经用 NServiceBus 和 Service Bus 实现了一些类似的过程。您可以在此处找到代码和图表:docs.particular.net/samples/azure/… 使用函数方法,您的长时间运行的函数(处理器)不必轮询,它会被触发。
    • 我建议使用github.com/Azure/azure-functions-durable-extension,它提供了您需要的长时间运行/编排功能
    • 马特,耐用的功能还没有成熟。
    【解决方案3】:

    所以您的问题是如何让 Azure Function Message 触发器一次处理一条消息,而一条消息只能处理一次。

    我已经能够使用以下host.json 配置实现相同的功能。

    {
      "serviceBus": {
        "maxConcurrentCalls": 1,
        "autoRenewTimeout": "23:59:59",
        "autoComplete": true
      }
    }
    

    请注意,我将autoRenewTimeout 设置为 24 小时,这对于真正长时间运行的进程来说已经足够了。否则,您可以将其更改为适合您需要的持续时间。

    许多人会争论将 Azure Function 用于长期运行的操作是否合适。但这不是这里需要回答的问题。

    【讨论】:

      【解决方案4】:

      我也遇到了同样的问题,我所做的是删除默认规则并在订阅者上添加自定义规则。

      (OriginalTopic='name-of-topic' AND OriginalSubscription='name-of-subcription-sub') OR (NOT Exists([OriginalTopic]))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-10-18
        • 1970-01-01
        • 2019-01-23
        • 1970-01-01
        • 1970-01-01
        • 2014-11-03
        • 2017-11-01
        • 1970-01-01
        相关资源
        最近更新 更多