阿里云飞天发布时刻,领先大模型限免,超7000万 tokens免费体验 了解详情
写点什么

在容器中使用 Java 的资源分配准则

  • 2019-11-19
  • 本文字数:2538 字

    阅读完需:约 8 分钟

在容器中使用Java的资源分配准则

短短几年,容器就改变了软件行业的开发模式。也许,很多开发者已经开始在容器中运行 Java 应用。但是,对于容器化的 Java 应用程序,当遇到 CPU 和内存占用等问题时,还是有很多问题需要注意。本文假设读者对 Java 和容器技术有基本了解,如果需要更多背景知识,可以阅读文末的参考文献。


堆空间

如果说在容器中运行 Java 应用有一条核心定律,那么就是:对于在容器中运行的 Java 进程,不要手工设置 JVM 堆内存。相反的,设置容器的限制。

为什么?

首先,设置容器的限制可以实现容器/cgroup 提供的基本功能,既隔离容器内进程的资源使用。当我们通过 JVM 参数手工设置堆内存的时候,就意味着彻底无视这个功能。这样能够方便的调整容器资源分配,为自动化扩缩容容器(例如 K8s 垂直 pod 自动扩缩容)打开了大门,而无需手工调整 JVM 参数。


如果容器运行在编排引擎环境中(例如 Kubernetes),那么容器的限制对于节点健康度和调度都非常重要。调度器需要使用这些限制来找到适合容器运行的节点,同时确保节点之间负载均衡。如果通过 JVM 参数设置内存使用,这个信息无法通知到调度器,因此调度器无法知道如何为容器分配负载。


如果不设置容器限制,同时运行在容器中的 Java 进程也没有显式设置 JVM 内存参数,那么 JVM 将会自动设置最大堆内存为运行节点总内存的 25%。例如,如果容器运行在一个内存为 64GB 的节点上,JVM 进程堆内存最大可设置成 16GB。如果这个节点上运行了 10 个容器(对于自动扩缩容经常发生),那么可能会突然需要 160G 内存。

我们能做什么?

设置容器内存(和 CPU)限制,依赖资源请求(软限制)是不够的。资源请求对调度器非常有用,但是设置硬限制让 Docker(或者其他容器运行时环境)为容器分配指定资源,同时确保不会超出。这也让 Java(在 Java 8u191 之后,默认提供“容器感知”功能)基于容器设置的资源限制自动分配内存,而不是通过运行节点分配。

关于[Min|Max|Initial]RAMPercentage 参数

最近的Java版本中,引入了如下 JVM 参数(同时向后移植到了 Java 8u191):


  • -XX:MinRAMPercentage

  • -XX:MaxRAMPercentage

  • -XX:InitialRAMPercentage


本文不会详细介绍这些参数如何工作,但是关键点是这些参数可以在不需要直接设置堆内存大小的情况下用于调优 JVM 堆大小。也就是说,容器仍然可以依赖对其设置的资源限制。


那么,这些参数的值该怎么设置呢?答案是:看情况,尤其是依赖于容器上设置的资源限制。


默认设置下,JVM 堆内存会设置成容器内存的 25%。我们可以通过这些参数来修改初始、最小、最大堆内存。例如,设置-XX:MaxRAMPercentage=50 将会允许 JVM 将容器内存的 50%作为堆内存使用,而不是默认的 25%。这样设置是否安全主要取决于容器运行的内存以及容器内的进程情况。


例如,假设容器只运行一个 Java 进程,分配了 4GB 内存,而我们设置了-XX:MaxRAMPercentage=50,此时 JVM 堆内存上限是 2GB。这与默认情况下只能使用 1GB 内存不同。在这种情况下,50%基本上是非常安全的,也许也是最佳的,因为还有许多可用内存实际利用率都不高。相反,假设相同的容器只分配了 512MB 内存,现在设置了-XX:MaxRAMPercentage=50 之后,堆内存会占用 256MB 内存,而对于容器剩下的所有可用内存就只有 256MB 了。这些内存需要被容器中运行的其他进程共享,同时还有 JVM 的 Metaspace/PermGen 等其他内存使用。因此在这种场景下,50%可能不太安全。


这里提供如下建议:


  • 除非想为 Java 进程压榨额外内存,否则不要修改这些参数。在大部分情况下默认值 25%对于内存管理来说是比较安全的。这个设置对内存来说可能并不是最有效的,但是内存是相对廉价的,同时相比于 JVM 进程在未知情况下被 OOM-kill,还是谨慎一些比较好。

  • 如果非要调试这些参数,还是保守点为妙。50%通常是个安全值,可以避免(大部分)问题。当然,这还是主要取决于容器内存大小。我不推荐设置成 75%,除非容器至少有 512MB 内存(最好是 1GB),同时需要对应用程序的实际内存使用非常了解。

  • 如果容器内除了 Java 进程之外还有其他进程,那么在调整这些值的时候需要额外的注意。容器内存由其中所有进程共享,因此在这种情况下,了解整个容器内存使用会更加复杂。

  • 设置成超过 90%可能是在自找麻烦。

对于 Metaspace/PermGen/其他内存呢?

这已经超出了本文的范围,不过这些也可以调整,通常情况下最好不要。大多数情况下,JVM 默认行为已经很好了。如果你发现自己正试图解决一个晦涩的内存问题,那么可能需要研究一下 JVM 内存这个深奥的领域。其他情况,我尽可能避免直接去修改。

