【问题标题】:Azure Functions scaling and concurrency using Queue triggers and functionAppScaleLimit on the Consumption PlanAzure Functions 缩放和并发使用队列触发器和 functionAppScaleLimit 在消费计划
【发布时间】:2021-02-23 23:13:49
【问题描述】:

我在 Linux 消费计划上有一个 Azure Function 应用,它有两个队列触发器。两个队列触发器都将batchSize 参数设置为1,因为它们每个都可以使用大约 500 MB 的内存,而且我不想超过 1.5GB 的内存限制,所以只允许它们接收一条消息一次。

如果我想允许这两个队列触发器同时运行,但不希望它们超出此范围,将 functionAppScaleLimit 设置为 2 是否足以实现这一目标?

编辑:添加新示例,感谢@Hury Shen 为这些示例提供框架

更多详情请查看下方@Hury Shen 的回答。我已经测试了三个队列触发场景。都使用以下图例:

没有functionAppScaleLimit的QueueTrigger

QueueTrigger 将functionAppScaleLimit 设置为2
functionAppScaleLimit 设置为1 的QueueTrigger

目前,我想我会坚持使用最后一个示例,但将来如果我升级到高级计划,我想我可以安全地将我的 functionAppScaleLimit 设置为 23。我还将测试两个队列触发器,它们使用 functionAppScaleLimit2 监听不同的存储队列,但我怀疑对我来说最安全的做法是在该场景中为每个队列触发器创建单独的 Azure Function 应用程序。

编辑 2:在一个函数应用中添加两个队列触发器的示例

以下是在一个 Azure 函数中使用两个队列触发器时的结果,这些触发器正在侦听两个不同的存储队列。这是两个队列触发器的图例:

两个队列触发器同时运行,functionAppScaleLimit 设置为 2
两个队列触发器同时运行,functionAppScaleLimit 设置为 1

