小编Gra*_*ath的帖子

容器中的JVM错误地计算处理器?

我最近再次进行了一些研究,并偶然发现了这一点。在向 OpenJDK 团队抱怨之前,我想看看其他人是否观察到了这一点,或者不同意我的结论。

因此,众所周知,JVM 长期以来一直忽略应用于 cgroup 的内存限制。众所周知,它现在将它们考虑在内,从 Java 8 开始更新某些内容,以及 9 和更高版本。不幸的是,基于 cgroup 限制所做的计算是如此无用,以至于您仍然必须手动完成所有工作。请参阅谷歌和数百篇关于此的文章。

我几天前才发现的,并且没有在这些文章中阅读任何一篇文章,是 JVM 如何检查 cgroup 中的处理器数量。处理器计数用于决定用于各种任务的线程数,包括垃圾收集。所以正确理解很重要。

在 cgroup 中(据我所知,我不是专家)您可以设置可用 cpu 时间的限制(--cpusDocker 参数)。这仅限制时间,而不限制并行性。还有 cpu 份额(--cpu-sharesDocker 参数),这是在负载下分配 cpu 时间的相对权重。Docker 将默认值设置为 1024,但这纯粹是一个相对比例。

最后,还有 cpu 集(--cpuset-cpus用于 Docker)将 cgroup 和 Docker 容器显式分配给处理器的子集。这与其他参数无关,实际上会影响并行性。

因此,在检查我的容器可以并行运行多少线程时,据我所知,只有 cpu 集是相关的。JVM 虽然忽略了这一点,而是使用 cpu 限制(如果设置),否则 cpu 共享(假设 1024 默认为绝对比例)。恕我直言,这已经很错误了。它计算可用的 CPU 时间来调整线程池的大小。

在 Kubernetes 中情况变得更糟。AFAIK 最佳实践是不设置 cpu 限制,以便集群节点具有高利用率。此外,您应该为大多数应用程序设置一个低 CPU 请求,因为它们大部分时间都处于空闲状态,并且您希望在一个节点上安排多个应用程序。Kubernetes 将请求以毫 cpu 为单位设置为 cpu 份额,最有可能在 1000m 以下。JVM 始终假设一个处理器,即使您的节点运行在某个 64 核 CPU 怪物上。

有没有人也观察过这一点?我在这里错过了什么吗?还是 JVM …

java jvm cgroups docker kubernetes

7
推荐指数
1
解决办法
2729
查看次数

标签 统计

cgroups ×1

docker ×1

java ×1

jvm ×1

kubernetes ×1