有没有办法可以在Azure函数中延迟重试服务总线消息?

时间:2018-04-17 22:06:39

标签: c# azure-functions servicebus azure-servicebus-topics retry-logic

我有一个从订阅中提取消息的函数,并将它们转发到HTTP端点。如果端点不可用,则抛出异常。当发生这种情况时,我想延迟该特定消息的下一次尝试一段时间,例如15分钟。到目前为止,我找到了以下解决方案:

  • 抓住异常,睡觉,然后扔。这是一个糟糕的解决方案,因为我会在睡眠时收取CPU使用费,这会影响功能的吞吐量。
  • 捕获异常,克隆消息,设置ScheduledEnqueueTimeUtc属性并将其添加回队列。这是一种更好的方式,但它会重置交付计数,因此实际问题永远不会出现问题,当只有一个订阅者无法处理时,它会重新发送给所有订阅。
  • 捕获异常,并将消息放在存储队列中。这意味着维护存储队列以匹配每个订阅,并具有两个功能而不是一个。

我最理想的情况是捕获异常,并退出函数而不释放消息上的锁。这样,一旦锁定到期,将再次重试该消息。但是,似乎在成功完成后,函数会对消息调用Complete(),并在抛出异常后,函数会对消息调用Abandon()。有可能绕过这个,或者以其他方式实现延迟吗?

3 个答案:

答案 0 :(得分:1)

我将通过提供一个 LogicApp 在纯函数上更好地处理您提出的流程来解决您的情况。

在LogicApp中实现 wait / retry / dequeue next 模式非常容易,因为这种类型的流控制正是LogicApps的设计目标。

答案 1 :(得分:1)

虽然仍处于预览状态(不建议用于生产代码),但您可以使用Durable Functions。如果你想保持在代码中操纵对象的能力,这可能是你最好的选择!

(也是LogicApp解决方案的+1!)

答案 2 :(得分:0)

现在通过 retry policies 原生支持此功能,该功能已于 2020 年 11 月左右添加到 Azure Functions(预览版)。您可以将重试策略配置为固定延迟或指数退避。

[FunctionName("MyFunction")]
[FixedDelayRetry(10, "00:15:00")]   // retries with a 15-minute delay
public static void Run(
    [ServiceBusTrigger("MyTopic", "MySubscription", Connection = "ServiceBusConnection")] string myQueueItem) 
{
    // Forward message to HTTP endpoint, throwing exception if endpoint unavailable
}