在两个队列触发器同时运行且functionAppScaleLimit 设置为2 的示例中,规模限制似乎不起作用。微软的人可以解释一下吗?官方文档 (https://docs.microsoft.com/en-us/azure/azure-functions/functions-scale#limit-scale-out) 中并没有警告该设置处于预览模式,但我们可以清楚地看到,当限制设置为 2 时,Azure Function 正在扩展到 4 个实例。在以下示例中,它看起来限制得到尊重,但功能不是我想要的,我们仍然看到@Hury Shen 的回答中存在等待。

结论
若要使用队列触发器限制 Azure Functions 中的并发和控制缩放,必须将 Azure Functions 限制为每个函数应用使用一个队列触发器,并使用 batchSizefunctionAppScaleLimit 设置。如果您使用多个队列触发器,您将遇到可能导致超时的竞争条件和等待。

【问题讨论】:

    标签: azure azure-functions azure-function-app azure-queues


    【解决方案1】:

    是的,您只需将functionAppScaleLimit 设置为2。但是您需要了解一些有关消费计划的机制。我用batchSize作为1在我身边测试它并将functionAppScaleLimit设置为2(我在功能应用程序的“应用程序设置”中将WEBSITE_MAX_DYNAMIC_APPLICATION_SCALE_OUT设置为2而不是设置functionAppScaleLimit,它们是相同的)。我用下面的代码进行测试:

    import logging
    import azure.functions as func
    import time
    
    def main(msg: func.QueueMessage) -> None:
        logging.info('=========sleep start')
        time.sleep(30)
        logging.info('=========sleep end')
        logging.info('Python queue trigger function processed a queue item: %s',
                     msg.get_body().decode('utf-8'))
    

    然后我将消息添加到队列中,我发送了 10 条消息:111222333444555666777888、@987654343 @,000,我一一发了。该功能触发成功,几分钟后,我们可以在“Monitor”中看到日志。点击“Monitor”中的日志之一,我们可以看到日志显示为:

    我在上面截图的右边使用了 4 个红色框,我将四个日志中的每一个命名为“s1”、“s2”、“ s3"、"s4"(步骤 1-4)。并总结excel中的日志供大家参考:

    我将“s2”到“s4”的单元格设为黄色,因为这段时间指的是函数任务的执行时间。

    根据excel的截图,我们可以推断出以下几点

    1.实例的最大数量只能扩展到2,因为我们可以发现它在excel表格的每一行中不超过两个黄色单元格。 因此,正如您在问题中提到的那样,该功能无法扩展到超过 2 个实例。

    2.你想让这两个队列触发器同时运行,可以实现。 但是实例会通过消费机制进行横向扩展。 简单来说,当一个函数实例被一条消息触发,还没有完成任务,现在又进来了一条消息,就不能确保使用另一个实例。第二条消息可能正在等待第一个实例。 我们无法控制是否启用另一个实例

    ================================更新======== =======================

    由于我对您的描述不是很清楚,我不确定您要收听多少个存储队列,以及您在自己身边创建了多少个函数应用程序和 QueueTrigger 函数。我将我的测试结果总结如下,供大家参考:

    1.关于would the Maximum Burst you described on the premium plan behave differently than this ?的问题,我想如果我们选择高级计划,实例也会以相同的消费计划机制横向扩展。

    2.如果你有两个存储队列需要监听,当然我们应该创建两个QueueTrigger函数来监听每个存储队列。

    3.如果你只需要监听一个存储队列,我用三种情况进行测试(我在三种情况下都将最大规模实例设置为2):

    A) 在 one 函数应用中创建 one QueueTrigger 函数来监听 one 存储队列。这是我在原始答案中测试的,excel表格显示实例将通过消费计划机制向外扩展,我们无法控制。

    B) 在一个函数应用中创建两个QueueTrigger函数来监听同一个存储队列。结果与案例A几乎相同,我们无法控制使用多少个实例来处理消息。

    C) 创建两个函数应用并在每个函数应用中创建一个QueueTrigger函数来收听相同 存储队列。结果也和案例 A 和 B 类似,不同的是最大实例可以扩展到 4,因为我创建了两个函数应用程序(它们都可以扩展到 2 个实例)。

    总之,我认为这三种情况都是相似的。虽然我们选择案例 3,但创建两个函数应用程序,每个应用程序中都有一个 QueueTrigger 函数。 我们也不能确保第二条消息立即处理,它仍然可能被处理到第一个实例并等待第一个实例完成处理第一条消息。

    所以这篇文章中您当前问题的答案 is setting the functionAppScaleLimit to 2 enough to achieve that? 是:如果您希望两个实例同时运行,我们无法确定。如果你只想要两个实例来处理消息,答案是肯定的。

    【讨论】:

    • 感谢您的详细回答。您的示例中的两个队列触发器是否都在同一个队列上侦听?我的示例是针对单独的队列,然后也许 Azure Functions 能够确保正在使用另一个实例?
    • 您在高级计划中描述的Maximum Burst 的行为会与此不同吗?这个解决方案对我不起作用,因为每个实例可能需要大约 5 分钟,而我不能在等待其他实例完成时浪费那段时间。
    • 也许将newBatchThreshold 设置为0 也能解决问题?
    • 我使用两个队列和一个 newBatchThreshold0 测试了您的进程,但问题仍然存在,因为我看到一些队列触发器的执行时间超过 60 秒。你认为这里有什么解决办法吗?还是我必须为每个队列创建一个完全独立的 Azure 函数或升级到高级计划?
    • 我认为最好的办法是使用两个单独的 Azure Function 应用程序,它们将侦听每个单独的队列,以确保您的示例中的等待不会发生。那么将来我可以将这两个计划升级到高级版并在需要时使用Maximum Burst
    猜你喜欢
    • 2021-02-08
    • 2021-02-10
    • 2018-12-26
    • 2021-12-26
    • 2018-12-17
    • 2017-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多