Nginx 反向代理与负载均衡实战:从单机到多节点的高可用方案 原创
引言
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 终结到缓存限流,每个环节都直接影响线上稳定性。核心原则:先跑通最小可用配置,再根据监控数据逐步优化,避免一上来就全量配置导致排障困难。