带有 Servicebus 的 Azure 函数如何不将消息标记为完整

Azure function with Servicebus how to not mark message as complete

我有一个 Azure 函数可以侦听 Azure 服务总线队列中的消息。当它收到消息时,它将它们标记为已完成并且它们不再在队列中。 有没有办法将它们标记为仅当一个漫长的过程完成时?或者如果失败则取消将它们标记为已完成?

我的函数调用了一个 Api,我希望在 Api 返回成功代码之前消息不会被标记为完成。

函数执行完成后,消息将被标记为完成。

中止消息的最简单方法是从您的函数中抛出异常,例如当您的 API 以错误状态代码响应时。在这种情况下,消息将被放回队列并重试函数(直到达到为此服务总线队列配置的最大重试次数)。

作为已接受答案的替代方法,如果您将函数的签名设置为接受 BrokeredMessage,那么您可以手动为消息添加死信。

[FunctionName("MyFunctionName")]
public async static Task Run([ServiceBusTrigger("myqueue", AccessRights.Manage)]BrokeredMessage brokeredMessage, TraceWriter log) {

    // This will immediately deadletter the message.
    await brokeredMessage.DeadLetterAsync("My reason for deadlettering", "Some description that further explains...");

    return;

}

When it receives the messages it marks them as complete and they are no longer in the queue.

默认情况下,Functions 运行时实际上不会将消息标记为完成 until your function returns successfully。如已接受的答案中所述,抛出异常(在您的情况下,如果 API 被调用 returns 且响应不佳)将放弃该消息并阻止其被标记为完成。

为了更好地控制消息何时完成、放弃等,您可以将消息作为 BrokeredMessage type as mentioned previously. This class directly supports the methods you'd need to control what happens to your message. Note, the service bus trigger documentation mentions that BrokeredMessage should be used for Azure Functions version 1.*. If you're using version 2.*, you should consume your message as a Message 类型使用。

使用 Message 的一个 pain-point 是,与 BrokeredMessage 不同,它没有直接让您控制消息何时完成等方法。要实现这一点,我们可以将 MessageReceiver 参数绑定到我们的函数。

为了展示它是如何工作的,这里有一个 dead-lettering 使用 MessageMessageReceiver 的例子:

[FunctionName("SOExampleFunction"]
public static async Task ProcessMessage(
    [ServiceBusTrigger("myqueue")] Message message,
    MessageReceiver messageReceiver)
{
    . . .

    await messageReceiver.DeadLetterAsync(message.SystemProperties.LockToken);

    . . .
}

使用此方法时,请确保您在 host.json 中将 "autoComplete" 服务总线设置设置为 false。例如:

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