一、反向代理与负载均衡:概念解析

在现代 Web 架构中,反向代理(Reverse Proxy) 是位于客户端与后端服务器之间的中间层,它接收客户端请求并将其转发到适当的后端服务器,然后将服务器的响应返回给客户端。反向代理对客户端是透明的——客户端认为自己在直接与源服务器通信。

负载均衡(Load Balancing) 则是将传入的网络流量分发到多台后端服务器的技术。它解决了单台服务器无法承载高并发流量的瓶颈问题,同时提供了故障转移(Failover)能力。

Nginx 凭借其事件驱动架构和异步非阻塞 I/O 模型,天然适合承担反向代理和负载均衡的角色。在 10,000 并发连接下内存占用仅约 2.5MB,这使其成为业界最广泛采用的方案之一。

客户端 HTTPS Nginx 反向代理 / 负载均衡 App Server 1 App Server 2 App Server 3 ↑ 下游 (Downstream) ↑ 上游 (Upstream) 反向代理架构示意图 — Nginx 作为流量入口分发请求

二、Nginx 安装与基础配置

Ubuntu/Debian 安装

# 更新包索引
sudo apt update

# 安装 Nginx
sudo apt install nginx -y

# 验证安装
nginx -v
# 输出: nginx version: nginx/1.24.0

# 启动并设置开机自启
sudo systemctl start nginx
sudo systemctl enable nginx

# 检查状态
sudo systemctl status nginx

配置文件结构

/etc/nginx/
├── nginx.conf              # 主配置文件
├── sites-available/        # 可用站点配置
│   └── default
├── sites-enabled/          # 已启用站点(符号链接)
│   └── default -> ../sites-available/default
├── conf.d/                 # 额外配置片段
├── snippets/               # 可复用配置片段
│   ├── ssl-params.conf
│   └── proxy-params.conf
└── mime.types              # MIME 类型映射

三、反向代理核心配置

以下是一个完整的反向代理配置,将请求转发到本地 Node.js 应用(端口 3000):

server {
    listen 80;
    server_name example.com www.example.com;
    
    # 日志配置
    access_log /var/log/nginx/example.access.log;
    error_log  /var/log/nginx/example.error.log;
    
    # 客户端请求体大小限制(文件上传等)
    client_max_body_size 50M;
    
    location / {
        proxy_pass http://127.0.0.1:3000;
        
        # 传递真实客户端信息
        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_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
        
        # 缓冲配置
        proxy_buffering on;
        proxy_buffer_size 4k;
        proxy_buffers 8 4k;
    }
    
    # 静态资源直接由 Nginx 处理
    location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf)$ {
        root /var/www/example/public;
        expires 30d;
        add_header Cache-Control "public, immutable";
    }
}

四、负载均衡策略详解

Nginx 通过 upstream 模块实现负载均衡,支持多种调度算法:

1. 轮询(Round Robin)—— 默认策略

upstream backend {
    server 192.168.1.10:3000;
    server 192.168.1.11:3000;
    server 192.168.1.12:3000;
}

请求按顺序轮流分配到各服务器。适合各服务器性能相近的场景。

2. 加权轮询(Weighted Round Robin)

upstream backend {
    server 192.168.1.10:3000 weight=3;   # 处理 3/6 请求
    server 192.168.1.11:3000 weight=2;   # 处理 2/6 请求
    server 192.168.1.12:3000 weight=1;   # 处理 1/6 请求
}

3. IP 哈希(IP Hash)

upstream backend {
    ip_hash;
    server 192.168.1.10:3000;
    server 192.168.1.11:3000;
    server 192.168.1.12:3000;
}

同一客户端 IP 始终路由到同一台后端服务器,解决 Session 共享问题。

4. 最少连接(Least Connections)

upstream backend {
    least_conn;
    server 192.168.1.10:3000;
    server 192.168.1.11:3000;
    server 192.168.1.12:3000;
}

五、健康检查与故障转移

Nginx 提供了被动健康检查和主动健康检查两种机制:

upstream backend {
    server 192.168.1.10:3000 max_fails=3 fail_timeout=30s;
    server 192.168.1.11:3000 max_fails=3 fail_timeout=30s;
    server 192.168.1.12:3000 backup;  # 备用服务器
}

参数说明:

  • max_fails=3:30秒内失败3次标记为不可用
  • fail_timeout=30s:不可用状态持续30秒后重试
  • backup:备用服务器,仅在其他服务器全部不可用时启用
  • down:手动标记服务器为不可用(维护模式)

六、SSL/TLS 终端配置

server {
    listen 443 ssl http2;
    server_name example.com;
    
    # SSL 证书路径
    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    
    # 现代 SSL 配置
    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';
    ssl_prefer_server_ciphers on;
    
    # 启用 HSTS
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
    
    location / {
        proxy_pass http://backend;
        proxy_set_header X-Forwarded-Proto https;
    }
}

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

七、生产环境完整配置模板

upstream app_cluster {
    least_conn;
    server 127.0.0.1:3001 weight=3 max_fails=2 fail_timeout=20s;
    server 127.0.0.1:3002 weight=3 max_fails=2 fail_timeout=20s;
    server 127.0.0.1:3003 backup;
    keepalive 32;  # 长连接池大小
}

server {
    listen 443 ssl http2;
    server_name api.example.com;
    
    ssl_certificate     /etc/ssl/certs/example.pem;
    ssl_certificate_key /etc/ssl/private/example.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    
    client_max_body_size 20M;
    client_body_buffer_size 128k;
    
    # Gzip 压缩
    gzip on;
    gzip_types text/plain application/json application/javascript text/css;
    gzip_min_length 256;
    
    location / {
        proxy_pass http://app_cluster;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        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_connect_timeout 10s;
        proxy_read_timeout 30s;
        proxy_send_timeout 30s;
        
        proxy_buffering on;
        proxy_buffer_size 8k;
        proxy_buffers 16 8k;
        
        # 限流
        limit_req zone=api_limit burst=20 nodelay;
    }
    
    location /health {
        proxy_pass http://app_cluster;
        access_log off;
    }
}

# 请求限流区域
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=100r/s;

八、性能调优参数

参数 推荐值 说明
worker_processesauto自动匹配 CPU 核心数
worker_connections4096每个 Worker 最大连接数
keepalive_timeout65Keep-Alive 超时时间
keepalive_requests1000单连接最大请求数
sendfileon启用零拷贝文件传输
tcp_nopushon优化 TCP 包发送

九、常见问题排查

502 Bad Gateway

后端服务未启动或无法连接。排查步骤:

  1. 确认后端服务是否运行:netstat -tlnp | grep :3000
  2. 检查 Nginx 错误日志:tail -f /var/log/nginx/error.log
  3. 测试直接访问后端:curl http://127.0.0.1:3000

504 Gateway Timeout

后端响应超时。增大 proxy_read_timeout 值,或检查后端是否存在慢接口。

请求头丢失

确保配置了 proxy_set_header 传递必要的请求头,特别是 HostX-Forwarded-* 系列头。

💡 最佳实践建议

将重复的 proxy 配置抽取为 snippet 文件,在多个 location 中通过 include 复用,减少配置冗余。同时建议对上游服务器启用 keepalive 长连接,显著降低 TCP 握手开销。