Nginx 反向代理与负载均衡实战:从单机到多节点的高可用方案 原创

温馨提示:
本文最后更新于 2026-09-21,已超过 0 天没有更新。 若文章内的图片失效(无法正常加载),请留言反馈或直接 联系我

引言

Nginx 作为最流行的反向代理服务器之一,在 production 环境中承担着流量分发、SSL 终结、缓存加速等核心职责。本文从实际运维经验出发,覆盖从单机反向代理到多节点负载均衡的完整链路,包含配置实例、健康检查方案和故障排查思路。

一、反向代理基础配置

最常见的场景:将 Nginx 放在应用服务器前面,对外暴露统一入口。

server {
    listen 80;
    server_name api.example.com;

    location / {
        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;
    }
}

几个关键 header 的作用:

  • Host:透传原始域名,后端需要根据域名做虚拟主机区分时必不可少
  • X-Real-IP:传递客户端真实 IP,后端日志和风控依赖此值
  • X-Forwarded-For:多层代理时的 IP 链路追踪
  • X-Forwarded-Proto:告知后端原始协议是 HTTP 还是 HTTPS

二、负载均衡配置

当单台后端不够用时,引入 upstream 做多节点负载均衡:

upstream backend {
    # 轮询(默认)
    server 10.0.1.10:8080;
    server 10.0.1.11:8080;
    server 10.0.1.12:8080;

    # 或者使用加权轮询
    # server 10.0.1.10:8080 weight=3;
    # server 10.0.1.11:8080 weight=2;
    # server 10.0.1.12:8080 weight=1;

    # ip_hash 保证同一客户端落到同一后端(会话保持)
    # ip_hash;

    # least_conn 选择活跃连接数最少的服务器
    # least_conn;

    keepalive 32;  # 保持到后端的长连接池
}

server {
    listen 80;
    server_name api.example.com;

    location / {
        proxy_pass http://backend;
        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_http_version 1.1;
        proxy_set_header Connection "";  # 配合 keepalive 使用
    }
}

负载均衡策略对比

策略 指令 适用场景
轮询 默认 后端性能均匀
加权轮询 weight=N 后端性能不一致
IP Hash ip_hash 需要会话保持
最少连接 least_conn 请求处理时间差异大

三、健康检查与故障转移

Nginx 开源版自带被动健康检查:某台后端返回错误后,会被临时摘除。可以通过参数控制行为:

upstream backend {
    server 10.0.1.10:8080 max_fails=3 fail_timeout=30s;
    server 10.0.1.11:8080 max_fails=3 fail_timeout=30s;
    # max_fails: 在 fail_timeout 时间窗口内失败次数达到此值则摘除
    # fail_timeout: 摘除持续时间(也是统计窗口)
}

主动健康检查需要 Nginx Plus 或第三方模块(如 nginx_upstream_check_module)。开源替代方案是用 Consul + Consul-Template 动态更新 upstream 配置:

# consul-template 模板示例
upstream backend {
{{ range service "myapp" }}
    server {{ .Address }}:{{ .Port }};
{{ end }}
}

当某台服务从 Consul 注销时,consul-template 自动重写 nginx.conf 并 reload,实现准实时的故障摘除。

四、SSL 终结与 HTTPS 反向代理

在生产环境中,SSL 证书通常在 Nginx 层终结,后端走 HTTP:

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

    ssl_certificate     /etc/letsencrypt/live/api.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_ciphers         HIGH:!aNULL:!MD5;
    ssl_session_cache   shared:SSL:10m;
    ssl_session_timeout 10m;

    location / {
        proxy_pass http://backend;
        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 https;
    }
}

# HTTP 跳转 HTTPS
server {
    listen 80;
    server_name api.example.com;
    return 301 https://$host$request_uri;
}

五、缓存与限流

代理缓存

proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=api_cache:10m
                 max_size=1g inactive=60m use_temp_path=off;

server {
    location /api/data {
        proxy_cache api_cache;
        proxy_cache_valid 200 10m;
        proxy_cache_valid 404 1m;
        proxy_cache_key "$scheme$request_method$host$request_uri";
        add_header X-Cache-Status $upstream_cache_status;
        proxy_pass http://backend;
    }
}

请求限流

limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;

server {
    location /api {
        limit_req zone=api_limit burst=20 nodelay;
        proxy_pass http://backend;
    }
}

rate=10r/s 表示每秒允许 10 个请求,burst=20 允许突发 20 个请求排队,nodelay 表示不延迟排队中的请求。

六、WebSocket 代理

WebSocket 需要额外的 Upgrade header 处理:

location /ws {
    proxy_pass http://backend;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_read_timeout 300s;  # WebSocket 长连接需要更长的读超时
}

七、常见故障排查

502 Bad Gateway

最常见原因:后端服务未启动或端口错误。排查步骤:

# 1. 检查后端是否存活
curl -I http://127.0.0.1:8080

# 2. 检查 Nginx upstream 配置
nginx -T | grep -A 10 upstream

# 3. 检查 Nginx 错误日志
tail -f /var/log/nginx/error.log

504 Gateway Timeout

后端响应太慢。如果这是预期的(如长轮询、大文件处理),调整超时:

proxy_connect_timeout 10s;
proxy_send_timeout    60s;
proxy_read_timeout    60s;

413 Request Entity Too Large

上传文件被限制。调整 client_max_body_size:

client_max_body_size 50m;

八、配置优化清单

  • worker_processes 设为 auto,匹配 CPU 核心数
  • worker_connections 适当调大(10240+),注意 ulimit 限制
  • sendfile on + tcp_nopush on 提升静态文件传输效率
  • gzip on 压缩文本类响应
  • keepalive_timeout 控制客户端长连接保持时间
  • 日志格式中加入 $upstream_response_time$request_time 便于排查慢请求

总结

Nginx 反向代理的生产配置远不止 proxy_pass 一行。从 header 透传、负载均衡策略、健康检查、SSL 终结到缓存限流,每个环节都直接影响线上稳定性。核心原则:先跑通最小可用配置,再根据监控数据逐步优化,避免一上来就全量配置导致排障困难。