我在春季启动中创建了一些服务,我有11个胖jar,并将它们部署在docker容器中,我的怀疑是每个jar都消耗了1到1.5 GB的RAM,而没有任何使用,我通过运行来检查RAM :
docker stats containername
起初,我以为是Java容器,所以我尝试更改为使用alpine的容器,但没有任何变化,所以我认为唯一的问题是我的jar。有没有办法更改jar正在使用的RAM?还是这种行为是正常的,因为每个jar都有一个嵌入式的tomcat?或者将一些罐子放在一起作为战争来部署,并在一组“罐子”中仅使用一个tomcat更好?有人可以分享他/她的经验吗?,
谢谢。
答案 0 :(得分:3)
这是Java总体上的行为方式。 JVM会占用您所提供的尽可能多的内存,并且它会执行名为垃圾收集(What is the garbage collector in Java)的过程,以决定释放空间。
但是,如果您不告诉JVM它可以使用多少内存,它将使用系统默认值,该默认值取决于系统内存和所拥有的内核数量。您可以使用以下命令(How is the default Java heap size determined)进行验证:
java -XX:+PrintFlagsFinal -version | grep HeapSize
在我的机器上,那是256MiB的初始堆内存,最大堆大小是4GiB。但是,这并不意味着您的应用程序需要它。
一种测量内存的好方法是使用监视工具(如jvisualvm)。此外,您还可以使用执行器的/health
端点来查看堆内存使用情况。
您的堆内存使用情况通常具有锯齿模式(Why a sawtooth shaped graph),在该模式中逐渐使用内存,并最终由垃圾收集器释放内存。
垃圾回收后剩余的内存通常是无法销毁的对象,因为它们仍在使用中。您可以将其视为您的工作记忆。现在,要配置-Xmx
,您必须在试用后查看应用程序的行为:
OutOfMemoryError
。从上面的屏幕截图中,您可以看到我的应用程序为堆使用保留了大约1GiB的内存,而在垃圾回收后仅使用了大约30MiB。这意味着它的-Xmx
值太高了,因此我们可以将其更改为不同的值,并查看应用程序的行为。
人们通常更喜欢以2的幂进行工作(即使没有限制,如jvm heap setting pattern所示)。就我而言,我需要至少使用30MiB,因为那是我的应用程序始终使用的内存量。因此,这意味着我可以尝试-Xmx32m
,查看其性能,并调整它是否耗尽内存或性能更差。
答案 1 :(得分:2)
您可以使用-e JAVA_OPTS="-Xmx64M -Xms64M"
设置docker容器的内存使用情况。
docker文件:
FROM openjdk:8-jre-alpine
VOLUME ./mysql:/var/lib/mysql
ADD /build/libs/application.jar app.jar
ENTRYPOINT exec java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar
图像运行:
docker run -d --name container-name -p 9100:9100 -e JAVA_OPTS="-Xmx512M -Xms512M" imagename:tag
在这里,我设置了512Mb的内存使用率。您可以设置1g或根据您的要求。使用此命令运行后,检查您的内存使用情况。最高可达512Mb。
答案 2 :(得分:1)
看过openjkd DockerHub image documentation后,似乎可以通过设置-XX:MaxRAM=...
来设置默认堆大小:
Windows Server容器支持RAM限制,但是当前JVM 无法检测到。为了防止过多的内存分配, -XX:MaxRAM = ...选项的值必须不大于容器RAM限制。
来自oracle docs:
默认堆大小除非在命令行上指定了初始堆大小和最大堆大小,否则它们将根据数量进行计算 机器上的内存。