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 太小 调大 somaxconnlisten backlog

16IDC 观察

对大多数网站,Nginx 加上 CDN 的架构已经能够满足性能需求。把 Gzip、缓存策略和安全头配到位,不需要加硬件就能显著提升体验。调优前先量化:用 abwrk 记录当前 QPS 和延迟,改一处配置再压一次,别凭感觉堆参数。建议的调优顺序是先开 gzip 和缓存(见效最快),再看 keepalive 与内核参数,最后才考虑 HTTP/3 和硬件加速。

选择合适的 Nginx 运行环境可以参考服务器选型指南。