インスタンスの管理方法

インスタンスは App Engine の基本的な構成要素で、アプリケーションのホスティングに必要なすべてのリソースを提供します。ある時点において、アプリケーションは 1 つのインスタンスで実行されていることもあれば、複数のインスタンスで実行されていることもあります(この場合、リクエストはすべてのインスタンス間で分散されます)。各インスタンスにはセキュリティ レイヤが組み込まれており、インスタンスが誤って相互に影響しないようになっています。

App Engine では、トラフィックの変動に応じてインスタンスを自動的に作成またはシャットダウンできます。もしくは、トラフィックの量に関係なく、実行するインスタンス数を指定することもできます。新しいインスタンスを作成する方法とタイミングを決定するには、アプリのスケーリング タイプを指定します。スケーリング設定は、app.yaml ファイルの一部として、App Engine のバージョン レベルで適用されます。

スケーリング タイプ

App Engine は次のスケーリング タイプをサポートしており、これによりインスタンス作成の方法とタイミングを制御します。

  • 自動(デフォルト)
  • 基本
  • 手動

スケーリング タイプは、アプリの app.yaml で指定します。デフォルトでは、アプリは自動スケーリングを使用します。つまり、App Engine はアイドル インスタンスの数を管理します。

自動スケーリング
自動スケーリングは、リクエスト率、レスポンスのレイテンシなどのアプリケーションの指標に基づいてインスタンスを作成します。automatic_scaling 要素を構成することで、それぞれの指標のしきい値と、常時稼働する最小数のインスタンスを指定できます。
基本スケーリング
基本スケーリングでは、アプリケーションがリクエストを受信したときに、インスタンスが作成されます。各インスタンスは、アプリケーションがアイドル状態になるとシャットダウンされます。基本スケーリングは、断続的な処理やユーザーのアクティビティに応じて動作する処理に適しています。
手動スケーリング
手動スケーリングでは、負荷レベルに関係なく、常に実行されるインスタンスの数を指定します。これにより、複雑な初期化などのタスクや、時間の経過に伴うメモリの状態に依存するアプリケーションが実行できるようになります。
以下に、3 つのスケーリング タイプのパフォーマンス機能を比較した表を示します。

機能 自動スケーリング 基本スケーリング 手動スケーリング
リクエスト タイムアウト HTTP リクエストとタスクキューのタスクの場合は 10 分。アプリがこの制限時間内にリクエストを返さない場合、App Engine はリクエスト ハンドラを中断し、処理するコードのエラーを出力します。

レガシー ランタイム(Java 8、PHP 5、Python 2)の場合:

  • タスクキューのタスクと cron ジョブからのリクエストのタイムアウトは 10 分です。
  • その他の HTTP リクエストのタイムアウトは 1 分です。
HTTP リクエストとタスクキューのタスクの場合 24 時間。アプリがこの制限時間内にリクエストを返さない場合、App Engine はリクエスト ハンドラを中断し、処理するコードのエラーを出力します。

基本スケーリングしたインスタンスでは、/_ah/start を処理し、HTTP レスポンス コードを返さずに何時間もプログラムやスクリプトを実行できます。

基本スケーリングと同じです。
バックグラウンド スレッド 許可されていません 許可 許可
常駐 インスタンスは使用パターンに基づいてシャットダウンされます。 インスタンスは、idle_timeout パラメータに基づいてシャットダウンされます。リクエストを受信していない時間が idle_timeout を超えた場合など、アイドル状態になっているインスタンスはシャットダウンされます。 インスタンスはメモリに残り、状態はリクエスト間で保持されます。インスタンスを停止すると、ログに /_ah/stop リクエストが記録されます。/_ah/stop ハンドラまたは登録済みのシャットダウン フックがある場合、シャットダウンが発生するまでに 30 秒かかります。
起動とシャットダウン インスタンスはリクエスト処理のためにオンデマンドで作成され、アイドル時には自動的にシャットダウンされます。 インスタンスはリクエストを処理するためにオンデマンドで作成され、アイドル時には idle_timeout に基づいて自動的にシャットダウンされます。手動で停止したインスタンスは、リクエストの処理完了まで 30 秒待ってから強制終了されます。 インスタンスには、/_ah/start に対する空の GET リクエストの形式で App Engine から自動的に起動リクエストが送信されます。基本スケーリングの場合と同様、手動で停止されたインスタンスは、リクエスト処理の完了まで 30 秒待ってから強制終了されます。
インスタンスのアドレス指定 インスタンスは匿名です。 サービス「s」のバージョン「v」のインスタンス「i」は、https://i-dot-v-dot-s-dot-app_id.REGION_ID.r.appspot.com という形式の URL でアドレス指定できます。カスタム ドメインにワイルドカード サブドメイン マッピングを設定している場合は、https://s.domain.com または https://i.s.domain.com という形式の URL でサービスやその任意のインスタンスをアドレス指定できます。各インスタンスの状態を確実にキャッシュに保存し、後続のリクエストでそれを取得できます。 基本スケーリングと同じです。
スケーリング App Engine は処理量に応じて自動的にインスタンスの数を増減させます。このスケーリングは、構成ファイルでバージョンごとに指定されている automatic_scaling 設定に基づいて実行されます。 基本スケーリングを適用するサービスについては、basic_scaling 構成の max_instances パラメータでインスタンスの最大数を設定します。実行中のインスタンスの数は、処理量に応じて増減します。 各バージョンのインスタンスの数は該当するサービスの構成ファイルで構成します。インスタンスの数は通常、メモリに保持されているデータセットのサイズまたはオフライン作業の目標スループットに対応します。Modules API の set_num_instances 関数を使用すると、現在実行中のインスタンスを停止せずに、手動でスケーリングしたバージョンのインスタンスの数をすばやく調整できます。

