在docker里运行的java程序如何避免内存超过容器限制导致的os kill?

条件
1. docker里运行java程序,docker容器限制了内存
1. jvm的heap内存必须常驻物理内存,不能被置换
1. jvm的native、direct内存不可控,也没办法限制上限

目标:如何保证运行java程序的docker容器不会因为内存超过限制而被os kill

我的想法:
1. jvm是否有参数可以让native、direct内存通过文件映射分配,通过映射文件去和容器剩余物理内存进行置换
2. docker容器打开swap开关,但如何保证jvm的heap常驻物理内存

跪求大佬带一把,感激不尽

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 你看下这篇博客吧, 应该有用👉 :单个docker容器内启动多个java应用
  • 除此之外, 这篇博客: Docker容器内部署Java微服务的内存限制问题中的 2 基本定位 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:

    要确定 docker 容器内存超限问题的直接原因并不难。直接进入docker容器,执行 top 命令,我们发现宿主机是一台8核16G的机器,而且 docker 并不会屏蔽这些信息,也就是 JVM 会认为自己工作于一台 16G 内存的机器上。而查看 demo 服务的 Dockerfile,发现运行服务时并没有对 JVM 的内存进行任何限制,于是 JVM 会根据默认的设置来工作 —— 最大堆内存为物理内存的1/4(这里的描述并不完全准确,因为 JVM 的默认堆内存大小限制比例其实是根据物理内存有所变化的,具体内容请自行搜索资料),而基于模板创建的 ServiceStage 流水线,在部署应用堆栈的时候会把 docker 容器的内存配额默认设置为 512M,于是容器就会在启动的时候内存超限了。至于以前没有碰到过这种问题的原因,只是因为以前没将这么高规格的 ECS 服务器用于流水线部署应用堆栈。

    在查询过相关资料后,我们找到了两种问题解决方案,一个是直接在 jar 包运行命令里加上 -Xmx 参数来指定最大堆内存,不过这种方式只能将 JVM 堆内存限制为一个固定的值;另一个方法是在执行 jar 包时加上 -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap 参数,让 JVM 能够感知到docker容器所设置的 cgroup 限制,相应地调整自身的堆内存大小,不过这个特性是 JDK 8u131 以上的版本才具备的。

    最终,我们提醒 ServiceStage 流水线的同学将 CSEJavaSDK demo 的创建模板做了改进,在 Dockerfile 中将打包的基础镜像版本由原先的 java:8u111-jre-alpine 升级为了 openjdk:8u181-jdk-alpine,并且在运行服务 jar 包的命令中加上了 -Xmx256m参数。问题至此已经解决了。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^