对于 CPU

对于 CPU 没有什么可做的。从 Java 8u191 开始,JVM 默认情况下已经实现“感知容器”,能够正确解析 CPU 共享(CPU Share)设置。这里有一些细节需要理解,因此我直接附上一篇不错的文章,详细介绍相关知识,就不在本文中概述。

总结

现代的 Java 已经为容器环境做好了准备,但是为了应用程序能够有更好的性能,其中有一些不是那么明显的细节需要我们了解。我希望本文提供的信息,加上优秀的参考文献,可以帮助读者达到这个目的。


参考文献



附录:


在 64GB/16GB JVM 例子中,这里并不是说 JVM 进程会为堆内存自动消费 16GB 内存,只是说在内存溢出之前,堆内存可以增长到那么大。另外,由于设置的最大堆内存还有很多,对于垃圾回收器来说没有压力,堆内存很容易在触发垃圾回收之前,消耗多余容器实际可以提供的内存。这必然会引起应用程序问题(例如 OOM 错误),甚至更严重的错误(例如被 OOM kill,崩溃)。


原文链接:


https://www.ccampo.me/java/docker/containers/kubernetes/2019/10/31/java-in-a-container.html


2019-11-19 14:106983

评论 2 条评论

发布
用户头像
针对-XX:MaxRAMPercentage设置比例这块,作者太武断了,JAVA应用本来都很吃内存,生产环境一般是1G-2G的内存limit限制,-XX:MaxRAMPercentage设置成 75% 是公认的比较合理的值。
2021-08-31 19:21
回复
用户头像
需要容器化部署
2019-11-27 17:26
回复
没有更多了
发现更多内容

大数据培训后找不到工作的原因有哪些?

小谷哥

荣耀MagicOS 7.0正式发布!打造以人为中心的智慧生活解决方案

荣耀开发者服务平台

手机 系统 安卓 荣耀 honor

高级Java面试经验总结:多家大厂简历优化+面试题目+面经+薪酬等

钟奕礼

Java 程序员 java面试 java编程

我说用count(*)统计行数,面试官让我回去等消息...

小小怪下士

Java sql 程序员

存算一体 VS 存算分离 ,IT发展下的技术迭代

StoneDB

数据库 开源 存算分离 HTAP StoneDB

开源大数据热力报告:StarRocks摘得数据查询与分析方向增速第一

StarRocks

数据库

AirServer2023个人免费版本下载

茶色酒

AirServer2023

Camtasia2023全新版下载及功能介绍讲解

茶色酒

Camtasia2023

有位大牛终于把珍藏多年的算法视频给分享出来了,总共3.81G

小二,上酒上酒

算法 数据结构与算法 左程云

前端培训学习的前景怎么样

小谷哥

技术分享| 快对讲视频调度功能说明

anyRTC开发者

监控 快对讲 语音对讲 视频对讲 视频回传

最佳实践|用腾讯云AI文字识别对混贴票据识别

牵着蜗牛去散步

人工智能 腾讯云 腾讯 文字识别 OCR

想要做好代码质量,如何破局?

京东科技开发者

代码质量 系统 代码优化

支持向量机-线性SVM决策过程的可视化

烧灯续昼2002

Python 机器学习 算法 sklearn 11月月更

前端培训机构需要注意什么?

小谷哥

听说,清华毕业大牛分享出Redis实战视频及文档,共2.3G

小二,上酒上酒

Java redis 学习路线

java培训学习有什么好的方法

小谷哥

异常检测算法分类总结(含常用开源数据集)

云智慧AIOps社区

人工智能 机器学习 深度学习 异常检测 算法模型

既快又稳还方便,火山引擎VeDI的这款产品解了分析师的愁

字节跳动数据平台

大数据 数据分析

「案例分享」研发效能提升之第一性原理

京东科技开发者

redis flink 研发管理 研发效能 软件开发技术的第一性原理

融云全球社交泛娱乐洞察,互联网社交换挡期的「社区产品」机遇

融云 RongCloud

社交 社区

2023最新FL Studio中文版64位安装包下载教程

茶色酒

FL Studio FL Studio 21

新发现,新挑战,技术出海的机遇与挑战丨PingCAP DevCon 2022 出海专场

PingCAP

出海

膜拜!华为18级工程师用349页构建高可用Linux服务器,其实并不难

小二,上酒上酒

Java Linux 学习 华为 运维

MySQL的存储引擎及常用数据类型详解

C++后台开发

MySQL 数据库 中间件 后端开发 C++开发

AI赋能音乐创作,人人都是音视频创作者

HarmonyOS SDK

HMS Core

云原生加速器企业维格表创始人陈霈霖:提供人人可用的数字化转型全新方案,真正驱动组织创新

阿里巴巴云原生

阿里云 云原生 维格表

前端培训程序员失业后就业方向有哪些

小谷哥

上班干,下班学!这份 Java 面试八股文涵盖 20 多个技术点

钟奕礼

Java 程序员 java面试 java编程

Tiktok短视频搬运运营干货技巧

极客天地

数字化安全生产平台 DPS 重磅发布

阿里巴巴云原生

阿里云 云原生 数字化

在容器中使用Java的资源分配准则_服务革新_Christopher Campo_InfoQ精选文章