天蓝色函数 V2 中的延迟消息:提供的锁无效
Defer message in azure function V2: The lock supplied is invalid
在我的 azure 函数中,有时我想推迟我的消息。但如果我这样做,我会得到一个例外:
[7/30/2020 5:59:02 PM] Message processing error (Action=Complete, ClientId=MessageReceiver1UserCreated/Subscriptions/MySubscription, EntityPath=UserCreated/Subscriptions/MySubscription, Endpoint=xxxxxxxxxxx.servicebus.windows.net)
[7/30/2020 5:59:02 PM] Microsoft.Azure.ServiceBus: The lock supplied is invalid. Either the lock expired, or the message has already been removed from the queue, or was received by a different receiver instance.
这是我的代码
[FunctionName("UserCreated")]
public static async Task Run([ServiceBusTrigger("UserCreated", "MySubscription", Connection = "ServiceBusConnectionString")]UserCreated userCreated, ILogger log, string lockToken, MessageReceiver messageReceiver)
{
//some logic.....
await messageReceiver.DeferAsync(lockToken);
}
老实说,我不知道我做错了什么。找到的代码示例 ID 以及此 post 对我没有帮助。
我了解消息是在函数完成后自动完成的。所以我尝试禁用自动完成功能,但也没有成功找到有效的解决方案。
使用包:
- Microsoft.Azure.WebJobs.Extensions.ServiceBus 4.1.0
- (参考文献)Microsoft.Azure.ServiceBus 4.1.1
如错误消息所述,消息可能在到达 Defer 指令之前失去锁定。尝试延长服务总线上的锁定超时。我认为这可能会解决问题。
Here 是关于锁在服务总线队列中的作用的一些解释,根据您描述的错误,您的锁在您能够推迟之前到期并且自动更新应该由功能,但不能保证,因此解决此问题的最佳方法是延长锁定的最大持续时间。
实现这一点的最简单方法是导航到 Azure 门户并找到您要更改的服务总线订阅,一旦您 select 您应该会看到类似以下屏幕的内容:
通过单击消息锁定持续时间下方的“更改”按钮,您将能够根据需要修改持续时间。
感谢大家的回答,不过 none 实际上解释了真正的原因。
TL;DR
如果您想自己完成、推迟、放弃或删除邮件,您必须在 host.json
文件中禁用 自动完成。
根本原因
锁无效的原因说明:
The lock supplied is invalid. Either the lock expired, or the message has already been removed from the queue, or was received by a different receiver instance.
在我的例子中,消息已经被“删除”,因为我使用了 messageReceiver.DeferAsync(lockToken);
所以这意味着在这条语句之后,函数自动完成消息(已经延迟)。
因此您必须禁用消息的自动完成。
解决方案
在 host.json
中禁用自动完成
"extensions": {
"serviceBus": {
"messageHandlerOptions": {
"autoComplete": false
}
}
}
小心
禁用自动完成时,您有责任对消息进行处理。您始终必须做出决定,否则消息将在锁定超时后再次可用。
在我的 azure 函数中,有时我想推迟我的消息。但如果我这样做,我会得到一个例外:
[7/30/2020 5:59:02 PM] Message processing error (Action=Complete, ClientId=MessageReceiver1UserCreated/Subscriptions/MySubscription, EntityPath=UserCreated/Subscriptions/MySubscription, Endpoint=xxxxxxxxxxx.servicebus.windows.net)
[7/30/2020 5:59:02 PM] Microsoft.Azure.ServiceBus: The lock supplied is invalid. Either the lock expired, or the message has already been removed from the queue, or was received by a different receiver instance.
这是我的代码
[FunctionName("UserCreated")]
public static async Task Run([ServiceBusTrigger("UserCreated", "MySubscription", Connection = "ServiceBusConnectionString")]UserCreated userCreated, ILogger log, string lockToken, MessageReceiver messageReceiver)
{
//some logic.....
await messageReceiver.DeferAsync(lockToken);
}
老实说,我不知道我做错了什么。找到的代码示例 ID 以及此
我了解消息是在函数完成后自动完成的。所以我尝试禁用自动完成功能,但也没有成功找到有效的解决方案。
使用包:
- Microsoft.Azure.WebJobs.Extensions.ServiceBus 4.1.0
- (参考文献)Microsoft.Azure.ServiceBus 4.1.1
如错误消息所述,消息可能在到达 Defer 指令之前失去锁定。尝试延长服务总线上的锁定超时。我认为这可能会解决问题。
Here 是关于锁在服务总线队列中的作用的一些解释,根据您描述的错误,您的锁在您能够推迟之前到期并且自动更新应该由功能,但不能保证,因此解决此问题的最佳方法是延长锁定的最大持续时间。
实现这一点的最简单方法是导航到 Azure 门户并找到您要更改的服务总线订阅,一旦您 select 您应该会看到类似以下屏幕的内容:
通过单击消息锁定持续时间下方的“更改”按钮,您将能够根据需要修改持续时间。
感谢大家的回答,不过 none 实际上解释了真正的原因。
TL;DR
如果您想自己完成、推迟、放弃或删除邮件,您必须在 host.json
文件中禁用 自动完成。
根本原因
锁无效的原因说明:
The lock supplied is invalid. Either the lock expired, or the message has already been removed from the queue, or was received by a different receiver instance.
在我的例子中,消息已经被“删除”,因为我使用了 messageReceiver.DeferAsync(lockToken);
所以这意味着在这条语句之后,函数自动完成消息(已经延迟)。
因此您必须禁用消息的自动完成。
解决方案
在 host.json
"extensions": {
"serviceBus": {
"messageHandlerOptions": {
"autoComplete": false
}
}
}
小心
禁用自动完成时,您有责任对消息进行处理。您始终必须做出决定,否则消息将在锁定超时后再次可用。