本文共 2270 字,大约阅读时间需要 7 分钟。
本文首发自“Docker公司”公众号(ID:docker-cn)
编译丨小东每周一、三、五 与您不见不散!许多运行在 Java 虚拟机(JVM)上的应用程序(包括像 Apache Spark 和 Kafka 这类的数据服务器和传统企业应用程序)都已经实现了在容器中运行。最近,在容器中运行 JVM 会出现内存和 CPU 用量分配有误的问题,从而导致性能下降。出现这个问题的原因是因为 Java 没有识别出它正在容器中运行。随着 Java 10 的发布,JVM 现在可以通过容器控制组(cgroups)来识别约束集。内存和 CPU 约束都可以直接在容器中管理 Java 应用程序,包含以下几点:
Java 10 的改进已经在 Docker for Mac/Windows 和 Docker 企业版环境中实现。
在 Java 9之前,JVM 不能通过使用容器标签来识别内存和 CPU 的限制集。但在 Java 10中,它可以自动的识别和执行内存限制。
Java 定义了一个服务器类机器,它具有2个CPU和2GB内存,它的默认堆(heap)大小为四分之一的物理内存。举个例子,Docker EE 安装有2GB内存和4个CPU。比较它在 Java 8和 Java 10中运行容器的区别,首先来看 Java 8:
docker container run -it -m512 --entrypoint bash openjdk:latest $ docker-java-home/bin/java -XX:+PrintFlagsFinal -version | grep MaxHeapSize uintx MaxHeapSize : = 524288000 {product}openjdk version "1.8.0_162"
最大堆(heap)大小为512M或由 Docker EE安装设置的2GB的四分之一,而不是容器上限制集设置的512M。相比之下,在 Java 10上运行相同的命令显示容器中的内存限制集非常接近预期的128 M:
docker container run -it -m512M --entrypoint bash openjdk:10-jdk $ docker-java-home/bin/java -XX:+PrintFlagsFinal -version | grep MaxHeapSize size_t MaxHeapSize = 134217728 {product} {ergonomic}openjdk version "10" 2018-03-20
默认情况下,每个容器对主机的 CPU 周期访问是没有限制的。我们可以设置各种约束来限制容器访问主机的 CPU 周期。Java 10可以识别这些限制:
docker container run -it --cpus 2 openjdk:10-jdkjshell> Runtime.getRuntime().availableProcessors()$1 ==> 2
分配给 Docker EE 的所有 CPU 都获得相同比例的 CPU 周期。可以通过相对于所有其它运行中容器的权重来更改容器的 CPU 份额权重从而修改这个比例。只有当 CPU 密集型进程运行时这个比例才会启用。当在容器中的任务空闲时,其它容器可以使用剩余的 CPU 时间量。实际的 CPU 时间量取决于系统上运行的容器数量。这些可以在 Java 10中设置,如下所示:
docker container run -it --cpu-shares 2048 openjdk:10-jdkjshell> Runtime.getRuntime().availableProcessors()$1 ==> 2
“cpuset”约束集就是哪些CPU允许在 Java 10中执行,如下所示:
docker run -it --cpuset-cpus="1,2,3" openjdk:10-jdkjshell> Runtime.getRuntime().availableProcessors()$1 ==> 3
有了 Java 10,就可以使用容器设置来估计部署应用程序所需的内存和 CPU 的分配。我们假设已经确定了容器中运行的每个进程的内存堆(heap)和 CPU 需求,并设置好了 JAVA_OPTS。举个例子,如果您有一个跨10个节点分布的应用程序,其中有五个节点需要512Mb的内存,CPU 利用率权重为1024,另外五个节点需要256Mb的内存,CPU 利用率权重为512。请注意,1个CPU的份额比例由1024表示。
该应用程序至少需要分配5Gb大小的内存,如下所示:
512Mb x 5 = 2.56 Gb
256Mb x 5 = 1.28 Gb
该应用程序需要8个CPU才能有效运行,如下所示:
1024 x 5 = 5 CPUs
512 x 5 = 3 CPUs
最佳实践建议:之前的 Java 需要对应用程序进行性能分析来确定为每一个运行在 JVM 中的进程分配内存和 CPU。但是,Java 10 消除了这种分析猜测,通过容器设置来防止在 Java 应用程序中出现内存不足的错误以及分配足够的 CPU 来处理工作负载。
转载地址:http://qduoo.baihongyu.com/