Ubuntu 下优化 Nginx 内存使用的实用方案
一 基线评估与定位
- 观察进程真实占用:使用命令查看 RSS(实际物理内存)与整体占用,例如:top -p $(pgrep nginx | tr ‘\n’ ‘,’) 或 ps -o pid,rss,command -p $(pgrep nginx);对单个 worker 用 pmap -x | tail -n 10 查看内存映射分布。定位是否为 worker 数量过多、缓存占用或异常增长。
- 检查共享内存与缓存:用 ipcs -m | grep nginx 查看共享内存段;grep -r “proxy_cache” /etc/nginx/ 检查是否启用 proxy_cache/fastcgi_cache 及其路径与大小。
- 快速核对高风险配置:关注请求头/体缓冲与上传限制,例如 large_client_header_buffers 4 16k;(每个请求可能占用 64KB)、proxy_buffers 8 16k;(每连接可能占用 128KB)、以及 client_max_body_size。
- 日志与监控:tail -f /var/log/nginx/error.log | grep -i “memory” 观察异常;结合 Prometheus + Grafana 持续采集 worker 内存、缓存命中率等指标,便于回放与对比调优前后差异。
二 Nginx 配置优化要点
- 进程与连接
- 将 worker_processes 设为 auto(或 CPU 核心数),避免无谓的 worker 膨胀。
- 合理设置 worker_connections,并用“最大连接数 ≈ worker_processes × worker_connections”校核系统资源与并发目标。
- 请求头与请求体缓冲
- 将 client_header_buffer_size 设为 4k;large_client_header_buffers 4 8k;client_body_buffer_size 16k(按业务适当放大/缩小)。
- 限制上传大小:例如 client_max_body_size 10m,防止超大请求体导致内存激增。
- 代理缓冲
- 按需收紧:proxy_buffer_size 4k; proxy_buffers 8 16k; proxy_busy_buffers_size 32k;,避免为每个连接预分配过多缓冲。
- 长连接与传输
- 适度缩短 keepalive_timeout 30s;设置 keepalive_requests 100,回收空闲连接,降低连接级内存驻留。
- 静态资源
- 启用 sendfile on; tcp_nopush on; expires 7d; access_log off;,并添加 Cache-Control,减少磁盘 IO 与缓冲占用。
- 压缩与缓存
- 启用 gzip on; gzip_types text/plain text/css application/json; 降低带宽与后端压力。
- 使用磁盘缓存而非堆内存:例如 proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=1g; 并在 location 中启用缓存。
三 内核与系统层优化
- 文件句柄与队列
- 提升 fs.file-max(如 999999),增大 net.core.somaxconn(如 262144)与 net.ipv4.tcp_max_syn_backlog(如 262144),提升高并发下的连接接纳能力。
- TCP 时间与端口
- 缩短 net.ipv4.tcp_keepalive_time(如 15 秒)、net.ipv4.tcp_fin_timeout(如 15 秒);扩大 net.ipv4.ip_local_port_range(如 1024 65000),缓解端口耗尽。
- 套接字缓冲
- 适度设置 net.core.rmem_default / rmem_max 与 net.core.wmem_default / wmem_max,在并发与带宽之间平衡;如 4096 32768 262144。
- TIME_WAIT 优化
- 启用 net.ipv4.tcp_tw_reuse 1;根据场景调整 net.ipv4.tcp_max_tw_buckets(如 5000),降低连接关闭阶段的资源占用。
- 生效方式:编辑 /etc/sysctl.conf 后执行 sysctl -p。提示:内核参数影响全局网络栈,务必在测试环境验证后再上线。
四 进阶手段与应急
- 内存分配器优化
- 使用 tcmalloc(google-perftools) 替换默认分配器,降低高并发下的锁竞争与碎片;需重新编译 Nginx 并加入 –with-google_perftools_module,为 worker 指定 tcmalloc 目录(如 /tmp/tcmalloc),用 lsof 验证是否生效。
- 运行时资源限制
- 通过 cgroups 限制 Nginx 进程组内存(例如写入 memory.limit_in_bytes),防止异常流量导致 OOM;必要时结合 systemd 的 MemoryLimit= 配置。
- 应急限流与降级
- 临时开启限流:limit_conn_zone $binary_remote_addr zone=perip:10m; limit_conn perip 20; 限制单 IP 并发。
- 临时关闭高内存功能:如 proxy_cache off; 或缩小 ssl_session_cache(如 shared:SSL:20m;)。
- 平滑重启释放内存:nginx -s reload;必要时 systemctl restart nginx。
五 配置示例与落地步骤
- 示例片段(放在 http { } 内按需调整)
- 进程与连接
- worker_processes auto;
- worker_connections 1024;
- 缓冲与上传
- client_header_buffer_size 4k;
- large_client_header_buffers 4 8k;
- client_body_buffer_size 16k;
- client_max_body_size 10m;
- 代理与长连接
- proxy_buffer_size 4k;
- proxy_buffers 8 16k;
- proxy_busy_buffers_size 32k;
- keepalive_timeout 30s;
- keepalive_requests 100;
- 静态资源
- location ~* .(jpg|jpeg|png|gif|ico|css|js)$ {
- sendfile on;
- tcp_nopush on;
- expires 7d;
- access_log off;
- add_header Cache-Control “public”;
- }
- 压缩与缓存
- gzip on;
- gzip_types text/plain text/css application/json;
- proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=1g;
- location /static/ { proxy_cache my_cache; proxy_pass http://127.0.0.1:8000; }
- 落地步骤
- 基线采集:记录优化前的 RSS、连接数、缓存命中率与错误日志。
- 逐项调整:先进程/连接,再缓冲/上传,最后缓存与长连接;每次变更后用 ab/jmeter 或 wrk 压测验证。
- 回归观测:持续观察 24–72 小时,确认无内存泄漏与错误率上升,再进入下一轮微调。