コンテナ内の Java アプリケーションは、不要になった後もヒープメモリを長期間保持し続けることが多く、オペレーティングシステム (OS) が他のワークロードのためにそのメモリを再利用するのを妨げます。動的ヒープメモリ最適化は、未使用のヒープメモリを定期的に OS に返すことでこの問題を解決します。これにより、アプリケーションあたりのメモリフットプリントが削減され、Container Service for Kubernetes (ACK) クラスターではノードあたりの Pod レプリカ数を増やすことができ、Serverless Kubernetes クラスターではリソースコストを削減できます。
仕組み
動的ヒープメモリ最適化を有効にすると、Enterprise Distributed Application Service (EDAS) は、G1 GC ポリシーを使用するアプリケーションに対して -XX:G1PeriodicGCInterval パラメーターを追加し、その値を 60000 (60 秒) に設定します。これにより、JVM の収集ポリシーが調整され、未使用のヒープメモリが定期的にオペレーティングシステムに返されます。
また、EDAS は初期ヒープサイズ (Xms) を 128 MB に調整し、動的最適化に利用可能なメモリ範囲を最大化します。これにより、初期ヒープサイズと最大ヒープサイズの間に大きな差が生まれ、JVM が実際の需要に基づいてヒープ使用量を増減させるための余地が確保されます。
前提条件
以下のすべての要件を満たす必要があります。そうでない場合、この機能は有効化できません。
| 要件 | 値 | 詳細 |
|---|---|---|
| JDK バージョン | Dragonwell_11_ElasticHeap | 有効化後に JDK バージョンを変更すると、この機能は自動的に無効になります。 |
| GC ポリシー | G1 | [若い世代の GC ポリシー] と [古い世代の GC ポリシー] の両方を [G1] に設定する必要があります。有効化後に GC ポリシーを変更すると、この機能は自動的に無効になります。 |
| 最大ヒープメモリ | Xmx の設定が必須 | この機能には、最大ヒープサイズを定義する必要があります。 |
| 初期ヒープメモリ | Xms < Xmx | Xms が Xmx と等しい場合、EDAS は有効化時に Xms を 128 MB にリセットします。 |
モニタリング (任意)
最適化が機能するためにモニタリングは必須ではありませんが、メモリの傾向を可視化することができます。
| サービス | 提供されるメトリクス |
|---|---|
| Application Real-Time Monitoring Service (ARMS) | ヒープメモリ使用量 と JVM メモリ使用量の傾向 |
| Managed Service for Prometheus | [Pod のメモリ使用量] |
新規アプリケーションでの有効化
EDAS コンソールにログインします。
左側のナビゲーションウィンドウで、[アプリケーション管理] > [アプリケーション] を選択します。上部のナビゲーションバーでリージョンを選択し、[マイクロサービス名前空間] ドロップダウンリストからマイクロサービス名前空間を選択し、[アプリケーションの作成] をクリックします。
[基本情報] ステップで、以下のパラメーターを設定します。
パラメーター 値 クラスタータイプ Kubernetes クラスター [アプリケーション実行環境] [Java] -- JAR パッケージ (Dubbo または Spring Boot) の場合は [Java] を選択します。このオプションを選択した後、[Java 環境] パラメーターを再設定できます。WAR パッケージ (Dubbo または Spring) の場合は [Tomcat] を選択します。このオプションを選択した後、[Java 環境] と [コンテナバージョン] パラメーターを再設定できます。 Java 環境 Dragonwell_11_ElasticHeap [監視・ガバナンスソリューション] セクションで、[統合ソリューション (デフォルト)] を選択し、[次へ] をクリックします。
[設定] ステップで、環境、基本情報、デプロイモード、リソースパラメーターを設定し、[次へ] をクリックします。
[詳細設定] ステップで、[Java 起動パラメーターの設定] の横にある [編集] をクリックします。[Java 起動パラメーターの編集] ダイアログボックスで、以下のように設定します。
[初期ヒープサイズ] と [最大ヒープメモリ] を設定します。
[Young 世代 GC ポリシー] と [Old 世代 GC ポリシー] の両方を [G1] に設定します。
[OK] をクリックします。
[動的ヒープメモリ最適化] をクリックし、[動的ヒープメモリ最適化を有効にするかどうか] をオンにします。
既存アプリケーションでの有効化
EDAS コンソールにログインします。
左側のナビゲーションウィンドウで、[アプリケーション管理] > [アプリケーション] を選択します。リージョンと名前空間を選択し、[クラスタータイプ] ドロップダウンリストから [Container Service または Serverless Kubernetes クラスター] を選択し、対象のアプリケーション名をクリックします。
[概要] または [基本情報] ページで、右上の [デプロイ] > [デプロイ] を選択します。
[デプロイモードの選択] ページで、デプロイモードを選択し、[デプロイの開始] をクリックします。
デプロイ設定ページで、以下のように設定します。
[アプリケーション実行環境] を [Java] に、[Java 環境] を Dragonwell_11_ElasticHeap に設定します。
デプロイメントパッケージを設定します。
[Java 起動パラメーターの設定] の横にある [編集] をクリックします。[Java 起動パラメーターの編集] ダイアログボックスで、[初期ヒープサイズ] と [最大ヒープメモリ] を設定し、両方の GC ポリシーを [G1] に設定して、[OK] をクリックします。
[動的ヒープメモリ最適化] をクリックして、最適化設定を表示および設定します。
機能がアクティブであることの確認
いずれかの方法を使用して、デプロイが成功し、動的ヒープメモリ最適化が有効になっていることを確認します。
変更履歴:アプリケーションの [変更履歴] ページを開きます。[実行ステータス] に [成功] と表示されていれば、機能はアクティブです。
Pod ステータス:[アプリケーション概要] ページで、[実行ステータス] の横にある Pod ステータスリンクをクリックします。[Pod] セクションの [ステータス] 列に緑色のアイコンが表示されていれば、アプリケーションが最適化を有効にして実行されていることが確認できます。
最適化結果のモニタリング
メトリクス
EDAS は、過去 15 分間のアプリケーションの動作に基づいてメモリ使用量メトリクスを計算します。
ヒープメモリ使用率 = 平均使用ヒープメモリ / 平均使用 Pod メモリ (過去 15 分間)
平均使用ヒープメモリ = 15 分間にわたって 1 分ごとに収集された JVM ヒープ使用量サンプルの平均値
平均使用 Pod メモリ = 15 分間にわたって 1 分ごとに収集された最大 Pod メモリサンプルの平均値
グラフ
最適化ダッシュボードには、過去 7 日間のメモリ傾向が表示され、1 日あたり 1 つのデータポイントが示されます。
| チャート | 表示内容 | データソース |
|---|---|---|
| [Pod メモリ使用量] | Pod レベルのメモリ消費量 | Prometheus |
| [JVM ヒープ] | アプリケーションのヒープメモリ | ARMS |
| [JVM Old Generation] | Old Generation メモリ | ARMS |
最適化パラメーターの調整
デフォルトのパラメーター調整
動的ヒープメモリ最適化を有効にすると、EDAS は自動的に以下の調整を適用します。
| 条件 | 調整 |
|---|---|
| Xmx のみが設定されている (Xms なし) | Xms は 128 MB |
| Xmx が Xms と等しい | Xms は 128 MB |
| G1 GC ポリシーがアクティブ | -XX:G1PeriodicGCInterval は 60000 (60 秒の定期的 GC 間隔) に設定されます |
カスタムパラメーター
アプリケーションのためにより多くのメモリを予約し、OS に返される量を減らすには、ヒープ空き比率パラメーターを調整します。これらをカスタム Java 起動パラメーターとして設定します。設定手順については、「Java 起動パラメーターの設定」をご参照ください。パラメーターの詳細については、「Java ドキュメント」をご参照ください。
| パラメーター | 制御内容 | デフォルト | 例 |
|---|---|---|---|
MaxHeapFreeRatio | JVM がヒープを縮小する前に許容されるアイドルヒープメモリの最大パーセンテージ | 70% (HotSpot JDK 8, 11, 17) | -XX:MaxHeapFreeRatio=80 |
MinHeapFreeRatio | JVM がヒープを拡張する前に維持するアイドルヒープメモリの最小パーセンテージ | 40% (HotSpot JDK 8, 11, 17) | -XX:MinHeapFreeRatio=50 |
MaxHeapFreeRatio を増やすと、アプリケーションはより多くのアイドル状態のヒープメモリを保持できるようになり、OS へのメモリ解放の頻度が減少します。MinHeapFreeRatio を減らすことにより、JVM は拡張をトリガーする前により少ない空きヒープで動作できるようになります。