JVM(更新131之前的JDK 8)在码头容器中运行,忽略了容器环境设置的CGroup限制。而且,他们是在查询主机资源,而不是向容器分配什么。结果对JVM来说是灾难性的,即当JVM试图分配比通过CGroup限制所允许的更多资源(CPU或内存)时,docker恶魔会注意到这一点,并在java程序运行pid 1时杀死JVM进程或容器本身。
内存问题解决方案- - (可能在JDK8UPDATE 131中修复),就像上面描述的那样,JVM分配的内存比容器所允许的内存要多。这可以很容易地由
-Xmx )。(在131次更新之前)-XX:+UnlockExperimentalVMOptions和
-XX:+UseCGroupMemoryLimitForHeap再次解决了(可能在JDK 212中解决)问题,运行在docker中的JVM将直接查看主机硬件并获得可用的CPU总数。然后,它将尝试访问或优化基于这个CPU计数。
docker run -ti --cpus 1 -m 1G openjdk:8u212-jdk //jvms仅限于1 1cpu。发布于 2020-10-08 22:20:51
Linux容器支持首先出现在JDK 10中,然后移植到8u191,参见JDK-8146115。
JVM的早期版本获得可用CPU的数量如下所示。
sysconf(_SC_NPROCESSORS_ONLN) libc调用。然后,glibc读取系统文件/sys/devices/system/cpu/online。因此,为了伪造可用CPU的数量,可以使用绑定安装替换该文件:
回显0-3 >/tmp/在线码头运行--cpu 4 -v /tmp/在线:/sys/设备/系统/cpu/联机.
要只设置一个CPU,请编写echo 0而不是echo 0-3。sysconf,它开始调用sched_getaffinity来查找进程的CPU关联掩码。
这打破了装订技巧。不幸的是,您不能以与sched_getaffinity相同的方式伪造sysconf。但是,可以使用sched_getaffinity替换预压的libc实现。我编写了一个小型共享库程序计数,它替换了sysconf和sched_getaffinity。因此,这个库可以用于在8u191之前的所有JDK版本中设置正确数量的可用CPU。
是如何工作的
cpu.cfs_quota_us和cpu.cfs_period_us,以确定容器是否使用--cpus选项启动。如果两者都高于零,则CPUs的数量估计为
cpu.cfs_quota_us / cpu.cfs_period_uscpu.shares并将可用CPU的数量估计为
cpu.shares / 1024
这种CPU计算类似于它在现代容器感知的JDK中的实际工作方式。sysconf和sched_getaffinity函数,以返回(1)或(2)中获得的处理器数。如何编译
gcc -O2 -fPIC -shared -olibproccount.so proccount.c -ldl如何使用
LD_PRELOAD=/path/to/libproccount.so java <args>https://stackoverflow.com/questions/64262912
复制相似问题