最近同事说到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数量,因此基本没用…