Java 10 牵手 Docker,新特性完美解决服务器资源分配问题
本文首发自“Docker公司”公众号(ID:docker-cn)
编译丨小东
每周一、三、五 与您不见不散!
许多运行在 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 来处理工作负载。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
linux安装jdk
本文介绍的是使用yum方式安装jdk,想要用其他方式绕行。 1.查看yum中管理的可用的JDK软件包列表: yum search java | grep -i --color JDK 结果如下图所示: image 2.选择合适版本,安装jdk,本人选择的是java-1.8.0-openjdk-devel.x86_64 yum install java-1.8.0-openjdk-devel.x86_64 3配置环境变量,打开etc文件下profile vi /etc/profile 在文件内添加 export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.71-2.b15.el7_2.x86_64 export CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar export PATH=$PATH:$JAVA_HOME/bin 保存关闭后,执行,让配置生效: source /etc/profile 然后分别输入下面命令确...
- 下一篇
[译]RabbitMQ教程C#版 - 工作队列
先决条件 本教程假定RabbitMQ已经安装,并运行在localhost标准端口(5672)。如果你使用不同的主机、端口或证书,则需要调整连接设置。 从哪里获得帮助 如果您在阅读本教程时遇到困难,可以通过邮件列表 联系我们。 工作队列 (使用.NET Client) 在第一篇教程中,我们编写了两个程序,用于从一个指定的队列发送和接收消息。在本文中,我们将创建一个工作队列,用于在多个工作线程间分发耗时的任务。 工作队列(又名:任务队列)背后的主要想法是避免立即执行资源密集型、且必须等待其完成的任务。相反的,我们把这些任务安排在稍后完成。我们可以将任务封装为消息并把它发送到队列中,在后台运行的工作进程将从队列中取出任务并最终执行。当您运行多个工作线程,这些任务将在这些工作线程之间共享。 这个概念在Web应用程序中特别有用,因为在一个HTTP请求窗口中无法处理复杂的任务。 准备 我们将略微修改上一个示例中的Send程序,以其可以在命令行发送任意消息。 这个程序将调度任务到我们的工作队列中,所以让我们把它命名为NewTask: 像 教程[1]一样,我们需要生成两个项目: dotnet new ...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Hadoop3单机部署,实现最简伪集群
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Windows10,CentOS7,CentOS8安装Nodejs环境
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- 设置Eclipse缩进为4个空格,增强代码规范
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS关闭SELinux安全模块
- CentOS7,8上快速安装Gitea,搭建Git服务器
- CentOS7,CentOS8安装Elasticsearch6.8.6