在消费计划中使用队列触发器和 functionAppScaleLimit 的 Azure Functions 缩放和并发

Azure Functions scaling and concurrency using Queue triggers and functionAppScaleLimit on the Consumption Plan

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

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

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

详情请看@Hury Shen 的回复。我已经测试了三个队列触发场景。全部使用以下图例:

QueueTrigger 没有 functionAppScaleLimit

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

现在,我想我会坚持最后一个例子,但在未来我想我可以安全地将我的 functionAppScaleLimit 设置为 23 如果我升级到高级计划。我还将测试两个队列触发器,它们侦听 functionAppScaleLimit2 的不同存储队列,但我怀疑对我来说最安全的做法是为每个队列触发器创建单独的 Azure Function 应用程序在那种情况下。

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

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

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

在两个队列触发器 运行 同时 functionAppScaleLimit 设置为 2 的示例中,规模限制似乎不起作用。 Microsoft 的人可以解释一下吗?官方文档(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 设置。如果您使用多个队列触发器,您将遇到可能导致超时的竞争条件和等待。

是的,您只需将 functionAppScaleLimit 设置为 2。但是有一些关于消费计划的机制你需要知道。我用 batchSize 作为 1 在我这边测试它,并将 functionAppScaleLimit 设置为 2(我将 WEBSITE_MAX_DYNAMIC_APPLICATION_SCALE_OUT 设置为 2 in "应用程序设置”而不是设置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 条消息:111222333444555666777888999000,我都一一发过去了。函数触发成功,几分钟后,我们可以在“Monitor”中看到日志。点击“Monitor”中的其中一条日志,我们可以看到日志显示为:

我用上面截图右边的4个红框,我把4个日志分别命名为“s1”,“s2", "s3", "s4"(步骤 1-4)。并总结excel中的日志供大家参考:

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

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

1.最大实例数只能扩展到2,因为我们可以发现在[=132的每行中不存在超过两个黄色单元格=] table。 因此该函数无法扩展到超过您在问题中提到的 2 个实例。

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

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

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

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

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

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

A) 在one函数app中创建oneQueueTrigger函数监听one存储队列。这是我在原始答案中测试的内容,excel table 向我们展示了实例将通过消费计划机制进行扩展,我们无法控制它。

B) 在one函数app中创建two QueueTrigger函数监听same存储队列。结果与情况A几乎相同,我们无法控制使用多少实例来处理消息。

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

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

因此,您当前在 post is setting the functionAppScaleLimit to 2 enough to achieve that? 中的问题的答案是:如果您希望两个实例都启用运行并发,我们无法确定。如果你只是想让两个实例来处理消息,答案是肯定的。