Nginx 反向代理与负载均衡完全指南
前言
在现代 Web 架构中,反向代理和负载均衡是构建高可用、高性能服务的核心组件。Nginx 作为一款轻量级、高性能的 HTTP 服务器和反向代理服务器,凭借其出色的并发处理能力和低资源消耗,成为了业界的首选方案。
本文将从基础概念入手,逐步深入到实战配置、负载均衡策略、性能优化等方面,帮助你全面掌握 Nginx 反向代理与负载均衡的核心技术。
一、什么是反向代理
1.1 正向代理 vs 反向代理
正向代理:代理客户端访问外部服务,客户端知道自己在使用代理,服务器不知道真实客户端是谁。典型应用:翻墙、公司内网访问外网。
反向代理:代理服务器接收客户端请求,转发给后端真实服务器,客户端不知道真实服务器是谁。典型应用:负载均衡、缓存加速、SSL 卸载。
客户端 → 反向代理服务器 → 后端真实服务器集群1.2 反向代理的作用
- 负载均衡:将请求分发到多台后端服务器,提高系统吞吐量和可用性
- 缓存加速:缓存静态资源和动态内容,减少后端服务器压力
- SSL 卸载:统一处理 HTTPS 加密解密,降低后端服务器开销
- 安全防护:隐藏后端服务器真实 IP,提供 WAF、限流等安全功能
- 统一入口:通过域名路径路由到不同后端服务,实现服务聚合
二、Nginx 反向代理基础配置
2.1 最简单的反向代理
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:8080;
}
}这是最基础的配置,将所有请求转发到本地的 8080 端口。
2.2 常用代理参数
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 $scheme;
# 超时设置
proxy_connect_timeout 30s;
proxy_send_timeout 30s;
proxy_read_timeout 30s;
# 缓冲区设置
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
proxy_busy_buffers_size 8k;
}2.3 路径路由配置
通过不同路径转发到不同后端服务:
server {
listen 80;
server_name example.com;
# 静态资源由本地处理
location /static/ {
alias /var/www/static/;
expires 30d;
}
# API 请求转发到后端服务
location /api/ {
proxy_pass http://api-server:8080/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# 管理后台转发到另一台服务器
location /admin/ {
proxy_pass http://admin-server:8081/;
proxy_set_header Host $host;
}
# 其他请求转发到主站
location / {
proxy_pass http://web-server:8080;
proxy_set_header Host $host;
}
}注意:
proxy_pass末尾的斜杠很重要。加斜杠会把 location 匹配的部分去掉后再转发,不加斜杠则会把完整路径转发过去。
三、负载均衡策略详解
3.1 上游服务器配置
使用 upstream 定义后端服务器集群:
upstream backend_servers {
server 192.168.1.10:8080;
server 192.168.1.11:8080;
server 192.168.1.12:8080;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend_servers;
proxy_set_header Host $host;
}
}3.2 五种负载均衡策略
1. 轮询(默认)
请求按顺序逐一分配到不同后端服务器,是默认策略。
upstream backend {
server 192.168.1.10:8080;
server 192.168.1.11:8080;
}2. 加权轮询(weight)
根据权重分配请求,权重越高分配的请求越多。
upstream backend {
server 192.168.1.10:8080 weight=3; # 3/4 的请求
server 192.168.1.11:8080 weight=1; # 1/4 的请求
}适用场景:后端服务器性能差异较大时。
3. IP 哈希(ip_hash)
根据客户端 IP 地址的哈希结果分配服务器,同一客户端的请求始终落到同一台服务器上。
upstream backend {
ip_hash;
server 192.168.1.10:8080;
server 192.168.1.11:8080;
}适用场景:需要会话保持(Session Sticky)的场景。
缺点:如果客户端在 NAT 后面,所有用户会被分配到同一台服务器,导致负载不均。
4. 最少连接(least_conn)
将请求分配给当前连接数最少的后端服务器。
upstream backend {
least_conn;
server 192.168.1.10:8080;
server 192.168.1.11:8080;
}适用场景:请求处理时间差异较大的场景。
5. 最短响应时间(least_time) – Nginx Plus 功能
根据平均响应时间和连接数来分配请求,需要 Nginx Plus 商业版支持。
3.3 服务器状态参数
upstream backend {
server 192.168.1.10:8080 weight=5 max_fails=3 fail_timeout=30s;
server 192.168.1.11:8080 backup;
server 192.168.1.12:8080 down;
}weight:权重,默认 1max_fails:最大失败次数,超过后标记为不可用fail_timeout:失败超时时间,标记不可用后多久重试backup:备份服务器,只有所有主服务器都不可用时才启用down:标记服务器永久不可用
四、高级配置与优化
4.1 健康检查
Nginx 原生支持被动健康检查,通过 max_fails 和 fail_timeout 实现。
如果需要主动健康检查(定期探测后端健康状态),有两种方案:
方案一:使用 Nginx Plus 商业版
upstream backend {
zone backend 64k;
server 192.168.1.10:8080;
server 192.168.1.11:8080;
}
server {
location / {
proxy_pass http://backend;
health_check interval=5s fails=3 passes=2;
}
}方案二:使用 nginx_upstream_check_module 第三方模块
需要编译安装,配置示例:
upstream backend {
server 192.168.1.10:8080;
server 192.168.1.11:8080;
check interval=3000 rise=2 fall=5 timeout=1000 type=http;
check_http_send "GET /health HTTP/1.0\r\n\r\n";
check_http_expect_alive http_2xx http_3xx;
}4.2 缓存配置
# 在 http 块中定义缓存路径
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 / {
proxy_pass http://backend;
proxy_cache my_cache;
proxy_cache_valid 200 302 10m; # 200 和 302 响应缓存 10 分钟
proxy_cache_valid 404 1m; # 404 响应缓存 1 分钟
proxy_cache_valid any 1m; # 其他响应缓存 1 分钟
# 缓存键
proxy_cache_key $scheme$request_method$host$request_uri;
# 添加缓存状态头,方便调试
add_header X-Cache-Status $upstream_cache_status;
}
}4.3 SSL 卸载
将 HTTPS 加密解密工作放在 Nginx 层处理,后端服务器只需要处理 HTTP:
server {
listen 443 ssl http2;
server_name example.com;
# SSL 证书配置
ssl_certificate /etc/nginx/ssl/example.com.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
# SSL 优化
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
location / {
proxy_pass http://backend_servers;
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; # 告诉后端这是 HTTPS 请求
}
}
# HTTP 重定向到 HTTPS
server {
listen 80;
server_name example.com;
return 301 https://$server_name$request_uri;
}4.4 限流与防刷
# 定义限流区域(在 http 块中)
limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
server {
location /api/ {
# 请求限流:每秒最多 10 个请求,突发 20 个
limit_req zone=req_limit burst=20 nodelay;
# 连接数限制:每个 IP 最多 10 个连接
limit_conn conn_limit 10;
proxy_pass http://api_backend;
}
}五、性能优化建议
5.1 系统层面优化
文件描述符限制:
# 临时生效
ulimit -n 65535
# 永久生效,修改 /etc/security/limits.conf
* soft nofile 65535
* hard nofile 65535内核参数优化(/etc/sysctl.conf):
# 优化 TCP 连接
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 0 # 注意:NAT 环境下不要开启
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_max_syn_backlog = 8192
# 优化端口范围
net.ipv4.ip_local_port_range = 1024 65535
# 优化缓冲区
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 167772165.2 Nginx 配置优化
# worker 进程数,建议设置为 CPU 核心数
worker_processes auto;
# 每个 worker 进程的最大连接数
events {
worker_connections 65535;
use epoll;
multi_accept on;
}
http {
# 高效文件传输
sendfile on;
tcp_nopush on;
tcp_nodelay on;
# 长连接超时
keepalive_timeout 65;
keepalive_requests 100;
# 压缩
gzip on;
gzip_vary on;
gzip_min_length 1k;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml application/json application/javascript application/xml+rss;
# 隐藏版本号
server_tokens off;
}5.3 上游连接优化
upstream backend {
server 192.168.1.10:8080;
server 192.168.1.11:8080;
# 长连接配置
keepalive 32;
keepalive_timeout 60s;
keepalive_requests 100;
}
server {
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection ""; # 清除 Connection 头,支持长连接
}
}六、常见问题与排错
6.1 502 Bad Gateway
常见原因:
- 后端服务未启动或端口不对
- 后端服务响应超时
- 后端服务崩溃
排查步骤:
- 检查后端服务是否正常运行:
curl http://backend-ip:port - 查看 Nginx 错误日志:
tail -f /var/log/nginx/error.log - 调整超时时间:
proxy_read_timeout
6.2 504 Gateway Timeout
原因:后端处理时间过长,超过了 Nginx 的等待时间。
解决:
proxy_read_timeout 300s; # 增加读取超时
proxy_send_timeout 300s; # 增加发送超时6.3 获取真实客户端 IP
后端服务器看到的是 Nginx 的 IP,需要通过请求头传递真实 IP:
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;后端应用需要配置读取这些请求头。以 PHP 为例:
// 获取真实 IP
$real_ip = $_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR'];6.4 静态资源 404
检查 proxy_pass 的路径是否正确,注意末尾斜杠的区别:
# 不加斜杠:请求 /api/user 会转发为 http://backend/api/user
location /api/ {
proxy_pass http://backend;
}
# 加斜杠:请求 /api/user 会转发为 http://backend/user
location /api/ {
proxy_pass http://backend/;
}七、完整配置示例
下面是一个生产环境可用的完整配置示例:
# 上游服务器组
upstream app_backend {
least_conn;
server 192.168.1.10:8080 weight=3 max_fails=3 fail_timeout=30s;
server 192.168.1.11:8080 weight=2 max_fails=3 fail_timeout=30s;
server 192.168.1.12:8080 weight=1 max_fails=3 fail_timeout=30s;
server 192.168.1.13:8080 backup;
keepalive 64;
}
# 缓存配置
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=static_cache:100m max_size=10g inactive=7d use_temp_path=off;
# 限流配置
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=20r/s;
server {
listen 80;
server_name example.com www.example.com;
return 301 https://example.com$request_uri;
}
server {
listen 443 ssl http2;
server_name example.com;
# SSL 配置
ssl_certificate /etc/nginx/ssl/example.com.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
# 静态资源缓存
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2?)$ {
proxy_pass http://app_backend;
proxy_cache static_cache;
proxy_cache_valid 200 30d;
proxy_cache_valid 404 1h;
expires 30d;
add_header Cache-Control "public, immutable";
}
# API 接口
location /api/ {
limit_req zone=api_limit burst=40 nodelay;
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_read_timeout 60s;
proxy_send_timeout 60s;
}
# 其他请求
location / {
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;
}
}总结
Nginx 反向代理和负载均衡是构建高可用 Web 架构的基础。通过本文的介绍,你应该能够:
- 理解反向代理的概念和作用
- 掌握 Nginx 反向代理的基础配置
- 灵活运用五种负载均衡策略
- 配置缓存、SSL 卸载、限流等高级功能
- 进行系统和 Nginx 层面的性能优化
- 排查常见的 502、504 等问题
在实际生产环境中,建议根据业务特点选择合适的负载均衡策略,并结合监控系统实时观察后端服务器的负载情况,不断调优配置参数。
参考资料: