首页 > 解决方案 > 如何在 Azure Functions 中实现指数退避?

问题描述

如何在 Azure Functions 中实现指数退避?

我有一个依赖于外部 API 的函数。我想使用重试策略来处理此服务的不可用性。当队列中出现新消息时触发此功能,在这种情况下,此策略默认打开:

对于大多数触发器,在函数执行期间发生错误时没有内置的重试。支持重试的两个触发器是 Azure 队列存储和 Azure Blob 存储。默认情况下,这些触发器最多重试五次。在第五次重试之后,两个触发器都将消息写入一个特殊的毒物队列。

不幸的是,重试在异常 (TimeSpan.Zero) 之后立即开始,在这种情况下这是没有意义的,因为服务很可能仍然不可用。 有没有办法动态修改消息在队列中再次可用的时间?

我知道我可以设置visibilityTimeouthost.json 参考),但它是为所有队列设置的,这不是我想要在这里实现的。

我找到了一种解决方法,但它远非理想的解决方案。如果出现异常,我们可以再次将消息添加到队列中,并为此消息设置 visibilityTimeout:

[FunctionName("Test")]
public static async Task Run([QueueTrigger("queue-test")]string myQueueItem, TraceWriter log,
    ExecutionContext context, [Queue("queue-test")] CloudQueue outputQueue)
{
    if (true)
    {
        log.Error("Error message");
        await outputQueue.AddMessageAsync(new CloudQueueMessage(myQueueItem), TimeSpan.FromDays(7),
            TimeSpan.FromMinutes(1), // <-- visibilityTimeout
            null, null).ConfigureAwait(false);
        return;
    }
}

不幸的是,这个解决方案很弱,因为它没有上下文(我不知道它是哪种尝试,因此我不能限制调用次数并修改时间(指数退避))。

内部重试策略也不受欢迎,因为它会大大增加成本(定价模型)。

标签: c#.netazureazure-functionsserverless

解决方案


微软在 2020 年 11 月左右(预览版)添加了重试策略,支持指数退避:

[FunctionName("Test")]
[ExponentialBackoffRetry(5, "00:00:04", "00:15:00")] // retries with delays increasing from 4 seconds to 15 minutes
public static async Task Run([QueueTrigger("queue-test")]string myQueueItem, TraceWriter log, ExecutionContext context)
{
    // ...
}

推荐阅读