Java 10 牵手 Docker,新特性完美解决服务器资源分配问题

出品丨Docker公司(ID:docker-cn)

编译丨小东

每周一、三、五晚6点10分  与您不见不散


说在前面


许多运行在 Java 虚拟机(JVM)上的应用程序(包括像 Apache Spark 和 Kafka 这类的数据服务器和传统企业应用程序)都已经实现了在容器中运行。最近,在容器中运行 JVM 会出现内存和 CPU 用量分配有误的问题,从而导致性能下降。出现这个问题的原因是因为 Java 没有识别出它正在容器中运行。随着 Java 10 的发布,JVM 现在可以通过容器控制组(cgroups)来识别约束集。内存和 CPU 约束都可以直接在容器中管理 Java 应用程序,包含以下几点:


  • 遵守在容器中设置的内存限制;

  • 在容器中设置可用的 CPU;

  • 在容器中设置 CPU 约束;


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 周期访问是没有限制的。我们可以设置各种约束来限制容器访问主机的 CPU 周期。Java 10可以识别这些限制:


docker container run -it --cpus 2 openjdk:10-jdk

jshell> Runtime.getRuntime().availableProcessors()

$1 ==> 2


分配给 Docker EE 的所有 CPU 都获得相同比例的 CPU 周期。可以通过相对于所有其它运行中容器的权重来更改容器的 CPU 份额权重从而修改这个比例。只有当 CPU 密集型进程运行时这个比例才会启用。当在容器中的任务空闲时,其它容器可以使用剩余的 CPU 时间量。实际的 CPU 时间量取决于系统上运行的容器数量。这些可以在 Java 10中设置,如下所示:


docker container run -it --cpu-shares 2048 openjdk:10-jdk

jshell> Runtime.getRuntime().availableProcessors()

$1 ==> 2


 “cpuset”约束集就是哪些CPU允许在 Java 10中执行,如下所示:


docker run -it --cpuset-cpus="1,2,3" openjdk:10-jdk

jshell> Runtime.getRuntime().availableProcessors()

$1 ==> 3


分配内存和 CPU


有了 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 来处理工作负载。



点击下列标题,阅读更多干货



如果本文对你有帮助,欢迎分享到朋友圈!获取更多Docker实用技巧,扫描下图二维码!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值