最近同事說到Java的 ParallelGCThreads 參數,我翻了下jdk8的代碼,發現 ParallelGCThreads 的參數默認值以下:java
可是被提醒,發現即便在分配4核的容器上,GC線程數也爲38。而後就想到應該和容器的資源限制有關——jvm可能沒法覺察到當前容器的資源限制。node
翻了下代碼,發現最新版本的java是能感知容器的資源限制的,就按照jdk版本再翻了下代碼:bash
寫一個sleep 1000s的程序,而後運行:jvm
./jdk1.8.0_144/bin/java -XX:+UseG1GC -XX:+ParallelRefProcEnabled Main
複製代碼
而後查看GC線程數目:ui
$ jstack $pid | grep 'Parallel GC Threads' | wc -l
38
複製代碼
一算就知道物理機器有56個核心(8+(56-8)*5/8=38)spa
而後使用+PrintFlagsFinal看下參數:線程
$ ./jdk1.8.0_144/bin/java -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal -version | grep ParallelGCThreads
uintx ParallelGCThreads =38 {product}
複製代碼
看來jdk8u144並沒有法讀取容器配額。日誌
而後發現,從jdk 8u191版本開始,Java就能夠讀取容器配額了:code
運行一樣的程序:內存
./jre1.8.0_191/bin/java -XX:+UseG1GC -XX:+ParallelRefProcEnabled Main
複製代碼
$ jstack $pid | grep 'Parallel GC Threads' | wc -l
4
複製代碼
查看實際參數:
$ ./jre1.8.0_191/bin/java -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal -version | grep ParallelGCThreads
uintx ParallelGCThreads =4 {product}
複製代碼
另外,jdk 8u191引入了PrintContainerInfo參數:
$ ./jre1.8.0_191/bin/java -XX:+UnlockDiagnosticVMOptions -XX:+PrintContainerInfo -version
OSContainer::init: Initializing Container Support
Path to /memory.limit_in_bytes is /sys/fs/cgroup/memory/memory.limit_in_bytes
Memory Limit is: 10737418240
Path to /cpu.cfs_quota_us is /sys/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_us
CPU Quota is: 400000
Path to /cpu.cfs_period_us is /sys/fs/cgroup/cpu,cpuacct/cpu.cfs_period_us
CPU Period is: 100000
Path to /cpu.shares is /sys/fs/cgroup/cpu,cpuacct/cpu.shares
CPU Shares is: 681
CPU Quota count based on quota/period: 4
CPU Share count based on shares: 1
OSContainer::active_processor_count: 4
Path to /cpu.cfs_quota_us is /sys/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_us
CPU Quota is: 400000
Path to /cpu.cfs_period_us is /sys/fs/cgroup/cpu,cpuacct/cpu.cfs_period_us
CPU Period is: 100000
Path to /cpu.shares is /sys/fs/cgroup/cpu,cpuacct/cpu.shares
CPU Shares is: 681
CPU Quota count based on quota/period: 4
CPU Share count based on shares: 1
OSContainer::active_processor_count: 4
……
java version "1.8.0_191"
Java(TM) SE Runtime Environment (build 1.8.0_191-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.191-b12, mixed mode)
複製代碼
能夠看到,獲取的內存限制、可用CPU數目都是對的了。
結合這個日誌和代碼,咱們也能夠看到如何獲取容器配額:
首先從/proc/self/mounts中讀取對應的資源的mount位置,好比cpu就是在/sys/fs/cgroup/cpu,cpuacct:
$ cat /proc/mounts | grep -E -w '(cpu|memory)'
cgroup /sys/fs/cgroup/memory cgroup ro,nosuid,nodev,noexec,relatime,memory 0 0
cgroup /sys/fs/cgroup/cpu,cpuacct cgroup ro,nosuid,nodev,noexec,relatime,cpu,cpuacct 0 0
複製代碼
對於內存:
$ cat /sys/fs/cgroup/memory/memory.limit_in_bytes
10737418240
複製代碼
對於cpu資源:
其一,能夠經過quota/period來算:
$ cat /sys/fs/cgroup/cpu,cpuacct/cpu.cfs_period_us #單CPU總時間片配額,微秒
100000
$ cat /sys/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_us #時間片內,容器可佔用的CPU時間
400000
複製代碼
好比上面就表示分配了4核。
也能夠經過cpu.shares來獲取:
$ cat /sys/fs/cgroup/cpu,cpuacct/cpu.shares
681
複製代碼
不過這個值是cpu佔用份額,沒法根據這個算出來可用cpu數量,因此基本沒用…