動的インスタンスのスケーリング

基本スケーリングまたは自動スケーリングを使用する App Engine アプリケーションは、受信リクエストの量に応じて、随時、任意の数の動的インスタンスによって実行されます。アプリケーションに対するリクエストが増加すると、動的インスタンスの数も増加する可能性があります。

基本スケーリングを使用するアプリ

基本スケーリングを使用すると、App Engine は低コストを維持しようとしますが、受信リクエストの量が増えるため、レイテンシが増大することになります。

受信リクエストを処理できる既存のインスタンスがない場合、App Engine は新しいインスタンスを起動します。新しいインスタンスを起動した後でも、新しいインスタンスが起動プロセスを完了するまで、リクエストをキューに入れる必要がある場合があります。レイテンシを最小限に抑える必要がある場合は、自動スケーリングを使用して、新しいインスタンスをプリエンプティブルに作成することを検討してください。

自動スケーリングを使用するアプリ

自動スケーリングを使用する場合は、アプリの各インスタンスに受信リクエスト用の独自のキューがあります。アプリのレイテンシに影響が及ぶほどキューが長くなる前に、App Engine は自動的に新しいインスタンスを 1 つ以上作成して負荷の増加に対応します。

自動スケーリングの設定を構成することで、必要なパフォーマンスと支払うべき費用とのトレードオフを実現できます。次の表では、これらの設定について説明しています。

自動スケーリングの設定 説明
ターゲットの CPU 使用率 CPU 使用率のしきい値を設定して、トラフィックを処理するインスタンスの増加を開始する CPU 使用率の上限を指定します。
ターゲットのスループット使用率 同時リクエストの数にスループットのしきい値を設定します。このしきい値を超えると、トラフィックを処理するインスタンスの増加が開始されます。
最大同時リクエスト インスタンスが受け入れることができる同時リクエストの最大数を設定します。これを超えると、スケジューラが新しいインスタンスを生成します。

App Engine のスケジューラの設定の動画を見ると、これらの設定の効果を確認できます。

スケールダウン

リクエスト数量が減ると、App Engine はインスタンスの数を減らします。この縮小スケーリングにより、アプリケーションの現在のインスタンスすべてが最適な効率と費用対効果で使用されます。

あるアプリケーションがまったく使用されていないとき、App Engine はそのアプリケーションに関連付けられた動的インスタンスを無効にしますが、インスタンスが必要になった時点で直ちに再読み込みを行います。インスタンスが再度読み込まれると読み込みリクエストが発生するため、ユーザーに対してレイテンシが発生します。

アイドル状態にするインスタンスの最小数を指定できます。アプリケーションのアイドル インスタンス数をリクエスト数量に応じて適切に設定すると、リクエスト数量が異常に多くなった場合を除き、アプリケーションは少ないレイテンシですべてのリクエストに対処できます。

自動スケーリングでのスケールダウン

アプリで自動スケーリングを使用する場合は、アイドル状態のインスタンスが約 15 分間非アクティブになり、シャットダウンが開始されます。1 つ以上のアイドル インスタンスを実行し続けるには、min_idle_instances の値を 1 以上に設定します。

リクエストのスケーリングとバッチ

複数のリクエストをタスクキューなどのサービスに一括送信して処理する場合、短時間のうちに多数のインスタンスが作成されます。可能であれば、これを制御するために 1 秒あたりの送信リクエスト数をレート制限することをおすすめします。たとえば、Google Tasks を使用する場合は、タスクが push されるレートを制御できます。

インスタンスのライフサイクル

インスタンスの状態

自動スケーリング サービスのインスタンスは常時実行されています。それに対して、手動または基本スケーリング サービスのインスタンスは実行中と停止中のどちらかになります。サービスとバージョンが同じであるインスタンスはすべて、同じ状態を共有します。インスタンスの状態を変更するには、バージョンを管理します。次のことが可能です。

起動

各サービス インスタンスは、起動リクエスト(/_ah/start に対する空の HTTP GET リクエスト)へのレスポンスとして作成されます。App Engine は、このリクエストを送信してインスタンスを生成します。ユーザーが /_ah/start にリクエストを送ることはできません。手動スケーリングと基本スケーリングのインスタンスは、起動リクエストに応答した後で初めて別のリクエストを処理できるようになります。起動リクエストは、次の 2 つの目的で使用できます。

  • 追加のリクエストを受け入れずに、無期限で実行されるプログラムを起動する。
  • 追加のトラフィックを受信する前に、インスタンスを初期化する。

