
📢 凌晨三点,刺耳的告警划破宁静! 手机疯狂震动: “Nginx虚拟机已重启!” 睡眼惺忪的我心里一沉——线上服务出事了!
火速登录监控平台,资源画像触目惊心:内存曲线像坐了火箭🚀,一路飙升直至耗尽! 紧接着Swap被榨干,磁盘IO爆表... 服务器在崩溃边缘反复横跳,最终触发了OOM Killer的重启保命机制。
这绝不是一次普通的波动,内存正在被某个“黑洞”疯狂吞噬!必须立刻揪出元凶!
atop,实时捕捉案发瞬间。

Nginx worker 进程化身“内存饕餮”,available 内存被它们一点点蚕食殆尽,最终被迫动用缓慢的 Swap,导致系统卡顿直至崩溃。• journalctl -k | grep -i 'Out of memory':内核日志铁证如山,确认是内存耗尽被OOM Killer干掉的。
• 深入Nginx error.log,发现了决定性线索:
2025/04/24 21:11:41 [emerg] ... malloc(1073741824) failed (12: Cannot allocate memory) ... while reading upstream ...
2025/04/24 21:11:41 [error] ... [subs_filter] ngx_http_subs_body_filter error ...1GB内存申请失败! 这太反常了!什么操作需要瞬间申请这么大块内存?ngx_http_subs_body_filter (属于 ngx_http_substitutions_filter_module)。这个模块负责把响应内容里的域名替换成CDN域名。access.log,化身“数据侦探”:ab 压测 (ab -n 8000 -c 200 -H 'Host: ...' ...)。mpstat 眼睁睁看着可用内存快速消失。ngx_http_substitutions_filter_module! 大胆假设:是这个第三方模块在处理特定内容(尤其是大块、无明确边界的JSON)时,发生了内存泄漏!subs_filter 相关指令,再次进行魔鬼压测...我们使用的 ngx_http_substitutions_filter_module 是第三方模块,需要重新编译Nginx集成。它在处理大型响应体(特别是流式或边界不清晰的内容如大JSON)时,存在内存管理缺陷,未能正确释放分配的内存,导致每次处理这类请求就“漏”一点,积少成多最终压垮服务器。
subs_filter。减少风险面。subs_filter_types 指令,限制只对明确需要替换的类型(如 text/html)生效。排除 application/json 等高风险类型! (这是关键!)ngx-leak)等。需Nginx编译时支持 dtrace。ngx_debug_pool 和 ngx_slab_stat 模块(需编译启用)直接分析内存池和共享内存。subs_filter_types 这样的限制指令非常重要!永远不要假设模块能智能处理所有内容类型。error.log 和内核日志 (journalctl/dmesg) 往往藏着最直接的线索。这次惊心动魄的“内存蒸发案”终于告破。一个小小的域名替换功能,竟因一个开源模块的内存泄漏,差点引发线上雪崩。运维路上,细节决定成败,对开源组件的“信任”也要保持一份警惕。
你的Nginx配置里,有没有藏着类似的“定时炸弹”呢?🤔 不妨检查一下那些第三方模块的使用姿势吧!
你在排查内存泄漏方面有什么独门秘籍或踩坑经历?欢迎留言分享交流!