J'ai créé une application Azure Function avec un déclencheur Azure Storage Queue qui traite une file d'attente dans laquelle chaque élément de file d'attente est une URL. La fonction télécharge simplement le contenu de l'URL. J'ai une autre fonction qui charge et analyse le plan du site XML d'un site et ajoute toutes les URL de page à la file d'attente. Le problème que j'ai est que l'application Functions s'exécute trop rapidement et qu'elle martèle le site Web afin qu'elle commence à renvoyer des erreurs de serveur. Existe-t-il un moyen de limiter/limiter la vitesse d'exécution de l'application Fonctions?
Je pourrais, bien sûr, écrire un travail Web simple qui les a traités en série (ou avec un peu d'async mais limiter le nombre de demandes simultanées), mais j'aime vraiment la simplicité d'Azure Functions et je voulais essayer l'informatique "sans serveur".
Vous pouvez envisager quelques options.
Tout d'abord, il y a quelques boutons que vous pouvez configurer dans Host.json
qui contrôle le traitement des files d'attente (documenté ici ). Le queues.batchSize
Le bouton est le nombre de messages de file d'attente récupérés à la fois. S'il est défini sur 1, le runtime récupère 1 message à la fois et ne récupère le suivant que lorsque le traitement de ce message est terminé. Cela pourrait vous donner un certain niveau de sérialisation sur une seule instance.
Une autre option pourrait être pour vous de définir le NextVisibleTime sur les messages que vous mettez en file d'attente de manière à ce qu'ils soient espacés - par défaut, les messages mis en file d'attente deviennent visible et prêt pour le traitement immédiatement.
Une dernière option pourrait être de mettre en file d'attente un message avec la collection de toutes les URL pour un site, plutôt qu'une à la fois, donc lorsque le message est traité, vous pouvez traiter les URL en série dans votre fonction et limiter le parallélisme de cette façon.
NextVisibleTime peut devenir compliqué s'il y a plusieurs fonctions parallèles s'ajoutant à la file d'attente. Une autre option simple pour tous ceux qui ont ce problème: créez une autre file d'attente, "éléments étranglés", et demandez à votre fonction d'origine de la suivre pour les déclencheurs de file d'attente. Ensuite, ajoutez une fonction de minuterie simple qui déplace les messages de la file d'attente d'origine toutes les minutes, en espaçant les NextVisibleTime en conséquence.
[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, itemsPerMinute - 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);
}
J'ai trouvé ce message en essayant de résoudre un problème similaire. Cela pourrait être utile à toute personne qui arrive ici. Vous pouvez désormais limiter le nombre d'instances simultanées de la fonction à l'aide du paramètre d'application WEBSITE_MAX_DYNAMIC_APPLICATION_SCALE_OUT. La définition de cette valeur sur 1 combinée à une limite de lot de 1 vous permettrait d'effectuer le traitement en série d'une file d'attente.
WEBSITE_MAX_DYNAMIC_APPLICATION_SCALE_OUT
Le nombre maximal d'instances que l'application de fonction peut évoluer. La valeur par défaut est sans limite.