はじめに
Keycloak(RedHat Build of Keycloak)はJavaアプリケーションとして動作するため、メモリ不足で落ちる際の挙動はJava実行の引数で渡すことができます。本記事では実際にメモリ不足(Out Of Memory)を起こし、その際にヒープダンプを出力する挙動の確認を行いました。
環境情報
- Red Hat Enterprise Linux 9.3
- rhbk-24.0.5
内容確認
Keycloakを起動するkc.shでは以下の箇所でメモリー関連の値を設定しています。
if [ -z "$JAVA_OPTS_KC_HEAP" ]; then JAVA_OPTS_KC_HEAP="-XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=20" if [ "$KC_RUN_IN_CONTAINER" = "true" ]; then JAVA_OPTS_KC_HEAP="$JAVA_OPTS_KC_HEAP -XX:MaxRAMPercentage=70 -XX:MinRAMPercentage=70 -XX:InitialRAMPercentage=50" else JAVA_OPTS_KC_HEAP="$JAVA_OPTS_KC_HEAP -Xms64m -Xmx512m" fi else echo "JAVA_OPTS_KC_HEAP already set in environment; overriding default settings with values: $JAVA_OPTS_KC_HEAP" fi
メモリー不足にはXmxの値が重要で、この値にてメモリー割当てプールの最大サイズを指定します。デフォルトでは512m(512メガバイト)が最大サイズです。
ヒープを出力させる設定
以下の箇所に
JAVA_OPTS="$JAVA_OPTS $JAVA_OPTS_KC_HEAP"
「-XX」という接頭辞が付いたコマンド行である”Java HotSpot VMオプション”を追加します。
JAVA_OPTS="$JAVA_OPTS $JAVA_OPTS_KC_HEAP -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./Test"
このオプションによってメモリの割当てが不足すると、Java HotSpot VMにヒープ・ダンプを生成するよう指示します。後半は出力するパスを任意の箇所に変更できます。
実際にダンプファイルを出力させる
メモリー不足を起こすために、あえて厳しい設定に変更します。
JAVA_OPTS_KC_HEAP="$JAVA_OPTS_KC_HEAP -Xms45m -Xmx45m"
この状態で起動させ、負荷をかけるとOutOfMemoryErrorにて停止しました。
$ systemctl status keycloak
× keycloak.service - Keycloak Application Server
Loaded: loaded (/etc/systemd/system/keycloak.service; enabled; preset: disabled)
Active: failed (Result: exit-code) since ...
Duration: 2min 3.060s
Process: 3170643 ExecStart=/root/rhbk-x/bin/kc.sh start (code=exited, >
Main PID: 3170643 (code=exited, status=3)
CPU: 1min 49.016s
... kc.sh[3170643]: Terminating due to java.lang.OutOfMemoryError: Java heap spaceダンプファイルも指定された場所に以下のファイル名で出力されます。
$ file heapdump heapdump: Java HPROF dump, created ...
ちなみにメモリー不足となる直前のKeycloakのログは以下となっていました。
... WARN [io.vertx.core.impl.BlockedThreadChecker] (vertx-blocked-thread-checker) Thread Thread[vert.x-eventloop-thread-1,5,main] has been blocked for 11517 ms, time limit is 2000 ms: io.vertx.core.VertxException: Thread blocked
at io.vertx.core.net.impl.VertxHandler.create(VertxHandler.java:33)
...
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base@17.0.11/java.lang.Thread.run(Thread.java:840)
終わりに
Keycloak起動スクリプトでJavaのメモリー設定をすることで、dump fileの出力に成功しました。設定の値によっては起動した瞬間にエラーとなる場合もあるので、記事の中で指定した値を参考に試してみてください。
以上、ご参考になれば幸いです。