Nginx 反向代理与负载均衡实战
Nginx 是目前最流行的 Web 服务器之一,它的反向代理和负载均衡能力使其成为现代 Web 架构的核心组件。
基础反向代理
最简单的反向代理配置:
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://localhost: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 指令详解
proxy_pass
# 带路径替换
location /api/ {
proxy_pass http://backend/;
# 请求 /api/users → 代理到 http://backend/users
}
location /api/ {
proxy_pass http://backend;
# 请求 /api/users → 代理到 http://backend/api/users
}
proxy_set_header
location / {
proxy_pass http://backend;
# 传递真实客户端 IP
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 传递原始 Host
proxy_set_header Host $host;
# 传递协议信息
proxy_set_header X-Forwarded-Proto $scheme;
}
超时配置
location / {
proxy_pass http://backend;
# 连接超时
proxy_connect_timeout 10s;
# 发送超时
proxy_send_timeout 30s;
# 读取超时
proxy_read_timeout 30s;
}
WebSocket 代理
location /ws/ {
proxy_pass http://ws-backend;
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;
# WebSocket 需要更长的超时
proxy_read_timeout 3600s;
}
负载均衡
Round Robin(默认)
upstream backend {
server backend1.example.com;
server backend2.example.com;
server backend3.example.com;
}
server {
listen 80;
location / {
proxy_pass http://backend;
}
}
加权轮询
upstream backend {
server backend1.example.com weight=3;
server backend2.example.com weight=2;
server backend3.example.com weight=1;
# backend1 处理 50% 的请求
}
IP Hash(会话保持)
upstream backend {
ip_hash;
server backend1.example.com;
server backend2.example.com;
# 同一 IP 始终路由到同一服务器
}
Least Connections
upstream backend {
least_conn;
server backend1.example.com;
server backend2.example.com;
# 请求发送到活跃连接数最少的服务器
}
健康检查
upstream backend {
server backend1.example.com max_fails=3 fail_timeout=30s;
server backend2.example.com max_fails=3 fail_timeout=30s;
server backend3.example.com backup; # 备用服务器
# 30 秒内失败 3 次则标记为不可用
}
缓存配置
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m
max_size=10g inactive=60m use_temp_path=off;
server {
location /api/ {
proxy_pass http://backend;
proxy_cache my_cache;
proxy_cache_key "$scheme$request_method$host$request_uri";
proxy_cache_valid 200 10m;
proxy_cache_valid 404 1m;
proxy_cache_bypass $http_cache_control;
# 缓存状态头
add_header X-Cache-Status $upstream_cache_status;
}
}
限流
# 定义限流区域
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
server {
location /api/ {
# 请求速率限制:每秒 10 个,突发 20 个
limit_req zone=api_limit burst=20 nodelay;
# 并发连接数限制
limit_conn conn_limit 10;
proxy_pass http://backend;
}
}
完整生产配置示例
upstream app_backend {
least_conn;
server 10.0.1.10:3000 weight=2 max_fails=3 fail_timeout=30s;
server 10.0.1.11:3000 weight=2 max_fails=3 fail_timeout=30s;
server 10.0.1.12:3000 weight=1 max_fails=3 fail_timeout=30s;
keepalive 32;
}
server {
listen 80;
server_name example.com;
return 301 https://$server_name$request_uri;
}
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;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
# 安全头
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 Strict-Transport-Security "max-age=31536000" always;
# Gzip
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
# 静态文件
location /_next/static/ {
alias /app/.next/static/;
expires 365d;
add_header Cache-Control "public, immutable";
}
# API 代理
location /api/ {
proxy_pass http://app_backend;
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;
}
# 前端应用
location / {
proxy_pass http://app_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
}
调试技巧
# 自定义日志格式用于调试
log_format proxy_debug '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'upstream: $upstream_addr '
'upstream_status: $upstream_status '
'upstream_response_time: $upstream_response_time '
'request_time: $request_time';
# 验证配置
nginx -t
# 重新加载
nginx -s reload
# 查看 upstream 状态
curl http://localhost/nginx_status
总结
Nginx 的反向代理和负载均衡能力非常强大。掌握这些配置技巧,你就能构建高可用、高性能的 Web 服务架构。关键在于:
- 正确设置 proxy headers
- 选择合适的负载均衡策略
- 配置缓存和限流保护后端
- 做好健康检查和故障转移