スケーリングの種類(手動、基本、自動)によって、インスタンスの起動方法が異なります。手動スケーリングのインスタンスを起動すると、App Engine は各インスタンスに直ちに /_ah/start リクエストを送信します。基本スケーリング サービスのインスタンスを開始すると、App Engine はトラフィックの受信を許可しますが、最初のユーザー リクエストを受け取るまではインスタンスに /_ah/start リクエストが送信されません。基本スケーリングの複数インスタンスが起動されるのは、トラフィックの増加に対応する必要がある場合だけです。自動スケーリング インスタンスは /_ah/start リクエストを受信しません。

インスタンスが /_ah/start リクエストに対して HTTP ステータス コード 200–299 または 404 を返した場合、そのインスタンスは正常に起動したとみなされ、追加のリクエストを処理できます。それ以外の場合、App Engine はインスタンスを終了します。手動スケーリングのインスタンスは直ちに再起動されますが、基本スケーリングのインスタンスは、トラフィックの処理に必要になった時点で初めて再起動されます。

シャットダウン

シャットダウン プロセスは、次に示すような計画的なイベントや計画外のイベントによってトリガーされます。

  • インスタンスが多すぎてアプリのリクエスト(トラフィック)が不十分になっている。
  • インスタンスを手動で停止した。
  • 更新されたバージョンをサービスにデプロイした。
  • インスタンスのメモリ量が、instance_class で構成されている最大値を超えた。
  • アプリケーションが、インスタンスの時間割り当てをすべて消費した。
  • インスタンスを現在実行しているマシンが再起動されたか、負荷分散の効率を改善する目的で App Engine がインスタンスを移動したため、インスタンスが別のマシンに移動された。

前述のスケールダウンで説明したように、App Engine スタンダード環境の「必要な分だけ支払う」プラットフォームの利点の 1 つは、トラフィックがないときに、システムによりインスタンスの数がゼロまで自動スケーリングされることです。これにより、継続的なリクエストを受信しない小規模アプリケーション向けに、App Engine で費用対効果の高いソリューションを実現できます。インスタンスをシャットダウンする必要がある場合、新しい受信リクエストは他のインスタンス(存在する場合)に転送され、現在処理されているリクエストを完了するための時間が与えられます。

インスタンスをシャットダウンする必要がある場合、App Engine は KILLSIGKILL)シグナルを送信してインスタンスを終了します。

読み込みリクエスト

App Engine でアプリケーションの新しいインスタンスが作成されるとき、リクエストの処理に必要なすべてのライブラリとリソースを最初にインスタンスで読み込む必要があります。この読み込みは、インスタンスへの最初のリクエスト(「読み込みリクエスト」)の際に発生します。読み込みリクエスト中にアプリケーションで初期化が行われるため、リクエストの処理に通常より時間がかかります。

読み込みリクエストの所要時間を短縮するためのベスト プラクティスを次に紹介します。

  • 起動に必要なコードのみを読み込む。
  • ディスクへのアクセスをできる限り少なくする。
  • 場合によっては、1 個の zip または jar ファイルからコードを読み込む方が、多数のファイルから読み込むよりも高速である。

ウォームアップ リクエスト

ウォームアップ リクエストは、実際のリクエストが行われる前に、インスタンスにアプリケーション コードを事前読み込みする特殊な読み込みリクエストです。手動または基本スケーリング インスタンスは /_ah/warmup リクエストを受信しません。

ウォームアップ リクエストの使用方法については、ウォームアップ リクエストの構成をご覧ください。

インスタンス稼働時間

App Engine は、手動スケーリングと基本スケーリングのインスタンスを継続的に実行しようと試みます。ただし、現時点では、手動および基本スケーリング インスタンスの稼働時間は保証されていません。ハードウェアやソフトウェアの障害により、事前の警告なしで処理が途中で終了する場合があります。また、再起動が頻繁に発生することもあります。これにより、障害の解決に時間がかかる可能性もあります。したがって、このような障害に耐えられるような方法でアプリケーションを構築する必要があります。

インスタンスの再起動によるダウンタイムを回避するには、次のような手法が効果的です。

  • インスタンスの再起動や新規インスタンスの起動にかかる時間を短縮する。
  • 長時間実行される処理では、チェックポイントを定期的に作成して、その状態から再開できるようにする。
  • アプリを「ステートレス」にして、インスタンスに何も格納されないようにする。
  • 非同期タスクの実行にキューを使用する。
  • インスタンスを手動スケーリングとして構成する場合:
    • 複数のインスタンス間でロード バランシングを行う。
    • 通常のトラフィックの処理に必要な数よりも多くのインスタンスを構成する。
    • 手動スケーリング インスタンスが使用不可の場合にキャッシュ内の結果を使用するよう、フォールバック ロジックを作成する。

App Engine スタンダード環境での NTP

App Engine スタンダード環境には、Google NTP サーバーを使用するネットワーク タイム プロトコル(NTP)サービスがあります。ただし、NTP サービスは変更できません。