Skip to content

反向代理与负载均衡

正向代理与反向代理

类型代表的一方客户端是否明确知道最终目标常见用途
Forward ProxyClient通常知道出口代理、访问控制
Reverse ProxyServer通常只访问代理地址入口路由、TLS Termination、Load Balancing

Nginx HTTP Module 的典型用途是 Reverse Proxy。它并不是开箱即用的通用 HTTPS Forward Proxy。

最小反向代理

nginx
location /api/ {
    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 3s;
    proxy_read_timeout 30s;
    proxy_send_timeout 30s;
}

Application 只有在请求来自可信 Proxy 时才能信任 ForwardedX-Forwarded-For 等 Header。边界 Proxy 应覆盖外部伪造值,应用应配置可信 Proxy 范围。

Upstream

nginx
upstream backend {
    least_conn;
    server app-1.example.net:8080 weight=2 max_fails=2 fail_timeout=10s;
    server app-2.example.net:8080 max_fails=2 fail_timeout=10s;
    keepalive 32;
}

server {
    location /api/ {
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_pass http://backend;
    }
}
方法选择方式适用边界
Round Robin默认轮询,Weight 可影响比例请求成本接近
least_connActive Connection 较少者优先请求耗时差异较大
ip_hash根据 Client IP Hash粗粒度粘滞,受 NAT/Proxy 和地址变化影响
hash key consistent根据指定 Key 做 Consistent HashCache Sharding 等场景

ip_hash 不是 Session Sharing。可靠方案是 Stateless Session、Shared Session Store 或业务 Token;粘滞路由只能降低跨实例概率,还会带来流量倾斜。

被动健康检查与重试

Open Source Nginx 常用 max_failsfail_timeoutproxy_next_upstream 做被动失败判断。请求失败后是否换 Upstream 取决于错误类型、配置以及 Response 是否已发送给 Client。

自动重试非幂等请求可能重复创建订单或扣款。应限制重试条件和次数,并为业务操作设计 Idempotency Key。

WebSocket

nginx
map $http_upgrade $connection_upgrade {
    default upgrade;
    ""      close;
}

location /ws/ {
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
    proxy_pass http://backend;
}

WebSocket 的 UpgradeConnection 是 Hop-by-hop Header,需要显式传给 Upstream。

uWSGI

旧 Django 笔记的 uWSGI 链路仍可理解,但 CentOS 7 安装命令不应照搬:

nginx
location / {
    include uwsgi_params;
    uwsgi_pass unix:/run/myapp/uwsgi.sock;
}

uwsgi_pass 使用 uwsgi Protocol;若 Application Server 暴露 HTTP,则使用 proxy_pass,两者不可混用。