阿里、蚂蚁、晟腾、中科加禾精彩分享 AI 基础设施洞见,现购票可享受 9 折优惠 |AICon 了解详情
写点什么

在容器中使用 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:106443

评论 2 条评论

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

一文带你掌握 OceanBase 社区版部署细节及原理

OceanBase 数据库

数据库 分布式数据库 oceanbase OceanBase 开源 OceanBase 社区版

立于山巅!他,凭什么抗住万亿级流量冲击!

博文视点Broadview

微服务的痛:你的微服务还好吗?

我爱娃哈哈😍

架构设计 架构设计实战

文件上传绕过思路拓展

网络安全学海

黑客 网络安全 信息安全 渗透测试 安全漏洞

如何优雅的在业务中使用设计模式(代码如诗)

小呆呆666

flutter android 大前端 设计模式

入职京东:成功拿到offer薪资30K「面试经历+面试真题」

今晚早点睡

Java 秋招

DEX去中心化交易所自动刷量机器人开发|去中心化做市机器人

Geek_23f0c3

去中心化交易所系统开发 量化交易机器人系统开发 量化机器人 做市机器人 自动刷量机器人

MySQL 不完全入门指南

Java 编程 架构 面试 架构师

论坛接口测试——Postman数据驱动(超详细小白教程)

程序员阿沐

编程 程序员 软件测试 自动化测试 接口测试

webrtc BitrateAllocator 带宽分配器

webrtc developer

WebRTC

❤️专科出身拿到阿里offer,我直呼666!【付硬核面试】❤️

编程susu

Java 编程 程序员 面试 计算机

堡垒机和跳板机的三大区别分析-行云管家

行云管家

运维 堡垒机 IT运维 跳板机

软件测试框架之——Postman参数化(超详细小白教程)

程序员阿沐

软件测试 自动化测试 接口测试

译文 | 四张画布教你判断「产品开发优先级」

LigaAI

产品经理 产品开发 画布 产品优先级

【等保测评】黑龙江等保测评机构详细信息说明

行云管家

网络安全 等保 等级保护 等保测评

简单、快捷、低成本的超写实虚拟人平台来了……

百度开发者中心

人工智能 AI 最佳实践 虚拟人 前沿技术

fil矿机1T一天可以挖多少币?fil矿机能挖多久?

fil矿机能挖多久 fil矿机1T一天可以挖多少

没有7年经验你真学不会这份SpringCloud实战演练文档

公众号_愿天堂没有BUG

Java 编程 程序员 架构 面试

华为高级技术专家多年经验分享微服务治理体系、架构及实践文档

公众号_愿天堂没有BUG

Java 编程 程序员 架构 面试

终于有大牛把Spring微服务架构设计第2版文档给整理完毕了

公众号_愿天堂没有BUG

Java 编程 程序员 架构 面试

20年IT老民工苦心编撰成超大流量分布式系统架构解决方案文档

公众号_愿天堂没有BUG

Java 编程 程序员 架构 面试

DEX去中心化交易所自动刷量机器人开发|去中心化做市机器人

量化系统19942438797

去中心化 做市机器人

fil挖矿怎么挖?fil挖矿成本是多少?

fil挖矿怎么挖 fil挖矿成本是多少

摩尔时代如何押注AI算力?英特尔战术大揭秘

科技新消息

影像篡改与识别(一):胶片时代

腾讯安全云鼎实验室

影像 暗房技术 篡改识别

石油行业数据采集中的 MQTT 协议

EMQ映云科技

数据 mqtt emq 远程监控 实时数据

简述 Linux I/O 原理及零拷贝(上)— 磁盘 I/O

Qunar技术沙龙

Linux 缓存 Mmap 磁盘 I/O

ipfs矿机公司星际联盟是什么公司?星际联盟ipfs矿机靠谱吗?

分布式存储 IPFS Filecoin ipfs挖矿 ipfs矿机

由阿里三位专家撰写:数据库高效优化:架构、规范SQL技巧文档

公众号_愿天堂没有BUG

Java 编程 程序员 架构 面试

解密优酷智能生产技术,看 AI 赋能内容数字化

阿里云视频云

音视频 短视频 视频处理 视频制作 视频云

短视频询盘获客系统开发案例解析

获客I3O6O643Z97

抖音、快手获客系统 抖音矩阵拓客

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