Nginx核心-反向代理与负载均衡
大约 9 分钟
Nginx核心-反向代理与负载均衡
业务场景引入
在构建一个大型电商平台时,系统架构师面临以下挑战:
- 高并发访问处理:平台在促销活动期间需要同时处理数十万用户请求
- 服务解耦需求:用户服务、商品服务、订单服务需要独立部署和扩展
- 故障容错机制:当某个服务实例出现故障时,系统应自动切换到健康实例
- 性能优化要求:需要合理分配请求负载,避免单点过载
- 安全访问控制:对外暴露统一入口,隐藏内部服务细节
这些需求正是Nginx反向代理和负载均衡功能的核心应用场景。通过合理配置,Nginx可以作为系统的统一入口,实现请求分发、故障转移、性能优化等关键功能。
反向代理深度解析
反向代理基本概念
反向代理是一种服务器架构模式,代理服务器接收客户端的请求,然后将请求转发给一个或多个后端服务器,最后将从后端服务器得到的结果返回给客户端。客户端通常不知道实际处理请求的是哪台服务器。
反向代理的优势
- 安全性增强:隐藏后端服务器信息,防止直接暴露
- 负载分担:将请求分发到多个服务器,提高整体处理能力
- 缓存加速:缓存静态内容,减少后端服务器压力
- SSL终止:在代理层处理SSL加密解密,减轻后端负担
- 压缩优化:在代理层进行内容压缩,减少网络传输
基础反向代理配置
# 基础反向代理配置
server {
    listen 80;
    server_name api.example.com;
    
    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 $scheme;
        
        # 超时设置
        proxy_connect_timeout 30s;
        proxy_send_timeout 30s;
        proxy_read_timeout 30s;
        
        # 缓冲区设置
        proxy_buffering on;
        proxy_buffer_size 4k;
        proxy_buffers 8 4k;
    }
}
# 后端服务器定义
upstream backend_servers {
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;
}高级反向代理配置
# 高级反向代理配置
server {
    listen 443 ssl http2;
    server_name api.example.com;
    
    # SSL配置
    ssl_certificate /etc/nginx/ssl/api.example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/api.example.com.key;
    
    # 安全头设置
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    
    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 $scheme;
        proxy_set_header X-Forwarded-Port $server_port;
        
        # 连接和超时设置
        proxy_connect_timeout 10s;
        proxy_send_timeout 30s;
        proxy_read_timeout 30s;
        proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
        
        # 缓冲区优化
        proxy_buffering on;
        proxy_buffer_size 128k;
        proxy_buffers 4 256k;
        proxy_busy_buffers_size 256k;
        
        # WebSocket支持
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
    
    # 健康检查端点
    location /health {
        access_log off;
        return 200 "healthy\n";
        add_header Content-Type text/plain;
    }
}
# 后端服务器组
upstream backend_servers {
    # 最少连接算法
    least_conn;
    
    # 服务器配置
    server 192.168.1.10:8080 weight=3 max_fails=3 fail_timeout=30s;
    server 192.168.1.11:8080 weight=3 max_fails=3 fail_timeout=30s;
    server 192.168.1.12:8080 weight=2 max_fails=3 fail_timeout=30s;
    server 192.168.1.13:8080 backup;  # 备用服务器
}不同协议的反向代理
HTTP/HTTPS反向代理
# HTTP反向代理
location /api/ {
    proxy_pass http://backend_api;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# HTTPS反向代理
location /secure-api/ {
    proxy_pass https://secure_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;
    
    # SSL相关设置
    proxy_ssl_verify off;
    proxy_ssl_session_reuse on;
}TCP/UDP反向代理(Stream模块)
# TCP反向代理配置
stream {
    upstream mysql_backend {
        server 192.168.1.10:3306;
        server 192.168.1.11:3306;
    }
    
    server {
        listen 3306;
        proxy_pass mysql_backend;
        proxy_timeout 1s;
        proxy_responses 1;
    }
    
    # UDP反向代理
    upstream dns_backend {
        server 192.168.1.10:53;
        server 192.168.1.11:53;
    }
    
    server {
        listen 53 udp;
        proxy_pass dns_backend;
    }
}负载均衡算法详解
轮询算法(Round Robin)
轮询是最简单的负载均衡算法,按顺序将请求分发给每个服务器。
upstream backend {
    # 默认使用轮询算法
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;
}加权轮询算法(Weighted Round Robin)
根据服务器权重分配请求,权重高的服务器处理更多请求。
upstream backend {
    # 加权轮询算法
    server 192.168.1.10:8080 weight=5;  # 50%的请求
    server 192.168.1.11:8080 weight=3;  # 30%的请求
    server 192.168.1.12:8080 weight=2;  # 20%的请求
}最少连接算法(Least Connections)
将请求发送给当前连接数最少的服务器。
upstream backend {
    # 最少连接算法
    least_conn;
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;
}IP哈希算法(IP Hash)
根据客户端IP地址进行哈希计算,确保同一客户端始终访问同一服务器。
upstream backend {
    # IP哈希算法
    ip_hash;
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;
}通用哈希算法(Hash)
根据指定的键进行哈希计算。
upstream backend {
    # 通用哈希算法
    hash $request_uri consistent;
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;
}
# 或者根据其他变量进行哈希
upstream backend {
    hash $cookie_user consistent;
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;
}随机算法(Random)
随机选择服务器,可配合权重使用。
upstream backend {
    # 随机算法
    random;
    server 192.168.1.10:8080 weight=3;
    server 192.168.1.11:8080 weight=2;
    server 192.168.1.12:8080 weight=1;
}负载均衡高级配置
服务器状态控制
upstream backend {
    server 192.168.1.10:8080 weight=3;           # 正常服务器
    server 192.168.1.11:8080 weight=2 down;     # 永久下线
    server 192.168.1.12:8080 weight=1 backup;   # 备用服务器
    server 192.168.1.13:8080 max_fails=3 fail_timeout=30s;  # 故障检测
}健康检查配置
upstream backend {
    server 192.168.1.10:8080 max_fails=2 fail_timeout=10s;
    server 192.168.1.11:8080 max_fails=2 fail_timeout=10s;
    server 192.168.1.12:8080 max_fails=2 fail_timeout=10s;
    
    # 健康检查相关指令
    keepalive 32;           # 保持连接数
    keepalive_requests 100; # 每个连接的最大请求数
    keepalive_timeout 60s;  # 保持连接超时时间
}会话保持配置
# 方法1:使用IP哈希
upstream backend {
    ip_hash;
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;
}
# 方法2:使用Cookie
location / {
    proxy_pass http://backend;
    proxy_set_header Host $host;
    
    # 设置sticky cookie
    proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict";
}
# 方法3:使用upstream的sticky模块(需要第三方模块)
upstream backend {
    sticky cookie srv_id expires=1h domain=.example.com path=/;
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;
}实际应用场景配置
电商网站负载均衡
# 电商网站反向代理配置
upstream user_service {
    least_conn;
    server 192.168.1.10:8080 weight=3 max_fails=3 fail_timeout=30s;
    server 192.168.1.11:8080 weight=3 max_fails=3 fail_timeout=30s;
    server 192.168.1.12:8080 backup;
}
upstream product_service {
    least_conn;
    server 192.168.2.10:8080 weight=2 max_fails=3 fail_timeout=30s;
    server 192.168.2.11:8080 weight=2 max_fails=3 fail_timeout=30s;
    server 192.168.2.12:8080 weight=1 max_fails=3 fail_timeout=30s;
}
upstream order_service {
    least_conn;
    server 192.168.3.10:8080 max_fails=3 fail_timeout=30s;
    server 192.168.3.11:8080 max_fails=3 fail_timeout=30s;
}
server {
    listen 80;
    server_name shop.example.com;
    
    # 用户服务路由
    location /api/users/ {
        proxy_pass http://user_service;
        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 5s;
        proxy_send_timeout 10s;
        proxy_read_timeout 10s;
    }
    
    # 商品服务路由
    location /api/products/ {
        proxy_pass http://product_service;
        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 3s;
        proxy_send_timeout 5s;
        proxy_read_timeout 5s;
    }
    
    # 订单服务路由
    location /api/orders/ {
        proxy_pass http://order_service;
        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_send_timeout 30s;
        proxy_read_timeout 30s;
    }
    
    # 静态资源代理
    location /static/ {
        proxy_pass http://static_servers;
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
}微服务架构负载均衡
# 微服务架构配置
upstream auth_service {
    least_conn;
    server auth1.internal:8080 weight=2;
    server auth2.internal:8080 weight=2;
    server auth3.internal:8080 backup;
}
upstream payment_service {
    least_conn;
    server payment1.internal:8080;
    server payment2.internal:8080;
}
upstream notification_service {
    least_conn;
    server notification1.internal:8080;
    server notification2.internal:8080;
    server notification3.internal:8080;
}
server {
    listen 80;
    server_name api.microservices.example.com;
    
    # 认证服务
    location /auth/ {
        proxy_pass http://auth_service;
        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 2s;
        proxy_send_timeout 5s;
        proxy_read_timeout 5s;
    }
    
    # 支付服务
    location /payment/ {
        proxy_pass http://payment_service;
        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 5s;
        proxy_send_timeout 15s;
        proxy_read_timeout 15s;
    }
    
    # 通知服务
    location /notification/ {
        proxy_pass http://notification_service;
        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 3s;
        proxy_send_timeout 10s;
        proxy_read_timeout 10s;
    }
    
    # 健康检查端点
    location /health {
        access_log off;
        return 200 "healthy\n";
        add_header Content-Type text/plain;
    }
}容器化环境负载均衡
# Docker/Kubernetes环境配置
upstream app_backend {
    # 使用DNS解析动态发现服务
    server app-service:8080 resolve;
    server app-service:8081 resolve;
    keepalive 32;
}
server {
    listen 80;
    server_name app.example.com;
    
    location / {
        proxy_pass http://app_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 2s;
        proxy_send_timeout 5s;
        proxy_read_timeout 5s;
        
        # 启用keepalive
        proxy_http_version 1.1;
        proxy_set_header Connection "";
    }
    
    # 健康检查
    location /health {
        proxy_pass http://app_backend/health;
        proxy_connect_timeout 1s;
        proxy_send_timeout 2s;
        proxy_read_timeout 2s;
    }
}性能优化配置
连接池优化
upstream backend {
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    
    # 连接池配置
    keepalive 32;           # 保持连接数
    keepalive_requests 100; # 每个连接的最大请求数
    keepalive_timeout 60s;  # 保持连接超时时间
}
server {
    location / {
        proxy_pass http://backend;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
    }
}缓冲区优化
upstream backend {
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
}
server {
    location / {
        proxy_pass http://backend;
        
        # 缓冲区优化
        proxy_buffering on;
        proxy_buffer_size 128k;
        proxy_buffers 4 256k;
        proxy_busy_buffers_size 256k;
        proxy_temp_file_write_size 256k;
        
        # 大文件传输优化
        proxy_max_temp_file_size 1024m;
    }
}超时优化
upstream backend {
    server 192.168.1.10:8080 max_fails=3 fail_timeout=10s;
    server 192.168.1.11:8080 max_fails=3 fail_timeout=10s;
}
server {
    location / {
        proxy_pass http://backend;
        
        # 超时优化
        proxy_connect_timeout 5s;    # 连接超时
        proxy_send_timeout 10s;      # 发送超时
        proxy_read_timeout 10s;      # 读取超时
        
        # 下游服务器故障转移
        proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
        proxy_next_upstream_timeout 10s;
        proxy_next_upstream_tries 3;
    }
}监控与日志配置
负载均衡状态监控
# 启用状态页面
server {
    listen 8080;
    server_name localhost;
    
    location /nginx_status {
        stub_status on;
        access_log off;
        allow 127.0.0.1;
        deny all;
    }
    
    location /upstream_status {
        upstream_show;
        access_log off;
        allow 127.0.0.1;
        deny all;
    }
}详细日志配置
# 自定义日志格式
log_format upstream_log '$remote_addr - $remote_user [$time_local] "$request" '
                        '$status $body_bytes_sent "$http_referer" '
                        '"$http_user_agent" "$http_x_forwarded_for" '
                        'upstream_addr=$upstream_addr '
                        'upstream_status=$upstream_status '
                        'request_time=$request_time '
                        'upstream_response_time=$upstream_response_time '
                        'upstream_connect_time=$upstream_connect_time';
upstream backend {
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
}
server {
    access_log /var/log/nginx/upstream_access.log upstream_log;
    
    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;
    }
}故障处理与恢复
自动故障检测
upstream backend {
    server 192.168.1.10:8080 max_fails=2 fail_timeout=10s;
    server 192.168.1.11:8080 max_fails=2 fail_timeout=10s;
    server 192.168.1.12:8080 max_fails=2 fail_timeout=10s;
    
    # 故障恢复配置
    keepalive 32;
}
server {
    location / {
        proxy_pass http://backend;
        
        # 故障转移配置
        proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
        proxy_next_upstream_timeout 10s;
        proxy_next_upstream_tries 3;
    }
}手动服务器管理
# 通过upstream_conf模块动态管理服务器
upstream backend {
    zone backend 64k;
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
}
server {
    location /upstream_conf {
        upstream_conf;
        allow 127.0.0.1;
        deny all;
    }
}
# 管理命令示例:
# 添加服务器: curl 'http://localhost/upstream_conf?upstream=backend&server=192.168.1.12:8080&weight=2'
# 移除服务器: curl 'http://localhost/upstream_conf?upstream=backend&remove=&server=192.168.1.10:8080'
# 修改权重: curl 'http://localhost/upstream_conf?upstream=backend&server=192.168.1.11:8080&weight=3'最佳实践总结
配置优化建议
- 合理选择负载均衡算法 - 一般场景使用最少连接算法
- 需要会话保持使用IP哈希
- 特殊需求使用通用哈希
 
- 服务器健康检测 - 设置合适的max_fails和fail_timeout
- 配置proxy_next_upstream实现故障转移
- 定期监控服务器状态
 
- 性能调优 - 启用连接池减少连接开销
- 合理配置缓冲区大小
- 优化超时设置
 
- 安全配置 - 限制管理接口访问
- 隐藏版本信息
- 设置适当的访问控制
 
常见问题处理
- 负载不均衡 - 检查服务器权重配置
- 确认负载均衡算法选择
- 监控各服务器连接数
 
- 连接超时 - 调整proxy_connect_timeout
- 检查后端服务器性能
- 优化网络配置
 
- 会话丢失 - 使用IP哈希或sticky cookie
- 检查应用程序会话存储
- 配置适当的故障转移策略
 
通过深入理解Nginx的反向代理和负载均衡功能,可以构建高可用、高性能的Web应用架构。在实际应用中,需要根据具体业务需求和系统特点,合理配置相关参数,持续监控和优化系统性能。
