Nginx 配置优化与反向代理实战:从入门到高并发调优

By | 2026年9月17日

为什么你的 Nginx 配置总是不够快?

很多开发者第一次接触 Nginx 时,往往是复制一段“万能配置”就上线了。结果流量一上来,502、504 频繁出现,或者静态资源加载缓慢。其实 Nginx 的默认配置是为通用场景设计的,要发挥它的威力,必须根据业务特点进行针对性调优。

本文将以一个典型的前后端分离项目为例:前端是 Vue 打包的静态文件,后端是运行在 8080 端口的 Spring Boot 应用。我们将从零开始配置 Nginx,实现反向代理、负载均衡、HTTPS、缓存和性能优化,并分享一些踩坑经验。

环境准备

假设你有一台 Linux 服务器(Ubuntu 20.04 或 CentOS 7+),已经安装了 Nginx。如果没有,可以用以下命令安装:


# Ubuntu/Debian
sudo apt update && sudo apt install nginx -y

# CentOS/RHEL
sudo yum install epel-release -y && sudo yum install nginx -y

检查版本:nginx -v,建议使用 1.18+ 以支持 HTTP/2 和更优的 TLS 配置。

第一步:基础反向代理配置

Nginx 的核心功能之一就是反向代理。我们先配置一个最简单的代理,将 /api/ 请求转发到后端服务。

创建配置文件 /etc/nginx/conf.d/myapp.conf:


server {
    listen 80;
    server_name example.com;

    # 前端静态文件
    location / {
        root /var/www/myapp/dist;
        index index.html;
        try_files $uri $uri/ /index.html;  # 支持 Vue/React 的 history 路由
    }

    # 后端 API 代理
    location /api/ {
        proxy_pass http://127.0.0.1:8080/;  # 注意末尾的斜杠
        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;
    }
}

关键点解析:

  • proxypass 末尾的斜杠:如果 location 是 /api/,而 proxypass 是 http://127.0.0.1:8080/,那么请求 /api/user 会被转发为 /user。如果 proxy_pass 没有末尾斜杠,则会转发为 /api/user。这个细节极易出错,务必根据后端路由设计选择。
  • try_files:对于单页应用,任何找不到的路径都返回 index.html,由前端路由处理。
  • 转发头信息:让后端能获取真实客户端 IP 和协议,对日志和重定向很重要。

测试配置并重载:


sudo nginx -t
sudo nginx -s reload

第二步:负载均衡与健康检查

当后端有多台实例时,可以用 upstream 做负载均衡。假设有两台后端服务器:


upstream backend {
    least_conn;  # 最少连接数算法,适合长连接场景
    server 192.168.1.10:8080 weight=3 max_fails=2 fail_timeout=30s;
    server 192.168.1.11:8080 weight=1 max_fails=2 fail_timeout=30s;
    keepalive 32;  # 保持与后端的长连接,减少握手开销
}

server {
    listen 80;
    server_name example.com;

    location /api/ {
        proxy_pass http://backend/;
        proxy_http_version 1.1;
        proxy_set_header Connection "";  # 配合 keepalive 使用
        # ... 其他头信息
    }
}

注意:

  • least_conn 比默认的轮询更适合请求处理时间不均的场景。
  • weight 可以根据服务器性能调整权重。
  • maxfails 和 failtimeout 实现被动健康检查:30 秒内失败 2 次则暂时剔除该节点。
  • keepalive 需要配合 proxyhttpversion 1.1 和 proxysetheader Connection "" 才能生效,否则可能适得其反。

💡 进阶: 如果需要主动健康检查,可以考虑 Nginx Plus 或使用 OpenResty 的 lua-resty-healthcheck。

第三步:HTTPS 与 HTTP/2 配置

安全是现代 Web 的标配。使用 Let’s Encrypt 免费证书:


sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d example.com -d www.example.com

Certbot 会自动修改 Nginx 配置,但我们可以手动优化 TLS 参数:


server {
    listen 443 ssl http2;
    server_name example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    # 现代 TLS 配置
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;

    # 会话复用,提升性能
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 1d;
    ssl_session_tickets off;

    # HSTS (谨慎开启,确保所有子域名都支持 HTTPS)
    add_header Strict-Transport-Security "max-age=63072000" always;

    # ... 其他 location 配置
}

# HTTP 重定向到 HTTPS
server {
    listen 80;
    server_name example.com;
    return 301 https://$host$request_uri;
}

注意:

  • sslpreferserver_ciphers off 让客户端选择加密套件,通常更快,因为客户端更了解自己的硬件。
  • sslsessiontickets off 提升前向安全性,但会稍微增加握手开销。如果追求性能,可以开启。
  • HSTS 头一旦被浏览器记录,在 max-age 内无法回退,测试时先用小 max-age。

