Azure功能服务总线触发多次运行

时间:2020-07-06 09:17:22

标签: azure azure-servicebus-topics

我在Visual Studio解决方案中添加了一个项目,该项目是服务总线主题触发功能。我正在使用默认代码运行应用程序,但遇到了问题。每当我将消息添加到服务总线主题时,我的触发器对每条消息执行5-6次,最后它会出现以下错误。

错误

提供的锁无效。锁已过期,或者消息已从队列中删除。

我的代码:

[FunctionName("TopicFunction1")]
    public static void Run(
        [ServiceBusTrigger("myservicebustopicname", "subscriptionname", Connection = "ServiceBus_NS_ConnectionString")]string message,
        Int32 deliveryCount,
        ILogger log)
    {
        log.LogInformation($"ServiceBus topic trigger function processed message: {message}");
    }

交货数量达到5-6。

我检查了与该问题有关的多个问题,它们没有帮助。下面是一个示例。 Azure Function App Azure Service Bus trigger triggers twice

请对此提供帮助。

2 个答案:

答案 0 :(得分:0)

一些要检查的东西。 All references are to the documentation

每次都确保它是同一封邮件,并且通过注销邮件ID不会收到多封邮件。

[FunctionName("ServiceBusQueueTriggerCSharp")]                    
public static void Run(
    [ServiceBusTrigger("myqueue", Connection = "ServiceBusConnection")] 
    string myQueueItem,
    Int32 deliveryCount,
    DateTime enqueuedTimeUtc,
    string messageId,
    ILogger log)
{
    log.LogInformation($"C# ServiceBus queue trigger function processed message: {myQueueItem}");
    log.LogInformation($"EnqueuedTimeUtc={enqueuedTimeUtc}");
    log.LogInformation($"DeliveryCount={deliveryCount}");
    log.LogInformation($"MessageId={messageId}");
}

如果您的函数引发任何异常,则消息将被重试,但事实并非如此。

最后,最有可能的是,如果您有两个功能应用程序或部署,并且它们被指向相同的队列,那么它们可能会相互竞争,下面复制消息的处理方式。您可能正在获得比赛条件。确保仅运行一个实例,并且队列中没有其他代码竞争。

PeekLock行为。Functions运行时会在PeekLock模式下收到一条消息。如果该函数调用消息完成 成功完成,或者在函数失败时调用Abandon。如果 函数的运行时间超过了PeekLock超时时间,该锁定为 只要该功能正在运行,它就会自动更新。

maxAutoRenewDuration可在host.json中配置,该映射到 OnMessageOptions.MaxAutoRenewDuration。允许的最大数量 根据服务总线文档,设置为5分钟, 而您可以将功能时间限制从默认值 5分钟到10分钟。对于服务总线功能,您不需要 这样做是因为您超出了服务总线的续订限制。

答案 1 :(得分:0)

如果您的 "autoComplete": false 文件中有 host.json,则消息将被处理,但不会从主题订阅中自动消失。就像在这个 host.json 文件中一样:

{
  "version": "2.0",
  "extensions": {
    "serviceBus": {
      "messageHandlerOptions": {
        "autoComplete": false
      }
    }
  }
}

删除 autoComplete 或将其设置为 true 应该会使该函数从主题订阅中删除成功处理的消息。

如果你需要更多的控制并且不能使用自动完成功能,那么你可以通过添加一个MessageReceiver参数来显式地完成消息,并像这样为CompleteAsync对象调用Message :

[FunctionName("TopicFunction1")]
public static async Task Run(
    [ServiceBusTrigger("myservicebustopicname", "subscriptionname", Connection = "ServiceBus_NS_ConnectionString")]Message message,
    MessageReceiver messageReceiver,
    ILogger log)
{
    log.LogInformation($"ServiceBus topic trigger function processed message: {message}");
    await messageReceiver.CompleteAsync(message.GetLockToken());
}