Java プロセスのウォームアップ
最終更新日 2024年05月07日(火)
Java または JVM Web アプリケーションに対して行われる最初のリクエストは多くの場合、そのプロセスの有効期間を通した平均応答時間より大幅に遅くなります。このウォームアップ期間は通常、低速なクラスのロードと、同一のコードを実行する以降のリクエストのために JVM を最適化するジャストインタイムコンパイルが原因であると考えることができます。
その結果、多くのユーザーは JVM プロセスを使用して実際のトラフィックを処理する前に、これにいくつかの人工的なリクエストを送信すると有効であることに気が付きます。アプリケーションへの単純な一連のノーオペレーションリクエストでさえ、通常はリクエストのオーバーヘッドの大きな部分を構成する、ネットワークやスタックのメッセージング部分をウォームアップすることができます。
この記事では、Heroku でこのような動作を実装するための 1 つの方法について説明します。
アプリケーションの Preboot
ルーターがプロセスにリクエストを送信し始める前に、そのプロセスを使用して何かを実行するには、Heroku の Preboot 機能を有効にする必要があります。これにより、アプリが起動してから、実際のトラフィックを処理し始めるまでの間にある程度の時間が確保されます。
ウォームアップスクリプトの作成
Preboot が有効になっている場合は、アプリケーションと並行して実行されるスクリプトを作成し、それがアクティブな dyno のプールに移動される前にいくつかのリクエストを送信できます。
プロジェクトのルートに bin/
ディレクトリを追加し、bin/warmup
ファイルを作成します。そのファイルをお気に入りのエディタで開き、次のコードを追加します。
until $(curl -o /dev/null -s -I -f http://localhost:$PORT); do
sleep 5
done
これにより、このスクリプトは何らかのリクエストを送信する前に、メインプロセスが起動して $PORT
にバインドされるまで確実に待機するようになります。
次に、リクエストを送信するために、次のコードを追加します。
for ROUTE in $WARMUP_ROUTES; do
echo "[warmup] calling $ROUTE"
curl -L "http://localhost:$PORT$ROUTE" >/dev/null 2>&1
done
このコードは、$WARMUP_ROUTES
環境設定で定義されているルートに 1 つのリクエストを送信します。これは、次のように設定できます。
$ heroku config:set WARMUP_ROUTES="/ /hello /db"
これにより、ウォームアップリクエストが /
、/hello
、/db
の 3 つの異なるルートに送信されます。この設定をアプリケーションのルートに合わせてカスタマイズする必要があります。ユーザーによっては、ウォームアップ専用の特殊なルートを追加する場合があります。アプリケーション固有のロジックを実行する必要はありませんが、それが役立つこともあります。
ルートを選択した後、このスクリプトを Procfile
に追加する必要があります。
ウォームアップスクリプトの有効化
bin/warmup
スクリプトを使用するには、web
プロセスの既存の Procfile
コマンドを、それに sh bin/warmup &
プレフィックスを追加することによって変更します。たとえば、次のようにします。
web: sh bin/warmup & java -jar my-app.jar
これにより、ウォームアップスクリプトがバックグラウンドで、java
プロセスがフォアグラウンドで起動されます。
Windows をローカルで実行している場合は、heroku local
を実行してもこのスクリプトが動作しないことに注意してください。これは (Heroku 上のものと同様に) Linux プラットフォームに固有です。この場合は、Procfile.windows
を作成し、heroku local -f Procfile.windows
を実行してそれをコマンドに追加する必要があります。Windows Procfile には、web:
エントリの java
コマンドのみが含まれます。
これが完了したら、変更を Git に追加して再デプロイします。
$ git add bin/warmup Procfile
$ git commit -m "warmup"
$ git push heroku master
アプリは再起動すると、通常どおりに動作しますが、ログにいくつかの [warmup]
ステートメントが表示されます。これは、前に定義したルートに対応しています。
この方法で設定されたアプリケーションの完全な例は、Github 上のサンプルアプリで見つけることができます。
ウォームアップスクリプトのカスタマイズ
bin/warmup
スクリプトは Bash で記述されているため、数行のコードを記述することによってカスタマイズできます。
たとえば、ウォームアップリクエストを複数回繰り返す場合は、curl
コマンドの前後に for
ループを追加することができます。次に例を示します。
for i in {1..10}; do
curl ...
done
各ウォームアップリクエストを数百回繰り返すことも妥当ですが、通常は必要ありません。
より堅牢なウォームアップスクリプトを作成したい場合は、Bash 以外の言語を使用できます。Ruby と Python はどちらも Cedar スタックで使用でき、この目的で単純な JVM アプリを記述することもできます。
参考情報
上級ユーザーは、ジャストインタイムコンパイルがアプリケーション向けにより適切に最適化され、それによってウォームアップ時間が改善されるように JVM を設定することもできます。このための優れたリソースは、Scott Oaks による「Java Performance: The Definitive Guide」です。
Heroku の Java サポートについての詳細は、Dev Center を参照してください。