各キューアイテムがURLであるキューを処理するAzure Storage QueueトリガーでAzure Functionアプリを作成しました。関数はURLのコンテンツをダウンロードするだけです。サイトのXMLサイトマップを読み込んで解析し、すべてのページのURLをキューに追加する別の関数があります。私が抱えている問題は、Functionsアプリの実行が速すぎて、Webサイトをハンマーしてサーバーエラーを返し始めることです。関数アプリの実行速度を制限/スロットルする方法はありますか?
もちろん、それらをシリアルに処理する(または非同期で、同時要求の数を制限する)単純なWebジョブを作成することもできますが、Azure Functionsのシンプルさが本当に好きで、「サーバーレス」コンピューティングを試してみたかったのです。
検討できるオプションがいくつかあります。
最初に、キューの処理を制御するHost.json
で構成できるいくつかのノブがあります(文書化された here )。 queues.batchSize
ノブは、一度にフェッチされるキューメッセージの数です。 1に設定すると、ランタイムは一度に1つのメッセージをフェッチし、そのメッセージの処理が完了したときにのみ次のメッセージをフェッチします。これにより、単一インスタンスである程度のシリアル化が可能になります。
別のオプションとして、エンキューするメッセージにNextVisibleTimeを設定して、間隔を空ける方法があります。デフォルトでは、エンキューされるメッセージは表示され、すぐに処理する準備ができています。
最後のオプションは、一度に1つではなく、サイトのすべてのURLのコレクションでメッセージをエンキューすることです。そのため、メッセージが処理されるときに、関数でURLをシリアルに処理し、並列処理を制限できます。そのように。
NextVisibleTimeいくつかの並列関数がキューに追加されている場合、混乱する可能性があります。この問題を抱えている人のためのもう1つの簡単なオプション:別のキュー「throttled-items」を作成し、元の関数がキュートリガーにそれに従うようにします。次に、元のキューから毎分メッセージを移動する単純なタイマー関数を追加し、それに応じてNextVisibleTimeの間隔を空けます。
[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);
}
同様の問題を解決しようとしたときにこの投稿を見つけました。これは、ここに到着したすべての人に役立つ場合があります。 WEBSITE_MAX_DYNAMIC_APPLICATION_SCALE_OUTアプリ設定を使用して、関数の同時インスタンス数を制限できるようになりました。これを1に設定してバッチ制限1と組み合わせると、キューのシリアル処理を実行できます。
WEBSITE_MAX_DYNAMIC_APPLICATION_SCALE_OUT
関数アプリがスケールアウトできるインスタンスの最大数。デフォルトは無制限です。