AWS beanstalk中的docker容器中的JVM内存设置

我在Docker容器中运行我的Java应用程序。 我使用AWS Beanstalk。 docker的基础图像是CentOS。 我在Amazon Linux AMI for Beanstalk上的EC2实例上使用4GB内存运行容器。

我应该如何configuration容器和JVM内存设置。 现在我有:

亚马逊Linux Beanstalk AMI ec2实例上的4GB

我专门为docker集装箱devise了3GB的4

{ "AWSEBDockerrunVersion": 2, "Authentication": { "Bucket": "elasticbeanstalk-us-east-1-XXXXXX", "Key": "dockercfg" }, "containerDefinitions": [ { "name": "my-service", "image": "docker-registry:/myapp1.0.2", "essential": true, "memory": 3184, "portMappings": [ { "hostPort": 80, "containerPort": 8080 } ] } } 

JVM设置是

  -Xms2560m -Xmx2560m -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 -XX:+ScavengeBeforeFullGC -XX:+CMSScavengeBeforeRemark -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./heapdump.hprof 

我可以将一个Docker容器的整个ec2实例内存分配给4GB,并将JVM设置为4GB吗?

我认为当不能分配Xmx内存参数时,JVM可能会崩溃。 如果是的话,我可以使用容器和JVM的最优值是什么?

现在,我为Amazon Linux本身留下了1GB的保证金,在容器中运行的CentOS保留了512MB。 1.5GB wasted 。 能做得更好吗?

真正的答案是非常依赖于您的Java应用程序和使用情况。

从一个3.5G的JVM堆开始。
将容器最大值设置为3.8G,以涵盖java的开销。
负载testing,反复。

Java的

-Xmx-Xms只能控制Java的堆大小,所以你不能把所有可用的内存分配给Java的堆,并期望Java和系统的其他部分运行良好(或根本)。

您还需要迎合:

堆栈: -Xss *线程数( -Xss在64位上默认为1MB)

PermGen / Metaspace: -XX:MaxPermSize默认为64MB。 Metaspace达到21MB,但可以增长。

你的应用程序也可以使用大量的共享内存,在堆外部执行JNI,依靠大型的mmaped文件来执行性能或exec外部二进制文件,或者堆外的其他任何exception。 在选定的内存级别进行一些负载testing,然后在这些级别之上和之下进行testing,以确保不会影响或接近影响性能的任何内存问题。

容器

Centos不会在容器中“运行”,docker只是为JVM进程提供一个文件系统映像来引用。 通常情况下,你不会“运行”比该容器中的java进程更多的东西。

当你在一个只有一个容器的专用主机上时,限制一个容器的最大内存并没有太大的好处,但是,如果原生Java中的某些内容耗尽了可用内存,它也不会受到影响。

这里的内存开销需要迎合上面提到的可能的本地Java使用,以及将从容器映像(而不是主机)加载并caching的jre的额外系统文件。 当你达到容器内存限制时,你也不会得到一个很好的堆栈或heapdump。

OS

一个普通的亚马逊AMI只需要大约50-60MB的内存运行加上一些备用的文件caching,所以说256MB覆盖操作系统有一定的余地。