【发布时间】:2019-03-07 13:13:07
【问题描述】:
我们有什么:
- 在 docker 容器中运行的 Java 应用程序
- 未调用本机代码,未启动处理程序,未引用 DLL / .so 文件。
- JVM 参数:
-Xmx256m -XX:NativeMemoryTracking=summary - Docker 硬内存限制设置为
768m - JVM 看起来很正常(正常的 GC 周期,没有内存泄漏,没有 OOM)
- Docker 内存不断增长,直到达到硬限制 (
768m) 导致终止并重新启动容器。
问题:
- 为什么 docker stats 内存持续增长(导致每天都达到硬内存限制),尽管 JVM 似乎在其限制范围内运行。
- 对于其他微服务,我们看不到这种行为
JVM
在 JVM 方面,我们没有注意到任何特别之处:
Docker 统计输出:
492.8MiB / 768MiB 64.17%
[ec2-user@ip-10-180-28-222 ~]$ docker exec 34d7 jcmd 1 VM.native_memory summary
1:
Native Memory Tracking:
Total: reserved=1731355KB, committed=472227KB
- Java Heap (reserved=262144KB, committed=262144KB)
(mmap: reserved=262144KB, committed=262144KB)
- Class (reserved=1131805KB, committed=92829KB)
(classes #16224)
(malloc=7453KB #20996)
(mmap: reserved=1124352KB, committed=85376KB)
- Thread (reserved=29932KB, committed=29932KB)
(thread #30)
(stack: reserved=29772KB, committed=29772KB)
(malloc=94KB #151)
(arena=66KB #55)
- Code (reserved=255659KB, committed=35507KB)
(malloc=6059KB #9814)
(mmap: reserved=249600KB, committed=29448KB)
- GC (reserved=15369KB, committed=15369KB)
(malloc=5785KB #547)
(mmap: reserved=9584KB, committed=9584KB)
- Compiler (reserved=190KB, committed=190KB)
(malloc=59KB #858)
(arena=131KB #6)
- Internal (reserved=7849KB, committed=7849KB)
(malloc=7817KB #18468)
(mmap: reserved=32KB, committed=32KB)
- Symbol (reserved=20018KB, committed=20018KB)
(malloc=17325KB #175818)
(arena=2693KB #1)
- Native Memory Tracking (reserved=3558KB, committed=3558KB)
(malloc=10KB #120)
(tracking overhead=3548KB)
- Arena Chunk (reserved=4830KB, committed=4830KB)
(malloc=4830KB)
运行约20小时后
649.6MiB / 768MiB 84.59%
[ec2-user@ip-10-180-28-222 ~]$ docker exec 34d7 jcmd 1 VM.native_memory summary
1:
Native Memory Tracking:
Total: reserved=1741020KB, committed=510928KB
- Java Heap (reserved=262144KB, committed=262144KB)
(mmap: reserved=262144KB, committed=262144KB)
- Class (reserved=1138319KB, committed=100495KB)
(classes #16390)
(malloc=7823KB #30851)
(mmap: reserved=1130496KB, committed=92672KB)
- Thread (reserved=30996KB, committed=30996KB)
(thread #31)
(stack: reserved=30800KB, committed=30800KB)
(malloc=97KB #156)
(arena=99KB #57)
- Code (reserved=261330KB, committed=69062KB)
(malloc=11730KB #16047)
(mmap: reserved=249600KB, committed=57332KB)
- GC (reserved=15363KB, committed=15363KB)
(malloc=5779KB #334)
(mmap: reserved=9584KB, committed=9584KB)
- Compiler (reserved=223KB, committed=223KB)
(malloc=92KB #1246)
(arena=131KB #6)
- Internal (reserved=8358KB, committed=8358KB)
(malloc=8326KB #18561)
(mmap: reserved=32KB, committed=32KB)
- Symbol (reserved=20253KB, committed=20253KB)
(malloc=17527KB #177997)
(arena=2725KB #1)
- Native Memory Tracking (reserved=3846KB, committed=3846KB)
(malloc=10KB #127)
(tracking overhead=3836KB)
- Arena Chunk (reserved=188KB, committed=188KB)
(malloc=188KB)
观察
观察 20 小时后我们目前所知道的:
- Docker 统计数据从
492.8MiB跃升至649.6MiB - JVM 提交的本机内存从
472227KB跳转到510928KB - docker stats 和 JVM 提交的本机内存之间的差距似乎越来越大。 (
649.6MiB - 510928KB在哪里,为什么会增长) - JVM 统计数据在此期间保持正常。
所以我不知道我还能在 JVM 端调试什么。我了解 java 需要的不仅仅是堆(因此需要本机内存跟踪),但 jvm 本机内存跟踪器报告的内容与 docker stats 看到的内容之间仍有大约 150m 的差距。我怎样才能更深入地了解该内存的去向?
【问题讨论】:
-
你的 dockerfile 是什么样子的?
-
github.com/IxorTalk/ixortalk-authserver/blob/master/src/main/… 我们传递的
JAVA_OPTS是由 cloudformation 模板设置的,但我们传递的唯一内容是-Xmx256m(最近还有用于调试的-XX:NativeMemoryTracking=summary -
您可能希望将此问题交叉发布到 DevOpsSE
-
我认为这个答案stackoverflow.com/a/38670876/482811 应该可以帮助您了解差异并解决您的问题。请注意,您要检查的第一个指标是内部 Java 堆,它是 Java 应用程序使用的总内存的(通常很大)一部分。因此,确实 Java 堆大小可能总是低于您的限制,但它并没有告诉您太多其他 Java 内存使用情况:GC、堆栈、堆外映射的内存等。
-
在本机内存旁边,您可能还希望使用以下标志运行 jcmd:VM.stringtable / VM.symboltable。