我在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 函数应用 Azure 服务总线触发器触发器两次
请帮忙。
需要检查的一些事项。所有引用均指向文档。
通过注销消息 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}");
}
如果您的函数抛出任何异常,消息将重试,但情况似乎并非如此。
最后,也是最有可能的是,如果你有两个函数应用或部署,并且它们指向同一个队列,则它们可能相互竞争,下面是消息的处理方式。您可能会遇到竞争条件。确保您只有一个实例正在运行,并且没有其他代码在队列中竞争。
速视锁定行为函数运行时在速览锁定模式下接收一条消息。如果函数对消息调用 Complete,则函数 成功完成,或者在函数失败时调用 Abandon 。如果 函数运行时间超过速览锁定超时,锁是 只要函数正在运行,就会自动续订。
maxAutoRenewDuration 可在 host.json 中配置,映射到 OnMessageOptions.MaxAutoRenewDuration。允许的最大值 根据服务总线文档,设置为 5 分钟, 而您可以将函数时间限制从默认值 5分钟到10分钟。对于不需要的服务总线函数 然后执行此操作,因为会超出服务总线续订限制。
如果您的host.json
文件中有"autoComplete": false
,则将处理消息,但不会自动从主题订阅中消失。就像这个host.json
文件一样:
{
"version": "2.0",
"extensions": {
"serviceBus": {
"messageHandlerOptions": {
"autoComplete": false
}
}
}
}
删除autoComplete
或将其设置为true
应该会使函数从主题订阅中删除成功处理的消息。
如果需要更多控制并且无法使用自动完成功能,则可以通过添加MessageReceiver
参数显式完成消息,并为Message
对象调用CompleteAsync
,如下所示:
[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());
}