如何解决Linux OOM Killer 杀死似乎有足够内存的 dockerized Java 进程
我们有一个运行 Java Spring 应用程序的 docker 容器,以及运行 Postgres 和 Caddy 的其他容器。
这就是 Dockerfile 启动 Java 应用程序的方式。
ENTRYPOINT ["java","-Xmx896m","-jar","springapplication.jar"]
从 JVM 的角度来看,可用内存量似乎远非零,不会成为问题,但我们几乎每天都会看到 Linux OOM Killer 在一台或另一台机器上杀死此 Java 进程。
sudo grep /var/log/kern.log* -ie kill
/var/log/kern.log:Jun 25 11:39:50 mk kernel: [27578.725827] VM Periodic Tas invoked oom-killer: gfp_mask=0x100cca(GFP_HIGHUSER_MOVABLE),order=0,oom_score_adj=0
/var/log/kern.log:Jun 25 11:39:50 mk kernel: [27578.725862] oom_kill_process.cold+0xb/0x10
/var/log/kern.log:Jun 25 11:39:50 mk kernel: [27578.726086] oom-kill:constraint=CONSTRAINT_NONE,nodemask=(null),cpuset=06b40d3fc921f46fa21dfe5b177c62374542484788c7889227c64dc8950b5b75,mems_allowed=0,global_oom,task_memcg=/docker/06b40d3fc921f46fa21dfe5b177c62374542484788c7889227c64dc8950b5b75,task=java,pid=1330,uid=0
/var/log/kern.log:Jun 25 11:39:50 mk kernel: [27578.726224] Out of memory: Killed process 1330 (java) total-vm:2934160kB,anon-RSS:644744kB,file-RSS:0kB,shmem-RSS:0kB,UID:0 pgtables:1632kB oom_score_adj:0
Java 代码在 oom-killer 执行其操作之前不久记录了以下内容。这些值来自在 docker 容器内运行的 JVM,该容器与其他 docker 容器共享服务器。
total memory: 124145664
free memory: 25273584
used memory: 98872080
这些是具有 1GB RAM 的 Ubuntu 20.x 机器。因此,在 kern.log 中,有一件令人费解的事情,它显示了 total-vm:2934160kB。我们如何在没有交换的 1GB 机器上拥有 2.9GB 的虚拟内存?
vmstat
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
2 0 0 88032 33016 276724 0 0 15 14 111 405 2 2 95 0 0
cat /proc/meminfo
MemTotal: 1004856 kB
MemFree: 88048 kB
MemAvailable: 234212 kB
Buffers: 33216 kB
Cached: 244140 kB
SwapCached: 0 kB
Active: 666068 kB
Inactive: 119660 kB
Active(anon): 519864 kB
Inactive(anon): 8532 kB
Active(file): 146204 kB
Inactive(file): 111128 kB
Unevictable: 18564 kB
mlocked: 18564 kB
SwapTotal: 0 kB
SwapFree: 0 kB
Dirty: 100 kB
Writeback: 0 kB
AnonPages: 524940 kB
Mapped: 111680 kB
Shmem: 15836 kB
KReclaimable: 32876 kB
Slab: 81812 kB
SReclaimable: 32876 kB
SUnreclaim: 48936 kB
KernelStack: 4748 kB
PageTables: 6016 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 502428 kB
Committed_AS: 2574580 kB
VmallocTotal: 34359738367 kB
VmallocUsed: 12896 kB
VmallocChunk: 0 kB
Percpu: 604 kB
HardwareCorrupted: 0 kB
AnonHugePages: 0 kB
ShmemHugePages: 0 kB
ShmemPmdMapped: 0 kB
FileHugePages: 0 kB
FilePmdMapped: 0 kB
CmaTotal: 0 kB
CmaFree: 0 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
Hugetlb: 0 kB
DirectMap4k: 110572 kB
DirectMap2M: 937984 kB
DirectMap1G: 0 kB
这是来自一台不同的、配置相同的机器,它没有任何此类 oom-killer 事件。但是 VmallocTotal 是一个可怕的数字。那是什么意思??那只是可寻址空间,还是实际上意味着内存使用情况?
我们最近开始使用 cron 作业在凌晨 4 点重新启动所有机器,并且在不到 8 小时后发生了上述崩溃,而在类似负载下的其他十几台机器没有发生此类事件。事实上,在上周之前,没有通过 cron 定期重启,机器可以在没有任何 oom-killer 事件的情况下运行数天。
似乎典型的内存泄漏会在某种程度上一致地影响所有机器,但这不是我们所看到的。每天大约有一台机器,而且它并不总是负载最重的机器。
这让我们陷入了一个缺乏专业知识的领域,所以我们真的不知道如何确定原因然后解决问题。我们不确定是否存在 Java 内存泄漏、Java 与其 docker 容器之间的错误配置,或者与 docker 或 Linux 相关的问题。
我们不愿意启用交换,因为这是一个低延迟的应用程序,所以交换几乎和崩溃一样糟糕。
欢迎提供任何见解。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。