在Azure功能应用程序中限制Azure存储队列处理

Ale*_*lex 23 azure azure-functions

我创建了一个Azure功能应用程序,其中包含一个Azure存储队列触发器,用于处理每个队列项都是URL的队列.该功能只下载URL的内容.我有另一个函数加载和解析站点的XML站点地图,并将所有页面URL添加到队列中.我遇到的问题是,功能应用程序运行得太快,它会破坏网站,使其开始返回服务器错误.有没有办法限制/限制功能应用程序运行的速度?

当然,我可以编写一个简单的Web作业来连续处理它们(或者使用一些异步但限制并发请求的数量),但我真的很喜欢Azure Functions的简单性并想尝试"无服务器"计算.

mat*_*ewc 30

您可以考虑几个选项.

首先,您可以在host.json控制队列处理中配置一些旋钮(此处记录).该queues.batchSize旋钮是众多队列中的消息是如何一次取.如果设置为1,则运行时将一次获取1条消息,并且仅在完成该消息的处理时获取下一条消息.这可以为您提供单个实例的某种级别的序列化.

另一种选择可能是你在你排队的消息上设置NextVisibleTime,使它们间隔开 - 默认情况下,排队的消息变得可见并准备好立即处理.

最后一个选项可能是您将一个消息与一个站点的所有URL集合排队,而不是一次排队,因此在处理消息时,您可以在函数中串行处理URL,并限制并行性那样.

  • 谢谢@mathewc.我提出了你的第二个建议(设置NextVisibleTime).我花了一些时间来弄清楚如何实现这一点,但它运作良好.我的代码在https://github.com/alindgren/SiteWarmer,以防有人想看一眼. (9认同)
  • host.json文档已更改为:https://docs.microsoft.com/en-us/azure/azure-functions/functions-host-json (3认同)

vla*_*rby 6

NextVisibleTime can get messy if there are several parallel functions adding to the queue. Another simple option for anyone having this problem: Create another queue, "throttled-items", and have your original function follow it for the queue triggers. Then, add a simple timer function that moves messages from the original queue every minute, spacing the NextVisibleTime accordingly.

    [FunctionName("ThrottleQueueItems")]
    public static async Task Run([TimerTrigger("0 * * * * *")] TimerInfo timer, ILogger logger)
    {
        var originalQueue = // get original queue here;
        var throttledQueue = // get throttled queue here;
        var itemsPerMinute = 60; // get from app settings
        var individualDelay = 60.0 / itemsPerMinute;
        var totalRetrieved = 0;
        var maxItemsInBatch = 32; // change if you modify the default queue config
        do
        {
            var pending = (await originalQueue.GetMessagesAsync(Math.Min(maxItemsInBatch, htmlPerMinute - totalRetrieved))).ToArray();
            if (!pending.Any())
                break;
            foreach (var message in pending)
            {
                await throttledQueue.AddMessageAsync(new CloudQueueMessage(message.AsString), null,
                                                                                        TimeSpan.FromSeconds(individualDelay * ++totalRetrieved), null, null);
                await originalQueue.DeleteMessageAsync(message);
            }
        } while (itemsPerMinute > totalRetrieved);
    }
Run Code Online (Sandbox Code Playgroud)


jon*_*dow 5

我在尝试解决类似问题时发现了这篇文章。这可能对到达这里的任何人都有用。您现在可以使用 WEBSITE_MAX_DYNAMIC_APPLICATION_SCALE_OUT 应用程序设置来限制函数的并发实例数。将此设置为 1 并结合批处理限制 1 将允许您执行队列的串行处理。

WEBSITE_MAX_DYNAMIC_APPLICATION_SCALE_OUT

函数应用可以扩展到的最大实例数。默认是没有限制。

https://docs.microsoft.com/en-gb/azure/azure-functions/functions-app-settings#website_max_dynamic_application_scale_out

  • 这很有用。注意:根据文档,目前该设置处于预览状态,建议的方法是更新“functionAppScaleLimit”应用程序属性:https://learn.microsoft.com/en-gb/azure/azure-functions/functions-scale #限制扩展 (3认同)