Google Cloud Functions のアンチパターンを回避する(第 1 回): べき等性を念頭に置いたコーディングで Cloud Functions のイベント ドリブン関数を正しく記述する方法
Google Cloud Japan Team
※この投稿は米国時間 2021 年 10 月 21 日に、Google Cloud blog に投稿されたものの抄訳です。
編集者注: 今後数週間にわたり、Google Cloud Functions の関数を記述するためのベスト プラクティスに注目するブログ投稿シリーズを公開していきます。これらのベスト プラクティスは、サポートチームがよく受ける質問や、よく見かける誤解を基にしています。こうした問題をここでは「アンチパターン」と呼び、これらを回避する方法をご紹介します。この記事は、そのシリーズの第 1 回目です。
シナリオ
Cloud Functions の関数が、1 回のリクエストに対し複数回実行されていることがわかりました。たとえば、1 回のリクエストによって、Firestore に重複するエントリが保存されるような事象が起きています。
最も一般的なアンチパターン
Cloud Functions の関数がべき等ではありません。ここで「べき等」とは、同じ入力データによって関数を複数回呼び出すことができるけれども、最初の呼び出しの結果は変わらないことを意味します。以下に例を示します。
調べる方法:
バックグラウンド関数を使用する場合、実行保証について十分理解していることが重要です。バックグラウンド関数は、少なくとも 1 回呼び出されることが保証されています。それはつまり、次のことを意味します。
同じ入力データで、最初の結果を変えることなく関数を複数回呼び出すことができるかをテストする必要がある。
もしくは、べき等な関数を記述できない場合、こうした追加の呼び出しをどのように処理するかに関する計画が必要である。
べき等な関数の例
サーバーレスにおいては、べき等性を念頭に置いてコードを記述することが重要です。べき等性を確保できない場合、重複する呼び出しをどのように処理するかについて計画を立てることが重要となります。
まず、HTTP でトリガーされる関数を詳しく見て、べき等な関数がどのようなものかを確認します。次に、バックグラウンド関数におけるべき等の例を見ていきます。
HTTP 関数の例
以下のべき等の例では、リクエストに一意の値(センサー ID とタイムスタンプ)が含まれており、それが Firestore への保存のキーとして使われています。この一意のキーを指定するために Firestore.set() がどのように使われているかにご注目ください。これにより、(理論上は)HTTP 関数がリクエストを 2 回受け取っても、同じ一意のキーを使用してドキュメントが作成されているため、Firestore に重複したエントリが保存されることはありません。
次に、非べき等の HTTP 関数の例について考えて、べき等の場合と動作がどのように異なるかを見ていきます。以下に示す HTTP 関数は、Firestore が自動生成するキーを使用して Firestore.add() を呼び出し、データを保存します。そのため、(理論上は)この HTTP 関数が 2 回リクエストを受け取ると、Firestore に 2 つの新しいエントリが作成されます。
バックグラウンド関数の例
ここまで HTTP 関数を使用した例を見てきましたが、ここからはバックグラウンド関数のべき等性について説明します。再試行可能なバックグラウンド関数をべき等にする方法は数多くあります。
引き続き Firestore にデータを保存する場合を例にしますが、ここからは HTTP リクエストではなく Pub/Sub によって関数がトリガーされるように変更します。
一般的に、べき等になるように関数を記述する方法は 2 つあります。
保存しようとしているデータがすでに存在しているかどうかを確認する。
べき等なバージョンの API 呼び出し(Firestore.set() に対する Firestore.add() など)があるかどうかを確認する。
べき等な関数を記述できない場合
関数をべき等にできない場合(在庫状況のような外部ソースからの情報に依存している場合など)は、回避策を講じるか、重複エントリを処理するための計画を立てる必要があります。
ここで重要になるのは、問題を認識していることです。べき等性を追求しているのに、べき等になるように関数を記述できない場合は、リクエストが複数回行われることによって発生する可能性がある問題を意識することが重要です。
その他の役立つヒント
べき等性を考慮したバックグラウンド関数を記述できたら、断続的エラーやアプリケーション エラーに備えて再試行の実装を検討することをおすすめします。
再試行を有効にする前に、コードが連続再試行ループに陥らないことを確認してください。
- Cloud デベロッパー アドボケイト Sara Ford
- テクニカル ソリューション エンジニア Martin Skoviera