Azure Service Bus触发函数抛异常后,消息何时会重新入队?
问题背景
我有一个运行在隔离模式下的Azure函数应用,通过Service Bus触发器从Service Bus主题/订阅消费消息,代码如下:
[Function("ConsumeMessage")] public async Task ConsumeMessage( [ServiceBusTrigger("%MyTopic%","%MySubscription%",Connection = "ServiceBusConnection")] string servicebusMessage) { throw new Exception(); }
实际运行中发现,即使函数抛出异常,消息仍会从订阅中被移除,且未进入死信队列。想咨询:在什么情况下消息会被出队后再次发送?
解答
以下几种场景下,Service Bus消息会被出队后重新投递:
未捕获异常且投递次数未达上限:
默认配置下,当函数抛出未处理异常时,Service Bus触发器会自动放弃消息(调用AbandonAsync)。此时消息会重新回到订阅的活跃队列,等待下一次投递,同时消息的DeliveryCount(投递次数)递增。只有当DeliveryCount达到订阅设置的maxDeliveryCount时,消息才会被移入死信队列。主动调用
AbandonAsync方法:
如果在函数代码中手动获取消息的客户端实例,主动调用AbandonAsync方法,无论函数执行是否成功,消息都会被放弃并重新回到队列等待投递。消息锁过期:
消息被取出时会获得一个排他锁(默认有效期30秒),如果函数执行时间超过锁的有效期,且未成功续期,锁会自动过期。此时Service Bus会将消息标记为未处理,重新放回队列,同时递增DeliveryCount。可通过触发器的maxAutoRenewDuration配置延长锁的自动续期时长。手动完成消息失败:
如果代码中手动调用CompleteAsync完成消息,但执行失败(如网络中断、权限问题),Service Bus可能会将消息重新标记为可投递状态,再次发送给函数。
针对你遇到的异常后消息直接被移除且未进入死信的情况,可能的原因包括:触发器配置了AutoComplete = true但异常被上层逻辑捕获、订阅的maxDeliveryCount设为1但死信队列未正确启用,或是函数的异常处理逻辑错误返回了成功信号,导致触发器误判执行完成并自动完成了消息。
内容的提问来源于stack exchange,提问作者A B

