博客 / 詳情

返回

jvm~jvm配置與系統配置的關係

一 生產環境問題描述

keycloak是運行在jboss上面,並且部署到了容器裏,在k8s上面進行編排,現在遇到gc在某個時刻垃圾回收速度變慢,CPU接近100%,容器導致存活探針失敗,容器最後重啓

圖片

二 問題分析與解決方案

這是一個典型的 JVM GC 問題導致的容器重啓場景。讓我分析一下你的配置和可能的原因:

2.1 問題分析

根據你的 devops.yaml 配置:

              value: "-Xms1024M -Xmx1024M -XX:ConcGCThreads=13 -XX:ParallelGCThreads=13 -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC -Djboss.bind.address.management=0.0.0.0"
          resources:
            limits:
              memory: 10Gi     # 限制的內存量
              cpu: 2       # 限制的 CPU 核心數
            requests:
              cpu: 100m
              memory: 500m
          livenessProbe: #存活檢測
            failureThreshold: 2 #探測失敗的重試次數,重試一定次數後將認為失敗,在 readiness 探針中,Pod會被標記為未就緒,默認為 3,最小值為 1
            initialDelaySeconds: 120 #容器啓動後要等待多少秒後就探針開始工作,單位"秒",默認是 0 秒,最小值是 0
            periodSeconds: 10 #執行探測的時間間隔(單位是秒),默認為 10s,單位"秒",最小值是 1
            successThreshold: 1 #探針檢測失敗後認為成功的最小連接成功次數,默認為 1
            timeoutSeconds: 5 #探針執行檢測請求後,等待響應的超時時間,默認為 1s,單位"秒",最小值是 1
            httpGet:
              path: /auth
              scheme: HTTP
              port: 8080

🔴 2.2 發現的關鍵問題

1. GC 線程數配置過高

-XX:ConcGCThreads=13 -XX:ParallelGCThreads=13

問題:你配置了 13 個併發 GC 線程和 13 個並行 GC 線程,但 CPU 限制只有 2 核

  • ParallelGCThreads=13:並行 GC 階段使用 13 個線程
  • ConcGCThreads=13:併發標記階段使用 13 個線程

當 13 個線程競爭 2 個 CPU 核心時,會導致:

  • 嚴重的 CPU 上下文切換
  • GC 線程互相等待 CPU 時間片
  • GC 暫停時間變長
  • CPU 使用率飆升到 100%

推薦配置

-XX:ParallelGCThreads=2 -XX:ConcGCThreads=1

公式參考

  • ParallelGCThreads = CPU 核心數(或稍少)
  • ConcGCThreads = max(1, ParallelGCThreads / 4)

2. 堆內存設置過小

-Xms1024M -Xmx1024M

問題:Keycloak 是一個比較重的應用,1GB 堆內存可能不夠用,尤其是:

  • 用户會話多時
  • 存在大量認證請求時
  • Infinispan 緩存佔用內存

這會導致:

  • 頻繁觸發 GC
  • Full GC 增多
  • GC 時間變長

推薦:容器內存限制是 10Gi,可以適當增加堆內存:

-Xms2048M -Xmx4096M

3. 存活探針配置過於嚴格

livenessProbe:
  failureThreshold: 2      # 只允許失敗 2 次
  periodSeconds: 10        # 每 10 秒探測一次
  timeoutSeconds: 5        # 超時 5 秒

問題:當發生 Full GC 或長時間 GC 暫停時:

  • GC STW(Stop The World)可能超過 5 秒
  • 只需要 2 次失敗(20 秒內)就會重啓容器
  • 這個配置對 Java 應用過於苛刻

推薦調整

livenessProbe:
  failureThreshold: 3      # 允許 3 次失敗
  periodSeconds: 15        # 每 15 秒探測
  timeoutSeconds: 10       # 超時 10 秒

4. 缺少關鍵的 G1GC 調優參數

當前配置缺少:

  • 最大 GC 暫停時間目標
  • G1 Region 大小
  • 堆內存使用率閾值

三 優化JAVA_OPTS配置

問題-XX:+PrintGCDetails 在 Java 9+ 已被棄用,應該使用統一的 -Xlog 語法。
優化建議的完整 JAVA_OPTS

非堆內存限制

-XX:MaxMetaspaceSize=512M
-XX:MaxDirectMemorySize=512M
-XX:ReservedCodeCacheSize=256M

並行與併發配置過於保守,可根據CPU核數來配置,如4核的CPU配置如下

  • ParallelGCThreads 並行GC線程數(約為CPU核數的5/8)
  • ConcGCThreads 併發GC線程數(約為ParallelGCThreads的1/4)
-XX:+UseG1GC
-XX:ParallelGCThreads=4
-XX:ConcGCThreads=1
-XX:MaxGCPauseMillis=200

完整的JAVA_OPTS配置

- name: JAVA_OPTS
  value: >-
    -Xms10240M
    -Xmx10240M
    -XX:+UseG1GC
    -XX:ParallelGCThreads=5
    -XX:ConcGCThreads=2
    -XX:MaxGCPauseMillis=200
    -XX:G1HeapRegionSize=16M
    -XX:InitiatingHeapOccupancyPercent=45
    -XX:MaxMetaspaceSize=512M
    -XX:MaxDirectMemorySize=512M
    -XX:ReservedCodeCacheSize=256M
    -XX:+HeapDumpOnOutOfMemoryError
    -XX:HeapDumpPath=/tmp/heapdump.hprof
    -Xlog:gc*:file=/tmp/gc.log:time,uptime,level,tags
    -Djboss.bind.address.management=0.0.0.0
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.