OOM Killer是Linux内核在内存严重不足时主动终止进程的保护机制,依据oom_score评分选择占用内存多、优先级低的进程杀死,日志中显示“Killed process”即为典型特征。
服务响应超时后被系统杀掉,大概率不是服务自己“慢死”,而是被 linux 内核主动终止——最典型的就是 oom killer(out-of-memory killer)在内存严重不足时,按策略选中并干掉占用内存最多的进程。这种情况下,日志里不会出现应用层报错,而是悄无声息消失,或只留下一句“killed process”。
先确认是不是真被 OOM 杀了
别翻应用日志或 Nginx error.log,直接查内核痕迹:
- 运行 dmesg -T | grep -i "killed process",看输出里有没有你的服务名(比如 java、php-fpm、node、nginx worker)和时间戳
- 再补查系统日志:grep -i "out of memory" /var/log/syslog(Ubuntu/Debian)或 /var/log/messages(CentOS/RHEL)
- 比对这些日志的时间点,是否和你观察到服务挂掉、请求开始超时的时间一致
- 如果吻合,基本坐实是 OOM 导致——这是系统级行为,不是代码或配置问题的表象
看内存到底哪里爆了
OOM 不是凭空发生的,得找到“内存异常进程”:
- 用 ps aux --sort=-%mem | head -10 查当前内存占用 Top 10 进程,重点关注你的服务进程(比如某个 Java 进程 RSS 达到 3GB+)
- 如果是 PHP-FPM,打开状态页:curl http://127.0.0.1/status?full(需提前配置 pm.status_path),看各 worker 的 memory_usage 字段,有无个别 worker 突然飙升到几百 MB 甚至 GB 级
- 挑一个高内存 PID,深入看它的内存构成:cat /proc/PID/smaps | awk '/^Rss:/ {sum += $2} END {print sum " kB"}',再对比 Pss 行,判断是不是大量私有内存没释放(Pss 明显小于 Rss 就说明共享多,泄漏可能性低;反之则可疑)
临时止血,防止雪崩
根因修复前,必须加防护层,避免服务反复被杀、请求持续打向残缺实例:
- PHP-FPM:在 pool 配置里加 rlimit_as = 512M(限制虚拟内存上限),再设 pm.max_requests = 500(强制 worker 处理一定请求数后重启)
- Nginx:加 proxy_next_upstream error timeout http_502 http_504 和 max_fails=2 fail_timeout=15s,让上游挂掉后快速摘除
- 系统级兜底:echo 2 > /proc/sys/vm/overcommit_memory,让内核更严格评估内存申请,减少误杀
往深里挖,找泄漏源头
OOM 是结果,不是原因。得顺着进程反推代码或配置问题:
- Java 服务:用 jmap -histo:live PID 看堆内对象分布,重点盯 byte[]、String、HashMap、ArrayList 是否异常多;结合 jstack PID 看线程是否卡在 IO 或锁上
- PHP:检查是否有大文件读取后没 unset、GD 图像资源没 imagedestroy、PDO 长连接未 close、或 opcache 缓存了大量无效脚本
- Go 服务:注意是否启用了 http.DefaultClient 但没设置超时和连接池,导致连接堆积;或 goroutine 泄漏(用 pprof /debug/pprof/goroutine 查)
- 通用检查:确认 JVM 堆外内存(-XX:MaxDirectMemorySize)、Netty 的 direct buffer、或 Redis 客户端的连接池 size 是否配置过大


