第四步:性能优化参数

Nginx 的性能很大程度上取决于 nginx.conf 中的全局配置。以下是一个针对高并发的优化模板:


# /etc/nginx/nginx.conf
user www-data;
worker_processes auto;  # 自动匹配 CPU 核心数
worker_rlimit_nofile 65535;  # 每个 worker 能打开的最大文件数

events {
    worker_connections 65535;  # 每个 worker 的最大连接数
    multi_accept on;  # 一次接受所有新连接
    use epoll;  # Linux 下高性能事件模型
}

http {
    # 基础优化
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    server_tokens off;  # 隐藏版本号

    # 客户端缓存
    open_file_cache max=10000 inactive=30s;
    open_file_cache_valid 60s;
    open_file_cache_min_uses 2;
    open_file_cache_errors on;

    # 压缩
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_types text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml;

    # 缓冲区
    client_body_buffer_size 10K;
    client_header_buffer_size 1k;
    client_max_body_size 8m;
    large_client_header_buffers 2 1k;

    # 超时
    client_body_timeout 12;
    client_header_timeout 12;
    send_timeout 10;

    # 代理缓冲区
    proxy_buffering on;
    proxy_buffer_size 4k;
    proxy_buffers 8 4k;
    proxy_busy_buffers_size 8k;

    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

参数解释:

  • worker_processes auto:通常设置为 CPU 核心数,但若磁盘 I/O 密集,可以适当增加。
  • workerconnections:理论最大连接数 = workerprocesses * worker_connections。但受限于系统文件描述符,需同步调整 ulimit -n。
  • multi_accept on:让 worker 一次尽可能多地接受连接,高并发下有效。
  • openfilecache:缓存文件描述符,减少磁盘 I/O,对静态文件服务提升明显。
  • gzipcomplevel 6:压缩级别 6 是性能与压缩比的平衡点,再高收益递减。

💡 系统层面优化: 修改 /etc/security/limits.conf 增加 nofile,调整内核参数如 net.core.somaxconn、net.ipv4.tcptwreuse 等。

第五步:静态资源缓存与 CDN 配合

对于前端静态资源,利用浏览器缓存能大幅减少请求。在 location 中为带哈希的文件设置长期缓存:


location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2?)$ {
    root /var/www/myapp/dist;
    expires 1y;
    add_header Cache-Control "public, immutable";
    access_log off;
}

location = /index.html {
    root /var/www/myapp/dist;
    add_header Cache-Control "no-cache, no-store, must-revalidate";
}

注意:

  • 只有文件名包含哈希(如 app.abc123.js)才能设置长期缓存,否则更新后客户端无法获取新版本。
  • index.html 必须禁用缓存,否则用户可能一直使用旧版本。
  • 如果使用 CDN,可以在 CDN 回源时设置缓存规则,Nginx 层可以简化。

常见坑与排查技巧

  1. 502 Bad Gateway:通常是后端服务未启动或端口不对。检查 proxy_pass 地址,查看后端日志。
  2. 504 Gateway Timeout:后端处理超时。调整 proxyreadtimeout(默认 60s),但更应优化后端性能。
  3. 413 Request Entity Too Large:上传文件大小限制。调整 clientmaxbody_size。
  4. 静态资源 404:检查 root 路径是否正确,权限是否足够(Nginx 用户需有读权限)。
  5. WebSocket 代理失败:需要额外配置:

“nginx proxysetheader Upgrade $httpupgrade; proxyset_header Connection "upgrade"; “

  1. 跨域问题:可以在 Nginx 层添加 CORS 头,但注意不要与后端重复。

调试利器:

  • nginx -t 测试配置语法。
  • tail -f /var/log/nginx/error.log 实时查看错误。
  • curl -I -H "Host: example.com" http://127.0.0.1 模拟请求。
  • 使用 nginx -T 输出最终生效的完整配置,排查 include 冲突。

总结与下一步

通过以上五步,你已经拥有了一个支持反向代理、负载均衡、HTTPS、缓存和高并发优化的 Nginx 配置。记住,没有“万能配置”,一定要根据实际业务压测后调整参数。

延伸方向:

  • 使用 OpenResty 和 Lua 实现动态限流、鉴权。
  • 配置 Nginx 作为 API 网关,集成 JWT 验证。
  • 结合 Prometheus + Grafana 监控 Nginx 指标(需 nginx-module-vts)。
  • 学习 map 指令实现更灵活的条件判断。

希望本文能帮你少走弯路,构建更稳定的 Web 服务。如果有问题,欢迎在评论区交流。