Google Cloud Functions のアンチパターンを回避する(第 5 回): Python でバックグラウンド プロセスを正しく実行する方法
Google Cloud Japan Team
※この投稿は米国時間 2021 年 11 月 18 日に、Google Cloud blog に投稿されたものの抄訳です。
編集者注: 過去数週間にわたり、Google Cloud Functions の関数を記述するためのベスト プラクティスに注目するブログ投稿シリーズを公開してきました。これらのベスト プラクティスは、サポートチームがよく受ける質問や、よく見かける誤解を基にしています。 こうした問題をここでは「アンチパターン」と呼び、これらを回避する方法をご紹介します。 この記事は、そのシリーズの第 5 回です。
シナリオ
Python 関数でバックグラウンド プロセスが完了する前に、ログに finished with status: 'timeout' が表示されます。
よくある根本的な問題
このタイムアウト エラーは、どのランタイムを使用する関数でも発生する可能性がありますが、Python デベロッパーが Cloud Functions の関数で os.fork() または multiprocessing.Process() を使用しようとした場合に特によく発生します。
Cloud Functions の関数で非同期処理を避けるべき理由
Cloud Functions の関数によって開始されたバックグラウンド タスクは、完了することが保証されていません。そのため、関数が完了したら(関数を返したり、タイムアウト エラーが発生したりなど)、関数インスタンスはいつでも終了できます。関数実行タイムラインについて詳しくは、ドキュメントをご覧ください。
多くの場合、お客様は関数のテストを、このような実行タイムアウトが存在しないローカル環境で行っています。また、お客様のローカルマシンは Cloud Functions の関数をプロビジョニングしているマシンよりも高性能である場合があります。そのため、こうしたマルチプロセスのシナリオがローカルで機能しているのを見て、コードが Cloud Functions インスタンスでも同じように機能すると思い込んでしまうことがあります。
このような非同期処理を必要とする Python デベロッパーは、代わりに Cloud Tasks サービスを使用してバックグラウンド処理をスケジュールすることをおすすめします。次の例をご覧ください。
Python Cloud Functions の関数で Cloud Tasks を使用する
次の関数は、Cloud Tasks を使用して非同期処理をスケジュールする方法を示しています。これは、Cloud Functions の関数(名前は「create_task」)が、バックグラウンド タスクを実行する別の Cloud Functions の関数を呼び出す Cloud Task を作成する例になります。詳細については、HTTP Target タスクの作成をご覧ください。
その他の役立つヒント
こちらのチュートリアルは Node.js 用に作成されていますが、Cloud Tasks タスクのキューを作成し、タスクから関数を呼び出すためのサービス アカウントを設定する手順も説明しています。タスクにサービス アカウントを指定することで、認証が必要な Cloud Functions の関数を使用できます。
Cloud Functions の関数の呼び出しに(関数の ID ではなく)異なるサービス アカウントを使用している場合、そのサービス アカウントに Cloud Functions 起動元のロール(roles/cloudfunctions.invoker)があることを確認する必要があります。
「create_task」関数の ID に、デフォルトとは異なるサービス アカウントを使用している場合、そのサービス アカウントにタスクを作成する権限があることを確認する必要があります。Cloud Tasks へのデータ追加ロール(roles/cloudtasks.enqueuer)が必要です。
Cloud Tasks について詳しくは、本シリーズの第 3 回目のブログ記事(アウトバウンド接続の確立方法)もご確認ください。
- Cloud デベロッパー アドボケイト Sara Ford
- テクニカル ソリューション エンジニア Martin Skoviera