Docker 由于 OOM 杀死了 java 容器,但 JMX 统计数据中没有高内存使用的迹象

问题描述 投票:0回答:1

我们有一个 Docker 容器,其中包含在 AWS ECS 上运行的 Java 11 应用程序。该服务被配置为一旦使用 1.5GB RAM 就被终止

"memory": 1500,
"memoryReservation": 1137,

问题是我们没有看到仪表板中反映出内存使用量的增加 (ps:grafana 仪表板中的平线是由于 Prometheus 不再接收指标)。

我们已经做了几乎所有可能的事情来限制 Java 允许使用的堆内和堆外内存量,如果我检查 NMT 的输出,它的保留使用量最多为 1.1GB。我们现在的命令行是这样的:

java ‑Xmx600m ‑XX:+UseG1GC ‑XX:MaxMetaspaceSize=220m 
‑XX:+PrintFlagsFinal ‑XX:NewRatio=1 ‑XX:MaxDirectMemorySize=40m 
‑Xss512k ‑XX:ProfiledCodeHeapSize=70M ‑XX:NonProfiledCodeHeapSize=50M 
‑XX:NonNMethodCodeHeapSize=8M ‑XX:+UseCodeCacheFlushing 
‑XX:CompressedClassSpaceSize=32M ‑XX:ReservedCodeCacheSize=128M 
‑XX:+SegmentedCodeCache ‑javaagent:/opentelemetry‑javaagent.jar 
‑Dotel.javaagent.extensions=/opentelemetry‑java‑ecs‑extension‑all.jar 
‑Dotel.resource.attributes=xxx,aws.ecs.launchtype=ec2 
‑XX:NativeMemoryTracking=summary ‑XX:‑OmitStackTraceInFastThrow 
‑Dspring.profiles.active=prd‑ecs ‑Dspring.cloud.consul.host=172.17.42.1 
‑Dspring.cloud.consul.config.watch.enabled=false 
‑Dcom.sun.management.jmxremote.port=9999 
‑Dcom.sun.management.jmxremote.authenticate=false 
‑Dcom.sun.management.jmxremote.ssl=false 
‑Dlog4j2.formatMsgNoLookups=true ‑Dserver.port=8080 
‑Daws.paramstore.enabled=true 
‑Daws.paramstore.region=eu‑west‑1 
‑Dspring.main.banner‑mode=off ‑jar /1234‑service.jar 

我们对我们的容器如何可能突然使用 400MB 内存而 JMX 指标中没有任何迹象表示一无所知。

//编辑:最早运行的容器的 NMT 的输出

Native Memory Tracking:

Total: reserved=1180115KB, committed=700171KB
-                 Java Heap (reserved=614400KB, committed=260096KB)
                            (mmap: reserved=614400KB, committed=260096KB)

