Google Cloud Schedulerを使ってCloud Functionsを定期実行させてみた

Cloud Functionsはサーバレスで動作可能な実行環境です。軽量なAPIを動作させるのに、AWS のChalice(Lambda)をよく使っていますが、GoogleのCloud Functionsでも同様のことができます

Google Cloud Functions とは

Google Cloud Functions は、クラウド サービスの構築と接続に使用するサーバーレスのランタイム環境です。Cloud Functions を使用すると、クラウドのインフラストラクチャやサービスで生じたイベントに関連する、シンプルで一義的な関数を作成できます。対象のイベントが発生すると、Cloud Functions がトリガーされ、コードがフルマネージドの環境で実行されます。インフラストラクチャをプロビジョニングする必要はなく、サーバーの管理に悩まされることもありません。

Cloud Functions の関数は、さまざまなサポート対象のプログラミング言語を使用して作成できます。サポートされているいずれかの標準的なランタイム環境で関数を実行すると、環境に依存することなく簡単にローカルテストを実施できます。

https://cloud.google.com/functions/docs/concepts/overview?hl=ja

Cloud Functionsの問題点(コールドスタート)

Cloud Functionsは呼び出し時に関数を初期化して準備を始めますので、最初の呼び出し時に数十秒時間がかかることがあります。(=コールドスタート)

以下の引用にありますように、これを回避するには、最小インスタンスを1(デフォルトでは0)にしておき、常にインスタンスをアイドル状態にしておけば良いようです。

最小インスタンス数を構成する

インスタンスの最小数を設定することで、アプリケーションのコールド スタートを回避し、アプリケーションのレイテンシを短縮できます。

Cloud Functions では、関数の新しいインスタンスを作成してスケーリングを行います。各インスタンスは一度に 1 つのリクエストしか処理できないので、リクエスト量が急増すると、多くの場合、新しいインスタンスを作成して需要を処理するため、待機時間が長くなります。

関数はステートレスであるため、実行環境をゼロから初期化することがあり、これはコールド スタートと呼ばれます。コールド スタートは完了するまでに時間がかかることがあるため、アプリケーションがレイテンシの影響を受けやすい場合は、Cloud Functions のインスタンスを最小数に設定することをおすすめします。

https://cloud.google.com/functions/docs/configuring/min-instances?hl=ja

ただ、以下に記載されている通り、最小インスタンスを設定すると常に料金が発生することになります。使用頻度が非常に少ないFunctionの場合、ちょっと勿体無い気がします。

アイドル インスタンスとコールド スタート

コールド スタートの影響を最小限に抑えるため、Cloud Functions では、リクエストを処理した後、関数インスタンスをアイドル状態で無期限に維持しようとします。このアイドル期間では、別のリクエストを処理する必要がある場合に備え、確立されているデータベース接続などのリソースが残り続けることがあります。このようにアイドル状態が維持されたインスタンスは、ご利用の関数でのインスタンスの上限数に対してカウントされますが、アイドル期間は課金されません。

この組み込み動作は、特にレイテンシの影響を受けやすいアプリケーションでは、不十分な場合があります。追加の対策としては、インスタンスの最小数を明示的に設定することで、コールド スタートを回避し、アプリケーションのレイテンシを低減できます。

インスタンスの最小数が設定されたためにインスタンスがアイドル状態のままになっている場合、これらのインスタンスは、トラフィックを最近提供していない限りアクティブとはみなされません。たとえば、関数がトラフィックを最近処理していない場合は、最小インスタンスの値が設定されていても、「アクティブ インスタンス」指標には「アクティブなインスタンスがない」と示される可能性があります。

ただし、インスタンスの最小数を設定すると、そうしたインスタンスのアイドル時間に対しても課金が発生します料金をご覧ください)。

インスタンスの最小数を設定しなければ、アイドル期間は課金されないようなので、定期的にFunctionを呼び出すジョブを設定して、アイドル状態を維持してこれを回避してみたいと思います。

Cloud Scheduler

Cloud Functionsを定期的に呼び出すために、Cloud Schedulerを使います。

Cloud Scheduler について

Cloud Scheduler では、作業単位のスケジュールを設定して、定義した回数または一定の間隔で実行できます。これらの作業単位は、一般的に cron ジョブと呼ばれています。代表的な使い方としては、レポートメールを毎日送信する、10 分間隔でキャッシュ データを更新する、1 時間に 1 回要約情報を更新する、などがあります。

Cloud Scheduler を使用して作成された各 cron ジョブは、指定のスケジュールに従ってターゲットに送信されます。ターゲットはタスクが処理される場所です。ターゲットは、次のいずれかのタイプでなければなりません。

cron ジョブは、Cloud Console または gcloud コマンドライン ツールのいずれかを使用して作成できます。

https://cloud.google.com/scheduler/docs/overview?hl=ja

今回は、Cloud Consoleからジョブを作成します。

まず、スケジュール(実行時間)を定義します。

頻度は、unix-cron形式で指定します。

cron ジョブの形式

スケジュールは、unix-cron 文字列形式(* * * * *)を使用して定義されます。これは、1 行に 5 つのフィールドのセットであり、ジョブが実行されるタイミングを示しています。

unix-cron 文字列形式

スケジュールの例

以下の表に、cron ジョブ スケジュールの例とその説明を示します。

スケジュールの例cron ジョブの形式
1 分おき* * * * *
毎週土曜日の 23:45(午後 11:45)45 23 * * 6
毎週月曜日の 9:00(午前 9:00)0 9 * * 1
毎週日曜日の 4:05(午前 4:05)5 4 * * SUN
毎週平日(月~金)の 22:00(午後 10:00)0 22 * * 1-5
https://cloud.google.com/scheduler/docs/configuring/cron-job-schedules?hl=ja

次に実行内容を構成します。

ターゲットタイプをHTTPにして、URLにCloud FunctionのトリガーURLを設定します。

最後に、必要に応じてオプションを設定して「作成」すれば完了です。

結果

スケジュール設定後のCloud Functionsの状態は、こんな感じです。

15分おきにCloud Functionsを呼び出しています。これによって最小インスタンス数を1にした時と同様の速度でレスポンスを返すことができました。