我们在 AWS ECS 中运行 Java 微服务。因此,对于 Docker,我们使用 -Xmx 指定了一些硬 Java 堆限制。确定我们可以为堆留多少内存以及我们需要多少非堆内存(元空间、堆栈、JIT 缓存等)是一个非常棘手的部分。 目前,我们正在运行压力测试以确定我们何时拥有 Docker OOMKiller。 例如,对于 2GB AWS 任务(docker),我们可以为堆设置 -Xmx1400m 的最大值(使用 -Xmx1450m 我们没有足够的内存用于非堆内容(退出代码 137)) 实际上,Java 10+ 有“-XX:MaxRAMPercentage”,但我们仍然需要知道这个百分比。
如何确定 Java 微服务的堆/非堆大小?或者压力测试是唯一的解决方案?
最佳答案
自 Java 8u131 起,there is an option to set the JVM limits based on container memory limits .所以如果你运行类似的东西:
docker run \
-m 2g \ # set a container memory limit
openjdk:8 \
java \
-XX:+UnlockExperimentalVMOptions \
-XX:+UseCGroupMemoryLimitForHeap \
com.example.Classname
JVM 将设置堆限制,使其符合 2 GB 容器内存限制,运行 -Xmx
为你。原则上这应该安排一些事情,这样你就不会达到容器内存限制,而是得到一个 Java OutOfMemoryError
。首先。
This blog post关于该主题还有更多示例,还建议 -XX:MaxRamFraction=1
允许使用“所有内存”,你用 docker run -m
限制了它选项。
在实践中你可能会设置$JAVA_OPTS
在像这样的 Dockerfile 中
FROM openjdk:8
COPY app.jar /
ENV JAVA_OPTS=-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRamFraction=1
CMD ["java", "-jar", "/app.jar"]
然后像这样运行
docker run -d -p ... -m 2g myimage
在 Kubernetes 环境中,pod 资源约束中声明的内存限制起着相同的作用。
正如@KarolDowbecki 在他们的回答中所建议的那样,您确实需要进行一些分析和监控才能真正为此选择正确的数字。在本地运行应用程序并监控 RSS
(驻留集大小)统计在ps
或 top
应该给你一个合理的基线。
关于java - 您如何使用 Docker 确定 Java 微服务的堆/非堆大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54700816/