我在 Azure 上的 Ubuntu 16.04.4 LTS 实例上运行了一些docker swarm容器。这些容器正在运行Java Spring Boot和Netflix OSS应用程序,例如Eureka,Ribbon,Gateway等应用程序。尽管服务只是REST端点,但是我发现我的容器占用了巨大的内存。
我试图通过传递如下所示的Java VM args来限制内存消耗,但这并没有帮助大小保持不变。
请注意以下我在这里使用的配置
Java版本:Java 8 Alpine
内核版本:4.15.0-1023-azure
操作系统:Ubuntu 16.04.4 LTS
OSType:Linux
体系结构:x86_64
CPU:32
总内存:125.9GiB
docker stats
之后的内存占用量
Java VM参数,
docker service create --name xxxxxx-service --replicas 1 --network overnet 127.0.0.1:5000/xxxxxx-service --env JAVA_OPTS="-Xms16m -Xmx32m -XX:MaxMetaspaceSize=48m -XX:CompressedClassSpaceSize=8m -Xss256k -Xmn8m -XX:InitialCodeCacheSize=4m -XX:ReservedCodeCacheSize=8m -XX:MaxDirectMemorySize=16m -XX:+UseCGroupMemoryLimitForHeap -XX:-ShrinkHeapInSteps -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=70"
我也尝试查看每个容器中的应用程序日志文件,但是找不到任何与内存相关的错误。我还试图限制容器资源。但这对我也不起作用。
有什么线索可以解决此内存大问题吗?
答案 0 :(得分:1)
您可以使用诸如visualvm或jprofiler之类的探查器进行故障排除,它们将向您显示内存的分配位置(对象的类型等)。
但是,如果可能的话,您不应在生产系统上使用它,因为分析可能会占用大量CPU资源。
答案 1 :(得分:1)
了解过去我使用过的更多信息的另一种方法是使用AspectJ's load time weaving添加特殊代码,该代码将内存信息添加到日志文件中。 这也会减慢您的系统速度,但是当您编写方面时,与其说是使用配置文件,还不如说是
如果可能的话,建议进行性能分析-否则,AspectJ加载时间的编织可能会有所帮助。
答案 2 :(得分:1)
您可以尝试启用执行器,并将内存消耗值与docker stats生成的值进行比较。
要启用执行器,您可以在pom.xml文件中添加以下依赖项。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
我通常使用HAL浏览器来监视应用程序并使用执行器端点。 您可以使用以下Maven依赖项来添加它。
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-rest-hal-browser</artifactId>
</dependency>
在HAL浏览器中,您可以尝试使用应用程序的/metrics
端点。
示例输出如下所示。
{
"mem" : 193024,
"mem.free" : 87693,
"processors" : 4,
"instance.uptime" : 305027,
"uptime" : 307077,
"systemload.average" : 0.11,
"heap.committed" : 193024,
"heap.init" : 124928,
"heap.used" : 105330,
"heap" : 1764352,
"threads.peak" : 22,
"threads.daemon" : 19,
"threads" : 22,
"classes" : 5819,
"classes.loaded" : 5819,
"classes.unloaded" : 0,
"gc.ps_scavenge.count" : 7,
"gc.ps_scavenge.time" : 54,
"gc.ps_marksweep.count" : 1,
"gc.ps_marksweep.time" : 44,
"httpsessions.max" : -1,
"httpsessions.active" : 0,
"counter.status.200.root" : 1,
"gauge.response.root" : 37.0
}
这样,您可以监视应用程序的内存性能,并找出您的应用程序实际消耗了多少内存。如果这与docker生成的报告类似,则说明您的代码有问题。
但是,我必须指出,执行器的使用对生产不利,因为它本身具有大量的资源开销。