Nginx 网站服务器优化完全指南:从基础配置到性能调优
一台 2 核 4G 的入门服务器,配置得当的 Nginx 可以扛住上万并发连接;配置随意,可能几百个请求就卡死。差距不在硬件,而在那几十行配置。Nginx 以其高性能、低资源消耗和灵活配置成为最流行的 Web 服务器和反向代理,全球超过 30% 的网站在使用 它,几乎是网站服务器领域的事实标准。
基础配置模板
# /etc/nginx/nginx.conf
user www-data;
worker_processes auto;
worker_rlimit_nofile 65535;
pid /run/nginx.pid;
events {
worker_connections 4096;
use epoll;
multi_accept on;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# 基础优化
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
server_tokens off;
}
worker_processes auto 让 Nginx 按 CPU 核数生成 worker;worker_connections 乘以核数就是理论最大并发连接数。worker_rlimit_nofile 要让系统文件描述符上限跟上,否则高并发下会出现 "too many open files"。
worker 数量不是越多越好:进程越多,内存占用和上下文切换开销越大,2 核机器开到 8 个 worker 反而可能变慢。一般建议 worker 数等于或略小于 CPU 核数,再根据压力测试结果微调。判断连接数配得够不够,可以用 ss -s 查看当前 TCP 连接数:如果接近 worker_processes × worker_connections 的上限,就需要调大;一般留出 2-3 倍余量即可,不必盲目堆到几十万。
TLS 配置要点
HTTPS 已经是标配,TLS 本身也值得单独调优。下面是一份常用的安全基线:
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_stapling on;
ssl_stapling_verify on;
ssl_session_cache 开启后可以复用 TLS 会话,避免每个新连接都做完整握手,对高并发的 API 或页面收益尤其明显。ssl_stapling(OCSP Stapling)则把证书吊销状态的查询结果缓存到 Nginx,减少浏览器侧的额外验证延迟。
静态文件服务优化
对托管静态资源的 Nginx,以下配置可显著减少带宽占用和响应时间:
server {
listen 80;
server_name static.example.com;
root /var/www/static;
# 启用 Gzip 压缩
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;
gzip_min_length 256;
gzip_comp_level 5;
gzip_vary on;
# 浏览器缓存
location ~* \.(jpg|jpeg|png|gif|ico|webp|svg)$ {
expires 365d;
add_header Cache-Control "public, immutable";
}
location ~* \.(css|js)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
location ~* \.(html|json)$ {
expires 1h;
add_header Cache-Control "public, must-revalidate";
}
}
按类型设置不同缓存时长是性价比最高的优化之一:带哈希文件名的 CSS/JS 可以放心用 immutable 缓存一年,HTML 只缓存一小时,保证内容更新能及时生效。
常见资源的缓存策略对比:
| 资源类型 | 建议缓存时长 | Cache-Control | 说明 |
|---|---|---|---|
| 带哈希的 CSS/JS | 365 天 | public, immutable |
文件名变则 URL 变,可放心长缓存 |
| 图片/字体 | 30-365 天 | public, max-age=... |
按更新频率调整 |
| HTML 页面 | 5 分钟-1 小时 | must-revalidate |
保证内容更新能及时生效 |
| API 响应 | 按需 | no-store 或短 TTL |
避免缓存到过期数据 |
反向代理配置
server {
listen 443 ssl http2;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# 缓冲优化
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
}
location /api/ {
proxy_pass http://127.0.0.1:8080;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
}
}
Connection "upgrade" 那两行是 WebSocket 必需的,否则 Nginx 层会把长连接掐断;X-Forwarded-Proto 让后端知道用户走的是 HTTPS,避免生成错误的链接。
安全加固配置
# 隐藏 Nginx 版本号
server_tokens off;
# 安全响应头
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
# 限制请求速率
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=30r/s;
location /login/ {
limit_req zone=mylimit burst=5 nodelay;
}
# 限制连接数
limit_conn_zone $binary_remote_addr zone=addr:10m;
server {
limit_conn addr 100;
}
对登录、注册、API 这类敏感端点做 limit_req,是防暴力破解和刷接口最简单有效的一招。举个例子:一个博客站把评论接口配成 rate=5r/s 后,被爬虫刷评论的速度立刻降下来,服务器负载明显回落;而某个没有限流的论坛,曾在几小时内被脚本灌了十几万条垃圾帖。限流参数不是越大越好,要根据真实流量留出余量,否则会误伤正常用户——可以先从 rate=10r/s 起步,观察误伤情况再收紧。
安全头这几行配置看着简单,却是上线前最容易漏掉的一环:X-Frame-Options 防止页面被 iframe 嵌入点击劫持,X-Content-Type-Options: nosniff 防止 MIME 嗅探,Permissions-Policy 则统一声明浏览器权限。它们对功能没有影响,建议所有站点直接全局加上。
性能调优技巧
1. 使用 HTTP/2 或 HTTP/3
HTTP/2 支持多路复用,减少了连接数;HTTP/3(基于 QUIC)在弱网环境下进一步降低延迟:
listen 443 ssl http2;
# HTTP/3 需要额外配置
listen 443 quic reuseport;
2. 开启 OpenSSL 硬件加速
ssl_engine aesni;
3. 调整内核参数
# /etc/sysctl.conf
net.core.somaxconn = 65535
net.ipv4.tcp_max_tw_buckets = 2000000
net.ipv4.tcp_fin_timeout = 10
net.ipv4.tcp_tw_reuse = 1
net.core.netdev_max_backlog = 5000
改完 sysctl -p 生效。内核参数要和 Nginx 配置配套,比如 somaxconn 调大后,listen 指令的 backlog 也应当相应调大。
性能检测命令
# 测试 Nginx 配置
nginx -t
# 查看 Nginx 状态
systemctl status nginx
# 实时请求统计
tail -f /var/log/nginx/access.log | grep -c "GET"
# 使用 ab 进行压力测试
ab -n 10000 -c 100 https://example.com/
参考:Nginx 官方文档 https://nginx.org/en/docs/
日志管理与切割
Nginx 默认把访问日志写在一个文件里,流量上来后很快会膨胀到 GB 级,既占磁盘又拖慢写盘。建议用 logrotate 按天切割并保留 30 天。Linux 上通常已自带配置,只需确认:
# /etc/logrotate.d/nginx
/var/log/nginx/*.log {
daily
rotate 30
compress
missingok
notifempty
sharedscripts
postrotate
[ -f /var/run/nginx.pid ] && kill -USR1 $(cat /var/run/nginx.pid)
endscript
}
kill -USR1 会通知 Nginx 重新打开日志文件,保证切割后旧文件不会继续被写入。
常见问题排查
| 现象 | 原因 | 处理 |
|---|---|---|
| 502 Bad Gateway | 后端服务没起来或崩溃 | 检查 proxy_pass 目标进程与日志 |
| 504 Gateway Timeout | 后端响应超时 | 调大 proxy_read_timeout 或优化后端 |
| too many open files | 文件描述符不够 | 提高 worker_rlimit_nofile 与系统 ulimit |
| 高并发连接被拒 | backlog 太小 | 调大 somaxconn 与 listen backlog |
16IDC 观察
对大多数网站,Nginx 加上 CDN 的架构已经能够满足性能需求。把 Gzip、缓存策略和安全头配到位,不需要加硬件就能显著提升体验。调优前先量化:用 ab 或 wrk 记录当前 QPS 和延迟,改一处配置再压一次,别凭感觉堆参数。建议的调优顺序是先开 gzip 和缓存(见效最快),再看 keepalive 与内核参数,最后才考虑 HTTP/3 和硬件加速。
选择合适的 Nginx 运行环境可以参考服务器选型指南。