新たに作成されたインスタンスにアプリのコードが読み込まれる際のリクエストとレスポンスのレイテンシを短縮するには、ウォームアップ リクエストを使用します。
App Engine は、作成されたばかりのインスタンスにアプリのコードを頻繁に読み込む必要があります。次の場合にインスタンスの読み込みが起こる可能性があります。
- 別のバージョンのアプリを再デプロイするとき。
- リクエスト数が現在実行中のインスタンス セットの容量を超え、その不足分を補うために新しいインスタンスが作成されるとき。
- 基盤となるインフラストラクチャやハードウェアのメンテナンスまたは修復が行われるとき。
アプリのコードを新しいインスタンスに読み込むと、読み込みリクエストが発生することがあります。読み込みリクエストのために、ユーザーのリクエスト レイテンシが増加する可能性がありますが、ウォームアップ リクエストを使用することによりこのレイテンシを回避できます。ウォームアップ リクエストは、実際のリクエストがインスタンスに到達するよりも先にアプリのコードを新しいインスタンスに読み込みます。
アプリケーションでウォームアップ リクエストが有効化されていると、App Engine は新しいインスタンスがアプリケーションで必要になるタイミングを検知し、ウォームアップ リクエストを開始して新しいインスタンスを初期化しようとします。しかし、この検出がいつもうまくいくとは限りません。そのため、アプリでウォームアップ リクエストが有効になっていても、読み込みリクエストが発生する場合があります。たとえば、アプリがトラフィックを処理していなければ、アプリへの最初のリクエストはウォームアップ リクエストではなく、常に読み込みリクエストになります。
App Engine アプリケーションに対する他のリクエストと同様、ウォームアップ リクエストもインスタンス時間を消費します。ウォームアップ リクエストが有効になっていても、読み込みリクエストの代わりにウォームアップ リクエストでアプリケーションの初期化が行われているだけなので、ほとんどの場合インスタンス時間が増えていることには気づきません。ウォームアップ リクエスト中に事前キャッシングなどの他の処理も行うと、インスタンス時間が増える可能性があります。min_idle_instances
を 0
より大きい値に設定すると、それらのインスタンスの初回起動時にウォームアップ リクエストが発生する可能性がありますが、それ以降も使用できます。
ウォームアップ リクエストを有効にする
ウォームアップ リクエストは、App Engine スケジューラによって使用されます。このスケジューラはユーザーが指定した構成に基づいてインスタンスの自動スケーリングを制御します。App Engine の Java ランタイムでは、ウォームアップ リクエストがデフォルトで有効になっているため、App Engine が /_ah/warmup
に対して GET
リクエストを発行することで、必要に応じてレスポンスを返し、アプリケーションのコードを初期化できます。ウォームアップ リクエストは、次のいずれかの方法で処理できます。
<load-on-startup>
サーブレットの使用- ウォームアップ ロジックを追加する最も簡単な方法は、
web.xml
構成ファイルで独自のサーブレットを<load-on-startup>
として指定する方法です。 ServletContextListener
の使用- ウォームアップ リクエストまたは読み込みリクエストでサーブレットが最初に呼び出される前に、カスタム ロジックを実行できます。
- カスタム ウォームアップ サーブレットを使用する
- カスタム ウォームアップ サーブレットを使用すると、読み込みリクエストの処理時ではなくウォームアップ リクエストの処理時にのみ、サーブレットの
service
メソッドが呼び出されます。
選択した方法によっては、/_ah/warmup
に独自のハンドラを実装する必要があります。
始める前に
ウォームアップ リクエストが有効になっている場合、さらに多くのインスタンスが必要であると判断すると、スケジューラはインスタンスを起動します。スケジューラはウォームアップ リクエストを使用してアプリを起動するため、アプリでそのリクエストが処理されていなくても、ログには表示されます。
次のメッセージは、/_ah/warmup
ログのウォームアップ リクエストを示しています。
This request caused a new process to be started for your application, and thus caused your application code to be loaded for the first time. This request may thus take longer and use more CPU than a typical request for your application.
ウォームアップ リクエストは必ず呼び出されるとは限りません。代わりに読み込みリクエストが送信されることがあります。たとえば、インスタンスが初めて起動されるインスタンスである場合や、トラフィックが急激に上昇する場合です。ただし、ウォームアップ リクエストが有効になっている場合は、すでにウォームアップされているインスタンスにリクエストを送信する「ベスト エフォート方式」が試行されます。
Java 8 では、ウォームアップ リクエストがデフォルトで有効になっています。有効にするには、appengine-web.xml
で inbound_services
ディレクティブに - warmup
を追加します。ウォームアップはデフォルトで有効になるため、明示的に有効にする必要があるのは、appengine-web.xml
でウォームアップ リクエストを無効にしてアプリケーションをデプロイした場合に限られます。この場合は、<warmup-requests-enabled>
の値を true
に設定してから再デプロイする必要があります。
<load-on-startup>
サーブレットの使用
ウォームアップ ロジックを追加する最も簡単な方法は、web.xml
で独自のサーブレットを <load-on-startup>
として指定する方法です。この方法の場合、アプリケーション コードを変更する必要がなく、アプリケーションで初期化するときに、指定したすべてのサーブレットが初期化されます。
web.xml
ファイルで、起動時に読み込むサーブレットの <servlet>
要素に <load-on-startup>1</load-on-startup>
要素を追加します。例:
<servlet>
<servlet-name>my-servlet</servlet-name>
<servlet-class>com.company.MyServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
このコードでは、指定したサーブレット クラスを読み込み、サーブレットの init()
メソッドを呼び出しています。ウォームアップ リクエストにより、実際のリクエストを処理する前に、指定したサーブレットが初期化されます。ただし、ウォームアップ リクエストがない場合、<load-on-startup>
に指定したサーブレットは、新しいインスタンスへの最初のリクエストに登録され、それによってリクエストが読み込まれます。前述のように、App Engine は、アプリケーションが新しいインスタンスを必要とするたびにウォームアップ リクエストを発行するとは限りません。
ServletContextListener
の使用
サーブレットの呼び出し前に実行する必要があるカスタム ロジックがある場合は、次のようにします。
web.xml
ファイルにServletContextListener
を登録します。<listener> <listener-class>com.company.MyListener</listener-class> </listener>
クラス、サーブレット、フィルタコードを指定します。
public class MyListener implements ServletContextListener { public void contextInitialized(ServletContextEvent event) { // This will be invoked as part of a warmup request, or // the first user request if no warmup request was invoked. } public void contextDestroyed(ServletContextEvent event) { // App Engine does not currently invoke this method. } }
ServletContextListener
はウォームアップ リクエスト中に実行されます。ウォームアップ リクエストがない場合は、新しいインスタンスへの最初のリクエスト時に実行されます。これにより、読み込みリクエストが発生する場合があります。
カスタム ウォームアップ サーブレットを使用する
カスタム ウォームアップ サーブレットは、ウォームアップ リクエストの処理時にのみ、サーブレットの service
メソッドを呼び出します。カスタム ウォームアップ サーブレットに高コストのロジックを含めることで、読み込みリクエストでの読み込み時間の増加を回避できます。
カスタム ウォームアップ サーブレットを作成するには、web.xml
で _ah_warmup
の組み込みサーブレット定義をオーバーライドします。
<servlet>
<servlet-name>_ah_warmup</servlet-name>
<servlet-class>com.company.MyWarmupServlet</servlet-class>
</servlet>