Nginx 高性能调优实战:从默认配置到生产级静态站
很多人部署 Nginx 时直接沿用发行版默认配置——能用,但远不是最优。本文以一台 Debian 12 + 静态站为例,从「进程模型 → 传输层 → 压缩 → 缓存 → 限流」五个层面,给出可直接落地的生产级调优清单。这套配置在本站(TechPulse)真实运行,效果可测。
一、进程模型:让 worker 数与硬件匹配
1. worker_processes
默认值 1 只用一个进程,浪费多核 CPU。现代机器建议直接设 auto,Nginx 会按 CPU 核数自动分配。
worker_processes auto;
worker_cpu_affinity auto; # 多核绑定,减少进程迁移开销
2. worker_connections 与事件模型
events {
worker_connections 4096; # 单 worker 最大并发连接(默认 768 偏小)
use epoll; # Linux 下默认即 epoll,显式声明更清晰
multi_accept on; # 一次 accept 尽量多接
}
理论峰值并发 ≈ worker_processes × worker_connections。4 核机器配 4096,即可支撑约 1.6 万并发连接——对个人站来说绰绰有余。
二、传输层:sendfile 与 TCP 优化
sendfile on; # 零拷贝发静态文件,绕开用户态内存拷贝
tcp_nopush on; # 攒够一个包再发,配合 sendfile 减少小包
tcp_nodelay on; # 小文件/API 响应立即发,不等待 Nagle
keepalive_timeout 30s;# HTTP 长连接保持时间(15~60s 均可)
keepalive_requests 1000; # 单连接最多复用请求数,默认 100 可调大
sendfile 对静态站收益最大——文件直接从磁盘到网卡,CPU 几乎不参与。注意:sendfile 与 gzip 同时开启时,压缩会在发送阶段进行,配合预压缩的 .gz 文件效果最佳(见下文)。
三、压缩:gzip + gzip_static,省一半流量
3. gzip 基础配置
gzip on;
gzip_comp_level 6; # 1~9,6 是性价比甜点
gzip_min_length 1024; # 小于 1KB 不压(压缩反而更大)
gzip_types text/plain text/css application/json
application/javascript image/svg+xml
application/xml application/xml+rss;
gzip_vary on; # 返回 Vary: Accept-Encoding,利于中间缓存
4. gzip_static:预压缩,彻底消除「解压再压缩」
运行时 gzip 每次请求都要现场压缩,很耗 CPU。若部署时已经生成 .gz 文件,开启 gzip_static on 后 Nginx 直接发预压缩文件,CPU 占用几乎归零。
# nginx.conf 中
gzip_static on;
# 生成预压缩文件(CSS/JS 等静态资源)
gzip -9 -k style.css main.js tools.js vendor/*.js
本站的 assets/js/vendor/*.js(如 pdf-lib、pptxgen)体积以 MB 计,预压缩后传输量直接降到 1/4~1/3,首屏收益立竿见影。
四、缓存:让「命中」代替「回源」
5. 静态资源长缓存 + 指纹刷新
location ^~ /assets/ {
expires 7d;
add_header Cache-Control "public, max-age=604800" always;
try_files $uri =404;
}
注意配套策略:CSS/JS 文件名带 ?v=N 或内容哈希作为「指纹」,改版时更新指纹即可强制刷新,旧缓存自然失效。
6. HTML 页面:绝不长缓存
location ~* \.html$ {
expires -1;
add_header Cache-Control "no-cache, must-revalidate" always;
}
HTML 是「入口」,一旦被浏览器/代理长缓存,用户就永远看不到新版本。用 no-cache, must-revalidate:每次导航都回源校验(返回 304,极快),拿到新版本就立刻替换——这是静态站最常见的翻车点。
7. open_file_cache:把「打开文件」也缓存起来
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2; # 访问 2 次以上才缓存句柄
open_file_cache_errors on; # 把「文件不存在」也缓存,防 404 风暴
静态站高频访问同一批文件,缓存文件句柄、元数据后,连 stat() 系统调用都省了,QPS 能再上一个台阶。
五、限流与安全:好性能的前提是「不被拖垮」
8. 全局限速 + 接口独立限速
limit_req_zone $binary_remote_addr zone=general:10m rate=30r/s;
limit_req_zone $binary_remote_addr zone=api:10m rate=5r/s;
server {
limit_req zone=general burst=300 nodelay; # 全局:突发 300
location = /api/ {
limit_req zone=api burst=20 nodelay; # 接口:更严
}
}
限速不是降低性能,而是「削峰」。没有限流,一次 CC/爬虫风暴就能让之前所有优化归零。
9. 敏感路径与隐藏版本
server_tokens off; # 隐藏版本号
location ~ /\.(?!well-known) { deny all; } # 隐藏点开头文件
location ~* \.(env|log|bak|sql|sh|py)$ { deny all; }
六、实测:调优前后对比
| 指标 | 默认配置 | 调优后 |
|---|---|---|
| 静态 CSS(gzip 后)传输量 | 5.1KB | 1.9KB(gzip_static) |
| pdf-lib.min.js 传输量 | 516KB | 206KB |
| 首屏 HTML 校验 | 完整 200 响应 | 304 命中(<1ms) |
| 单 worker 并发 | 768 | 4096 |