在 Ubuntu 上排查与修复 Nginx 内存泄漏的实用步骤
一、快速确认与止损
top -p $(pgrep nginx | tr '\n' ',') 或 ps -o pid,rss,command -p $(pgrep nginx),按 RSS 排序,定位异常 PID。dmesg -T | grep -i 'oom\|kill' | grep <PID>,若频繁出现,说明系统内存紧张,需要先降压再查根因。proxy_cache_path ... max_size=...、client_header_buffer_size、large_client_header_buffers、proxy_buffers。nginx -s reload 平滑重启释放已分配但未回收的缓冲;必要时 systemctl restart nginx。limit_conn_zone $binary_remote_addr zone=perip:10m; limit_conn perip 20;proxy_cache off;(或调小 ssl_session_cache)。二、定位根因
pmap -x <PID>,关注是否有超大匿名映射;结合 /proc/<PID>/smaps 查看具体段与 RSS 贡献。gdb -p <PID>dump binary memory ./mem.bin 0x7fa1d0b57000 0x7FA1D0B70000ipcs -m | grep nginxgrep -r "proxy_cache\|fastcgi_cache" /etc/nginx/error_log /var/log/nginx/error.log debug;(仅在排查窗口内开启,避免日志膨胀)。load_module、include 的模块目录,逐步定位问题来源。三、常见根因与修复对照表
| 症状 | 可能原因 | 快速验证 | 修复建议 |
|---|---|---|---|
| 个别 worker RSS 持续攀升 | 第三方模块/扩展内存管理不当 | gdb 导出内存、二分禁用模块 | 升级/修复模块;必要时改用稳定版本或移除 |
| 大请求头或大 Cookie 导致占用高 | client_header_buffer_size/large_client_header_buffers 过大 |
抓包或日志统计请求头大小 | 将 client_header_buffer_size 设为 4k–16k;仅对大头部启用 large_client_header_buffers 4 16k; |
| 反向代理/静态资源缓冲过大 | proxy_buffers、proxy_buffer_size 配置偏大 |
检查配置与连接并发 | 适度下调缓冲;启用 sendfile on; tcp_nopush on; 减少用户态拷贝 |
| HTTPS 会话缓存过大 | ssl_session_cache 过大或超时过长 |
检查 ssl_session_cache 与 ssl_session_timeout |
改为 shared:SSL:20m; ssl_session_timeout 10m; |
| reload 后内存约翻倍且不回落 | glibc 延迟归还内存 | 多次 reload 观察 RSS 是否稳定为 2x | 使用 jemalloc 并在合适位置调用 mallctl("arena." STRINGIFY(MALLCTL_ARENAS_ALL) ".purge", ...);或谨慎在 master 中调用 malloc_trim(0)(需自编译) |
| 缓存/连接数过多 | proxy_cache_path max_size 过大、连接并发高 |
检查缓存命中率与连接数 | 设置合理 max_size/inactive,并限制并发连接 |
上述对照覆盖了最常见的配置与模块类问题,优先从“请求头/缓冲/缓存/SSL/第三方模块”五类入手,命中率最高。
四、修复与优化落地
client_header_buffer_size 8k; large_client_header_buffers 4 16k;proxy_buffers 8 16k; proxy_buffer_size 16k; sendfile on; tcp_nopush on;proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m;ssl_session_cache shared:SSL:20m; ssl_session_timeout 10m;mallctl("arena." STRINGIFY(MALLCTL_ARENAS_ALL) ".purge", ...);或在 master 流程中调用 malloc_trim(0)(需自编译,谨慎评估)。worker_processes auto; 与 worker_connections;必要时用 cgroups 限制 Nginx 内存上限,避免影响整机稳定性。五、验证与长期观测
wrk -t12 -c400 -d30s http://example.com/ 对比优化前后 RSS 增长曲线 与错误率。error.log debug 的排查窗口日志,定位完成后恢复常规级别,避免磁盘压力。