Azure Functionsの制限時間は10分です。ダウンロードに1時間かかるファイルのダウンロードなど、長時間実行するタスクがあるとします。
[FunctionName("PerformDownload")]
[return: Queue("download-path-queue")]
public static async Task<string> RunAsync([QueueTrigger("download-url-queue")] string url, TraceWriter log)
{
string downloadPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString);
log.Info($"Downloading file at url {url} to {downloadPath} ...");
using (var client = new WebClient())
{
await client.DownloadFileAsync(new Uri(url), myLocalFilePath);
}
log.Info("Finished!");
}
このようなものを開始し、制限時間が切れる前に別の関数で再開するためのハッキーな方法はありますか?または、Azure Functionsを使用するワークフローにこのような長いタスクを統合するより良い方法はありますか?
(少し関連するメモとして、プレーンなAzure Webジョブは時代遅れですか?リソースの下に見つかりません。)
ワークロードの詳細に応じて、Azure Container Instancesを利用することもできます。 Azure Functionでコンテナーを起動し、ワークロードを処理して(ファイルをダウンロードして、\いくつかの処理を行うなど)、コンテナーをシャットダウンできます。スピンアップ時間は通常数秒であり、使用した分に対してのみ支払います(専用のアプリサービスプランやVMインスタンスは必要ありません)。 ACIの詳細 ここ 。
この投稿に出くわす可能性のある人のために追加:複数のAzure関数で構成されるワークフローは、非同期タスクをスケジュールするオーケストレーション関数の作成に使用できる Durable Functions 拡張を使用してコードで作成でき、シャットダウンします。そして、非同期作業が完了すると、再び起こされます。
これらは、ファイルのダウンロードなど、開いているTCPポートを必要とする長期実行タスクの直接的な解決策ではありません(そのため、App Service Planで実行されている関数には実行時間がありません制限)、そのようなタスクをより大きなワークフローに統合するために使用できます。
このようなものを開始し、制限時間が切れる前に別の関数で再開するためのハッキーな方法はありますか?
消費プランを使用している場合、Function Appの実行時間を制御できないため、Functionエントリポイントが完了した後も実行を継続するバックグラウンドスレッドを使用することは信頼できません。
App Serviceプランでは、有償のVMで実行しているため、Function Appを継続的に実行するように構成できます。また、AFAIKでは、App Serviceプランで関数のタイムアウトを設定する必要がないため、メインの関数エントリポイントを必要なだけ実行できます。
または、Azure Functionsを使用するワークフローにこのような長いタスクを統合するより良い方法はありますか?
はい。 Azure Data Factory を使用してデータをBlob Storageにコピーし、処理します。 Data Factoryパイプラインは、コピーアクティビティの前後の両方で関数を呼び出すことができます。
関数アプリの最後の関数がトリガーされてから10分( Host.json ファイルのタイムアウト設定に基づく)、VM関数アプリを実行するとやめる。
この動作が発生しないようにするには、空の Timertrigger関数 を5分ごとに実行します。それは何も費用がかからず、あなたのアプリを稼働させ続けます。
問題はコールドスタート状態に関連していると思います。ここでそれについての詳細を見つけることができます。 https://markheath.net/post/avoiding-Azure-functions-cold-starts
あなたができることは、それを「ウォーム」に保つためにあなたの長期実行関数を「ping」するトリガーAzure関数を作成することです
namespace NewProject
{
public static class PingTimer
{
[FunctionName("PingTimer")]
public static async Task Run([TimerTrigger("0 */4 * * * *")]TimerInfo myTimer, TraceWriter log)
{
// This CRON job executes every 4 minutes
log.Info($"PingTimer function executed at: {DateTime.Now}");
var client = new HttpClient();
string url = @"<Azure function URL>";
var result = await client.GetAsync(new Uri(url));
log.Info($"PingTimer function executed completed at: {DateTime.Now}");
}
}}