【问题标题】:How do I delay the execution of an Azure function after it fails?Azure 函数失败后如何延迟执行?
【发布时间】:2017-01-31 14:26:03
【问题描述】:

我正在使用一个 Azure 函数(用 C# 编写),当存储队列上有新消息时会触发该函数。该函数正在调用外部网络服务来处理消息,当外部服务响应时,一切正常。

问题是当外部网站关闭时,网络客户端会给出异常(周围没有 try/catch 块)。然后发生的情况是该函数被重试(通过 azure)5 次,每次尝试之间不到一秒。可以想象,Web 服务可能在所有 5 次尝试中仍处于关闭状态,这将使 azure 将消息移动到“毒药”队列。

是否可以配置在重试之前等待的时间量,或者我是否需要设置另一个每分钟运行一次的 azure 函数来检查毒队列中需要在正常情况下重新创建的消息排队?

【问题讨论】:

    标签: azure azure-functions


    【解决方案1】:

    我们目前没有为您提供配置失败消息的可见性超时的方法。如您所见,它目前被硬编码为TimeSpan.Zero。我同意你的观点,我们应该允许对其进行定制。我在我们的公共仓库中记录了一个问题,其中包含更多详细信息here

    【讨论】:

    • 感谢您提出问题。你说创建一个自定义队列处理器,但我想这仅适用于 webjobs 而不是 azure 函数?
    • 是的,这是一个更复杂、更低级别的可定制性,在 Functions 中不可用。
    • @mathewc 我看到 github 问题已关闭,host.json 允许设置visibilityTimeout。但这是一个固定的时间间隔。如果我想实现指数退避怎么办?
    【解决方案2】:

    该函数正在调用外部Web服务来处理消息,当外部服务响应时,一切正常。

    为什么不用队列消息来表示服务状态。

    Function is triggered
            \  /
             \/
    Do we have a message in service-status queue?
            \  /
             \/    
    Wait 30 seconds before making web-service call / else call it right away.
            \  /
             \/
    Can't reach web-service? -> Drop message in service-status queue.
    

    如果您有该 Function App 的多个实例,您需要使用存储中的持久文件或表存储中的条目发出信号。

    【讨论】:

    • 感谢您的快速回复,这个想法很好。然而问题是 Azure 按秒计费这些函数,因此在其中运行 Thread.Sleep(30000) 会非常昂贵。
    • 然后不要等待 30 秒。放弃。您不会删除该消息,因为您没有删除它。它将在visibility_timeout 中再次可见。队列中消息的顺序会被搞砸,但如果你能容忍的话,我看不到任何其他缺点。
    • 可能是我误会了你,但是如果我只是退出该功能,azure 会认为该消息已成功处理,它将永远消失。我还没有发现如何从 azure 函数中更改/设置可见性超时。
    • 这不应该发生,除非函数队列触发器与存储队列 SDK 的工作方式非常不同 - 请参阅“将下一条消息出队” - github.com/Azure/azure-content/blob/master/articles/storage/… -- 完成从队列,您还必须调用 DeleteMessage。
    • 请再次阅读问题,这就是我正在做的事情(抛出异常)。我在问如何在 azure 重试之前增加延迟。
    【解决方案3】:

    我们最终“手动”处理了 visibilityTimeout 参数:我们不使用输出绑定,而是将消息安排在队列中以供以后使用 Azure 存储 SDK 处理。

    https://github.com/teamdigitale/digital-citizenship-functions/blob/master/lib/utils/azure_queues.ts#L86

     queueService.updateMessage(
            queueName,
            queueMessage.id,
            queueMessage.popReceipt,
            visibilityTimeoutSec,
            err => {
              context.done( err );
            }
          );
    

    这让我们可以在不让进程进入休眠状态的情况下为 reties 插入一个指数退避策略。

    【讨论】:

      猜你喜欢
      • 2016-12-17
      • 2013-06-19
      • 1970-01-01
      • 2015-11-08
      • 2011-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-05
      相关资源
      最近更新 更多