1

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

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

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

4

3 回答 3

1

我将通过提供您提出的流程更好地由LogicApp处理而不是纯函数来解决您的情况。

在 LogicApp中实现等待/重试/出列下一个模式非常容易,因为这种类型的流控制正是 LogicApps 的设计目的。

于 2018-04-18T11:38:47.023 回答
1

尽管仍处于预览阶段(不推荐用于生产代码),但您可以使用Durable Functions。如果您想保持在代码中操作对象的能力,这可能是您最好的选择!

(也为 LogicApp 解决方案 +1!)

于 2018-04-18T18:51:35.860 回答
0

现在通过重试策略本机支持这一点,该策略于 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
}
于 2021-05-21T18:16:29.693 回答