-                     Class (reserved=215344KB, committed=208080KB)
                            (classes #35567)
                            (  instance classes #33401, array classes #2166)
                            (malloc=8496KB #125896)
                            (mmap: reserved=206848KB, committed=199584KB)
                            (  Metadata:   )
                            (    reserved=174080KB, committed=173536KB)
                            (    used=167363KB)
                            (    free=6173KB)
                            (    waste=0KB =0.00%)
                            (  Class space:)
                            (    reserved=32768KB, committed=26048KB)
                            (    used=22342KB)
                            (    free=3706KB)
                            (    waste=0KB =0.00%)

-                    Thread (reserved=77858KB, committed=16034KB)
                            (thread #125)
                            (stack: reserved=77260KB, committed=15436KB)
                            (malloc=452KB #752)
                            (arena=146KB #249)

-                      Code (reserved=139426KB, committed=96022KB)
                            (malloc=7330KB #29103)
                            (mmap: reserved=132096KB, committed=88692KB)

-                        GC (reserved=70010KB, committed=56862KB)
                            (malloc=14362KB #61984)
                            (mmap: reserved=55648KB, committed=42500KB)

-                  Compiler (reserved=896KB, committed=896KB)
                            (malloc=764KB #2798)
                            (arena=133KB #5)

-                  Internal (reserved=4509KB, committed=4509KB)
                            (malloc=4477KB #3670)
                            (mmap: reserved=32KB, committed=32KB)

-                     Other (reserved=4359KB, committed=4359KB)
                            (malloc=4359KB #39)

-                    Symbol (reserved=37775KB, committed=37775KB)
                            (malloc=34219KB #439593)
                            (arena=3556KB #1)

-    Native Memory Tracking (reserved=10765KB, committed=10765KB)
                            (malloc=34KB #437)
                            (tracking overhead=10731KB)

-               Arena Chunk (reserved=190KB, committed=190KB)
                            (malloc=190KB)

-                   Logging (reserved=4KB, committed=4KB)
                            (malloc=4KB #194)

-                 Arguments (reserved=20KB, committed=20KB)
                            (malloc=20KB #545)

-                    Module (reserved=3692KB, committed=3692KB)
                            (malloc=3692KB #14082)

-              Synchronizer (reserved=860KB, committed=860KB)
                            (malloc=860KB #7286)

-                 Safepoint (reserved=8KB, committed=8KB)
                            (mmap: reserved=8KB, committed=8KB)

//edit2:我们在 90 多个 Docker 服务上使用的 Docker 镜像

FROM --platform=$TARGETPLATFORM amazoncorretto:11

RUN yum install -y shadow-utils wget && yum clean all
RUN wget https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar -O /opentelemetry-javaagent.jar
ADD opentelemetry-java-ecs-extension-*-all.jar /opentelemetry-java-ecs-extension-all.jar
RUN adduser docker
RUN if [ -f $JAVA_HOME/conf/security/java.security ]; then sed -i 's/^networkaddress.cache.ttl/#networkaddress.cache.ttl/g' $JAVA_HOME/conf/security/java.security; fi && \
    echo "networkaddress.cache.ttl=30" >> $JAVA_HOME/conf/security/java.security

USER docker

//edit3:忘记提及我们还设置了这个环境变量

            {
                "name": "MALLOC_ARENA_MAX",
                "value": "4"
            }
java docker out-of-memory heap-memory
1个回答
0
投票

Java 不太擅长管理 RAM 资源作为限制。 Java 始于 PC 世界,那里有 RAM 和 SWAP 内存,因此每当您调整这些值时,都是为了使其尽可能保持最佳运行状态。

当docker出现时,java应用程序开始面临一个新问题,没有更多的SWAP可以使用,现在java能够看到的可用内存(主机)与docker分配的内存不相等一个极限。

例如,您的 Java 应用程序可能报告使用 1.1Gb RAM,但是当您为任务定义分配 1.5Gb RAM 时,这并不是 JAVA 本身能够看到的。如果您能够 ssh 进入容器,您将能够看到它报告的 RAM 是运行任务的主机容器实例。假设您有一个带有 2 个 CPU 和 2 GB RAM 的 t4g.small 运行您的任务。这意味着 Java 将遇到这些限制,并且某些组件的计算可能会超过该限制。从那里您需要考虑任何其他进程内存,如操作系统、网络、根进程、内部日志记录等。

您的 Cloudwatch 仪表板实际上显示了所有这些组件作为一个整体的真实使用情况,而您的 JAVA 仪表板仅报告其监控的选定组件。所以你不知道还有什么在消耗内存。

注意:另请记住,本机内存跟踪无法查看所有与 java 相关的内存使用情况。它确实有助于了解内存的主要使用方式,以便您可以改进设置,但只是一个近似的猜测,而不是真正的消耗。

建议:在容器化环境中使用 Java 应用程序时,最好留出更多空间来开始跟踪历史数据。就像给它一个月 8Gb 的内存一样,了解您的应用程序的行为并进行相应的优化。然后,让您的历史数据提示您限制应该在哪里。不要先设置一个小限制,然后尝试让你的 java 应用程序表现得更好。

© www.soinside.com 2019 - 2024. All rights reserved.