こんにちは、LOHACOフロント開発部の昆布です。
私が所属しているチームでは現在、一部のアプリケーションに暖機運転の仕組みを導入中です。今回はJVMにおける暖機運転の手法や効果についてご紹介したいと思います。
背景
Spring Bootベースで構築したWeb APIについて、
リリース直後のアプリケーションでレスポンス遅延が発生しやすいという課題がありました。
この事象を解消すべく暖機運転を導入してみることになりました。
なぜレスポンス遅延が起こるのか
皆さんご存知のとおりSpring Bootは複数のJVM言語をサポートするJavaの開発フレームワークですが、
JVM言語がJIT(Just In Time)コンパイラのため、初回リクエスト時にインタプリタ型の言語のようにプログラムの各行を機械語にコンパイルしながら実行されます。
この処理に要する時間が初回のレイテンシに影響が出ていると考えられます。
レスポンス遅延が発生するタイミング
レスポンス遅延が起こるタイミングについて、もう少し詳しく説明します。
私のチームが担当するアプリケーションは、Kubernetesベースの独自プラットフォーム上で動作しています。
この環境で、特にレスポンス遅延が起こりやすいタイミングは次の3つです。
- 通常のデプロイ時 (ローリングアップデートなど)
- オートスケール(スケールアウト)時
- クラッシュ後の再起時や、 Liveness Probeによる再起動
暖機運転を導入することで、これらのタイミングでのレスポンス遅延を軽減させることを狙いとしています。
JVMにおける暖機運転とは
一般的に「暖機運転」と聞くと、車がエンジン起動後にアイドリングを行うイメージが浮かびますが、JVMでの暖機運転も似たようなことを行います。
JVMはJavaアプリケーションの実行環境として機能しますが、前述したように起動直後はJITコンパイラによるコード最適化や、メモリ管理が未成熟の状態にあります。
このため、アプリケーションの起動直後に意図的に負荷をかけて慣らし、安定性を確保する手法がJVMの暖機運転(ウォームアップ)になります。
暖機運転の手法
私のチームが担当するアプリケーションの構成では、以下2つの暖機運転の手法がありました。
- KubernetesのStartup Probe機能を利用する
- Kubernetesでコンテナ起動時に任意のエンドポイントを実行する
- 暖機したいエンドポイントが少ないもの、APIのリクエストが煩雑でないものが適している
- Spring BootのなかでApplicationRunnerを定義する
- Spring Boot起動時にあらかじめ暖機運転が必要な処理を実行しておく
- 複数の処理を暖機運転する場合や、リクエストが煩雑なものが適している
今回は次の点を勘案して、1.のKubernetes側で暖機運転を導入する方法を採用しました。
- 暖機したいAPIが多くないこと
- 実装のシンプルさ
Kubernetesのヘルスチェックについて
今回暖機運転を導入するStartup Probe機能は、Kubernetesが提供するヘルスチェックの1つになります。
それぞれの監視項目を簡潔にまとめたものが次の表になります。
Startup Probeは、起動フェーズに特化した制御ができることが採用の主な理由になります。
| 名称 | 説明 |
|---|---|
| Startup Probe | コンテナの起動が完了したか、Startup Probeが成功したら、次のprobe(Readness,Liveness)に進む |
| Readness Probe | コンテナがトラフィックを受け入れる準備ができているか |
| Liveness Probe | コンテナが正常に動作しているか |
暖機運転の実装例
以下がアプリケーションのDEV環境に組み込んだ暖機運転の実装例です。
効果を説明しやすいように、暖機するAPIは1本で、/warmup(仮称)とします。
startupProbe: exec: # Warmup処理 command: - sh - -c - curl 'http://localhost:8080/warmup' > /dev/null # Spring Bootの起動を待つ秒数 initialDelaySeconds: 120 failureThreshold: 3 periodSeconds: 15 timeoutSeconds: 20
実行の流れとしては、次のようなイメージです。

検証結果
前述の暖機処理を導入した環境と暖機処理を入れる前の環境を用意して、各環境のアプリケーションを再起動します。
アプリケーションが起動したら、初回アクセスを実施します。
/warmupを暖機処理前後で比較した結果
| 実行順 | 計測対象のAPI | 暖機なし環境 | 暖機あり環境 |
|---|---|---|---|
| 1 | /warmup | 6.79s | 3.07s |
| 2 | /warmup | 826ms | 1.05ms |
バッチリ暖機できているようです。
暖機なし環境で1回目に/warmupを叩いた時よりも、暖機あり環境の方がレスポンスタイムが半分になっていることが分かります。
まとめ
Spring Bootベースで構築したWeb APIに暖機処理を導入すると、初回リクエストの遅延を緩和する効果があることが分かりました。
今回ご紹介したのはDEV環境での検証の一部になります。
実際に暖機するAPIは1つではないのですが、複数のAPIでも同様にレスポンスタイムの短縮が観測できました。
おわりに
暖機運転、絶賛導入中です!
リリース後もしっかり結果を追っていきたいと思いますので、乞うご期待ください。
ここまで読んでいただきありがとうございました。
参考資料
Kubernetes公式サイト
https://kubernetes.io/ja/docs/concepts/overview/
Liveness Probe、Readiness ProbeおよびStartup Probeの使用方法
https://kubernetes.io/ja/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/
Spring Bootにおいて、ReadnessとLivenessの概念
https://docs.spring.io/spring-boot/docs/3.2.4/reference/htmlsingle/#features.spring-application.application-availability