Spring Boot占用过多RAM

时间:2018-08-09 13:22:19

标签: docker spring-boot

我在春季启动中创建了一些服务,我有11个胖jar,并将它们部署在docker容器中,我的怀疑是每个jar都消耗了1到1.5 GB的RAM,而没有任何使用,我通过运行来检查RAM :

docker stats containername

起初,我以为是Java容器,所以我尝试更改为使用alpine的容器,但没有任何变化,所以我认为唯一的问题是我的jar。有没有办法更改jar正在使用的RAM?还是这种行为是正常的,因为每个jar都有一个嵌入式的tomcat?或者将一些罐子放在一起作为战争来部署,并在一组“罐子”中仅使用一个tomcat更好?有人可以分享他/她的经验吗?,

谢谢。

3 个答案:

答案 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),在该模式中逐渐使用内存,并最终由垃圾收集器释放内存。

Example of JVisualVM

垃圾回收后剩余的内存通常是无法销毁的对象,因为它们仍在使用中。您可以将其视为您的工作记忆。现在,要配置-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

  

默认堆大小除非在命令行上指定了初始堆大小和最大堆大小,否则它们将根据数量进行计算   机器上的内存。