Nginx 性能调优

这是本系列的压轴章节。前面学了配置、虚拟主机、反向代理、HTTPS、gzip——这些已经能让 Nginx 跑起来。但要让 Nginx 真正发挥单机数万并发的潜力,需要一套系统的性能调优。这一章我们从进程模型、事件循环、零拷贝、长连接、系统限制五个层面,把硬件压榨到极致。

1. 调优前先测量

性能优化的第一原则:先测后调。不要拍脑袋改配置,每次只改一个参数、用同一套基准测试对比。否则你根本不知道改了有没有效果,甚至可能负优化。

常用的压力测试工具:

2. worker_processes 与 worker_connections

这是 Nginx 性能的地基。worker 数量决定 CPU 利用率,每个 worker 的连接数决定并发上限:

# worker 进程与连接数调优
worker_processes auto;            # auto = 自动等于 CPU 核数(最常用)
# 也可以显式指定:worker_processes 8;

events {
    worker_connections 10240;     # 每个 worker 最大连接数(默认 512,太保守)
    multi_accept on;              # 一次接受所有新连接(高并发必备)
    use epoll;                    # Linux 默认就是 epoll,可省略
}

# 最大并发连接数 = worker_processes × worker_connections
#   4 核 × 10240 = 40960 并发
#   8 核 × 10240 = 81920 并发

# 反向代理场景要除以 2(每个客户端连接还要占一个到后端的连接)
#   8 核 × 10240 / 2 = 40960 真实客户端并发

几个关键经验:

3. 系统级文件描述符限制

worker_connections 设到 10240,但 Linux 默认每个进程只能开 1024 个文件描述符——这个限制会先于 Nginx 配置生效。必须同时调系统参数:

# 系统级文件描述符限制(worker_connections 受此约束)
# 查看当前限制
ulimit -n
# 1024 ← 默认值太小,需要调大

# 临时修改(仅当前 shell 生效)
ulimit -n 65535

# 永久修改:/etc/security/limits.conf
# 加两行:
#   *  soft  nofile  65535
#   *  hard  nofile  65535

# Nginx 配置里也可以单独设(推荐)
worker_rlimit_nofile 65535;

# systemd 系统(Ubuntu 16.04+)还要改 service 文件
# /etc/systemd/system/multi-user.target.wants/nginx.service
# [Service]
# LimitNOFILE=65535

这是最常见的"我明明配了 worker_connections 10240,但 QPS 上不去"的原因。生产环境部署脚本里应该自动设置。

4. sendfile、tcp_nopush、keepalive(黄金三件套)

这三个指令能带来50% 以上的性能提升,几乎没有任何副作用,建议默认开启:

http {
    # === 零拷贝:内核态直接传文件 ===
    sendfile on;          # 静态文件必开(性能提升 2-3 倍)

    # === TCP 数据包优化 ===
    tcp_nopush on;        # 等数据包填满再发(配合 sendfile,减少网络包数)
    tcp_nodelay on;       # 立即发包(适合实时交互,与 tcp_nopush 互不冲突)

    # === 长连接(HTTP keepalive)===
    keepalive_timeout  65;       # 客户端长连接超时(秒),0 = 关闭
    keepalive_requests 1000;     # 一个长连接上最多处理多少请求(默认 1000)

    # === 后端长连接(反向代理场景重要!)===
    upstream backend {
        server 10.0.0.1:3000;
        keepalive 32;            # 缓存 32 个到后端的长连接
    }

    server {
        location / {
            proxy_pass http://backend;
            proxy_http_version 1.1;                # 必须 1.1 才能复用长连接
            proxy_set_header Connection "";        # 清空 Connection 头
        }
    }
}

原理详解:

5. 缓冲区与超时

合理的缓冲区能减少磁盘 I/O,但太大反而浪费内存:

http {
    # === 客户端缓冲区 ===
    client_body_buffer_size 16k;      # 请求体缓冲区(超过会写磁盘)
    client_body_timeout 60s;          # 请求体接收超时
    client_header_timeout 60s;        # 请求头接收超时
    client_max_body_size 20m;         # 请求体最大大小(超过返 413)

    # === 大文件下载优化 ===
    output_buffers 2 32k;             # 响应输出缓冲区
    postpone_output 1460;             # 累积到 1460 字节再发(一个 TCP 包大小)

    # === connection_pool(高级)===
    # 每 worker 的连接内存池,一般不用改
    connection_pool_size 512;
    request_pool_size 4k;
}

几个经验值:

6. 客户端缓存:用浏览器省服务器

性能优化最划算的方式不是"让服务器更快",而是不让请求到达服务器。用 HTTP 缓存头让浏览器直接用本地副本:

# 客户端缓存:用 expires 控制 Cache-Control / Expires 头
server {
    location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff2)$ {
        root /var/www/static;

        # 强缓存:30 天内浏览器直接用本地缓存,不发请求
        expires 30d;
        add_header Cache-Control "public, immutable";
        # immutable 让浏览器连 304 验证都不发(适合带 hash 的文件名)
    }

    location ~* \.(html)$ {
        # HTML 不能强缓存(更新后用户看不到),用协商缓存
        add_header Cache-Control "no-cache";
        # 浏览器每次发请求问服务器"改了没",没改返 304
    }

    location = /index.html {
        add_header Cache-Control "no-store";
        # 完全不缓存(每次都重拉)
    }
}

缓存策略的最佳实践

7. 静态资源优化清单

8. HTTP/2 与 HTTP/3

HTTP/2 自带多路复用、头部压缩、服务器推送,对页面加载性能提升明显(HTTPS 章节讲过怎么开)。HTTP/3 基于 QUIC(UDP),进一步减少握手延迟,Nginx 1.25.0+ 开始支持,配置:

9. 实测对比

调优后用压测工具验证:

# 1. 用 ab(Apache Bench)测 QPS
ab -n 10000 -c 100 http://localhost/
#   -n 10000   总请求数
#   -c 100     并发数
#   关注:Requests per second、Time per request、Failed requests

# 2. 用 wrk 测(更准确)
wrk -t8 -c1000 -d30s http://localhost/
#   -t8      8 个线程
#   -c1000   1000 并发连接
#   -d30s    跑 30 秒

# 3. Nginx 自带状态页(需编译 stub_status 模块)
location /nginx_status {
    stub_status on;
    access_log off;
    allow 127.0.0.1;
    deny all;
}
# 访问 /nginx_status 看到:
#   Active connections: 15
#   server accepts handled requests
#    8456 8456 32891
#   Reading: 0 Writing: 1 Waiting: 14

# 4. 查看 Nginx 进程的 CPU 占用
top -p $(pgrep -d',' nginx)

典型优化前后对比(4 核 8G 服务器,纯静态 1KB 文件):

状态QPSP99 延迟
默认配置~800050ms
+ worker_connections 10240~1500040ms
+ ulimit + sendfile~2500030ms
+ gzip + open_file_cache~3000025ms

注意:测试要在不同机器上做,结果仅供参考。重点是掌握调优方法论,而不是记住具体数字。

10. 调优检查清单(生产必跑)

系列总结

恭喜你完成了Nginx 10 篇完整系列!从最基础的"什么是 Nginx",到生产级的反向代理、HTTPS、性能调优,你现在应该能:

下一步推荐:OpenResty(Nginx + Lua)解锁编程能力、Kong API 网关Envoy(云原生代理)。Nginx 是基础,掌握了它,学这些上层工具都会得心应手。

← 上一篇 日志系统

← 返回 Nginx 教程目录

✈️💬