容器中 Java 应用程序的内存和 CPU 如何分配?看这一篇就够了!

简介: 随着2018年的结束,我们将回顾排名前五的最受读者欢迎的文章。今天分享的第一篇文章,将帮助那些在容器中运行 Java 虚拟机(JVM)时遇到内存和 CPU 大小调整/使用困难的人,本文将解释如何在 Docker Desktop(Mac或Windows)和 Docker Enterprise 环境中改进 Docker 容器与 Java 10的集成。

screenshot

出品丨Docker公司(ID:docker-cn)
编译丨小东
每周一、三、五,与您不见不散!


随着2018年的结束,我们将回顾排名前五的最受读者欢迎的文章。今天分享的第一篇文章,将帮助那些在容器中运行 Java 虚拟机(JVM)时遇到内存和 CPU 大小调整/使用困难的人,本文将解释如何在 Docker Desktop(Mac或Windows)和 Docker Enterprise 环境中改进 Docker 容器与 Java 10的集成。


许多应用程序都以容器的形式运行在 Java 虚拟机(JVM)中,其中包括 Apache Spark 和 Kafka 等数据服务以及旧的企业级应用程序。直到最近,在容器中运行 Java 虚拟机会出现内存和cpu大小以及使用方面的问题,从而导致性能损失。这是因为 Java 没有识别到它是在容器中运行的。随着 Java 10的发布,Java 虚拟机现在可以识别容器控制组(cgroups)设置的约束。内存和 cpu 约束都可以用于直接在容器中管理 Java 应用程序,包括:

  • 遵守容器中设置的内存限制;
  • 在容器中设置可用的 cpu;
  • 在容器中设置 cpu 约束;

Docker Desktop(Mac 或 Windows)和 Docker Enterprise 环境都实现了 Java 10的改进。


容器内存限制

在 Java 9之前,Java 虚拟机无法识别容器使用标记设置的内存或CPU限制。在Java 10中,内存限制将自动进行识别并强制执行。

Java 将服务器类机器定义为具有2个 CPU 和 2GB 内存,默认堆大小为物理内存的1/4。 例如,Docker Enterprise Edition 安装有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"

最大堆大小为 512M 或 Docker EE 安装设置的 2GB 的1/4,而不是容器上设置的限制为512M。 相比之下,在 Java 10上运行相同的命令表明容器中设置的内存限制非常接近预期的128M:

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 分配。假设已经确定了容器中运行的每个进程的内存堆和 CPU 需求,并设置了 JAVA_OPTS。例如,如果您的应用程序分布在10个节点上,五个节点需要512Mb内存,每个节点占用 1024 CPU,另外五个节点需要256Mb内存,每个节点占用 512 CPU共享。请注意,1个CPU份额比例由 1024 表示。

对于内存,应用程序至少需要分配 5Gb 内存。

  • 512Mb x 5 = 2.56 Gb
  • 256Mb x 5 = 1.28 Gb

对于 CPU,应用程序需要分配8个CPU才能高效运行。

  • 1024 x 5 = 5 CPUs
  • 512 x 5 = 3 CPUs

最佳实践建议:分析应用程序以确定 Java 虚拟机中运行的每个进程的内存和 CPU 分配。无论如何,Java 10在调整容器大小时消除了猜测,预防了 Java 应用程序中的内存不足错误以及保障了分配足够的 CPU 来处理工作负载。

相关文章
存储 jenkins 持续交付
1148 2
|
UED 容器
10.HarmonyOS Next布局进阶:嵌套Flex容器与空间分配策略
在HarmonyOS Next的ArkUI框架中,Flex布局是构建用户界面的核心技术之一。通过嵌套使用Flex容器,我们可以创建复杂而灵活的界面结构,满足各种应用场景的需求。本教程将深入探讨如何在HarmonyOS Next中使用嵌套Flex容器实现复杂布局,以及如何合理分配和控制空间。
479 0
|
监控 Java 中间件
8G的容器Java堆才4G怎么就OOM了?
本文记录最近一例Java应用OOM问题的排查过程,希望可以给遇到类似问题的同学提供参考。
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
820 1
|
存储 C语言
C语言如何使用结构体和指针来操作动态分配的内存
在C语言中,通过定义结构体并使用指向该结构体的指针,可以对动态分配的内存进行操作。首先利用 `malloc` 或 `calloc` 分配内存,然后通过指针访问和修改结构体成员,最后用 `free` 释放内存,实现资源的有效管理。
2272 13
|
SQL 安全 Java
安全问题已经成为软件开发中不可忽视的重要议题。对于使用Java语言开发的应用程序来说,安全性更是至关重要
在当今网络环境下,Java应用的安全性至关重要。本文深入探讨了Java安全编程的最佳实践,包括代码审查、输入验证、输出编码、访问控制和加密技术等,帮助开发者构建安全可靠的应用。通过掌握相关技术和工具,开发者可以有效防范安全威胁,确保应用的安全性。
331 4
|
存储 缓存 Java
结构体和类在内存管理方面的差异对程序性能有何影响?
【10月更文挑战第30天】结构体和类在内存管理方面的差异对程序性能有着重要的影响。在实际编程中,需要根据具体的应用场景和性能要求,合理地选择使用结构体或类,以优化程序的性能和内存使用效率。
|
安全 Java 编译器
Java对象一定分配在堆上吗?
本文探讨了Java对象的内存分配问题,重点介绍了JVM的逃逸分析技术及其优化策略。逃逸分析能判断对象是否会在作用域外被访问,从而决定对象是否需要分配到堆上。文章详细讲解了栈上分配、标量替换和同步消除三种优化策略,并通过示例代码说明了这些技术的应用场景。
452 4
Java对象一定分配在堆上吗?
|
NoSQL 测试技术
内存程序崩溃
【10月更文挑战第13天】
669 62
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
1464 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS