找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

2810

积分

0

好友

374

主题
发表于 1 小时前 | 查看: 2| 回复: 0

很多运维工程师对反向代理的理解停留在“配置一下 proxy_pass”的层面,但对底层原理、负载均衡算法、会话保持机制等核心概念一知半解。这篇文章将从网络协议层面讲清反向代理的本质,详细介绍 Nginx 反向代理的配置、负载均衡策略、缓存机制、高可用方案,帮助你从“会用”提升到“精通”。

前置知识:HTTP 协议基础、TCP/IP 基础
实验环境:CentOS Stream 9 / Ubuntu 24.04 LTS,Nginx 1.26+

1 反向代理的本质

1.1 正向代理 vs 反向代理

正向代理(Forward Proxy):
                          客户端                代理服务器              目标服务器
                             |                    |                    |
    用户配置代理              | ───── GET / ────> |                    |
    请求发送到代理            |                    | ───── GET / ────────> |
                             |                    |                    |
    代理转发请求              |                    | <──── 200 OK ─────── |
                             |                    |                    |
    返回结果给用户            | <──── 200 OK ──── |                    |
                             |                    |                    |
    用途:翻墙、缓存、匿名访问

反向代理(Reverse Proxy):
                          客户端                代理服务器              目标服务器
                             |                    |                    |
    用户不知道真实服务器        | ───── GET / ────> |                    |
    请求发到代理               |                    | ───── GET / ────────> |
                             |                    | <──── 200 OK ─────── |
    代理转发给后端             |                    |                    |
                             | <──── 200 OK ──── |                    |
    返回结果给用户            |                    |                    |
                             |                    |                    |
    用途:负载均衡、安全防护、缓存加速

1.2 反向代理的工作原理

                   ┌─────────────────────────────────────────────────────┐
                   │                   Nginx 反向代理                      │
                   │                                                     │
                   │   接收请求                                           │
                   │      │                                               │
                   │      ▼                                               │
                   │   ┌──────────────┐                                   │
                   │   │ 协议解析     │ 解析 HTTP 请求头、正文             │
                   │   └──────────────┘                                   │
                   │      │                                               │
                   │      ▼                                               │
                   │   ┌──────────────┐                                   │
                   │   │ 连接池管理   │ 管理与后端服务器的连接              │
                   │   └──────────────┘                                   │
                   │      │                                               │
                   │      ▼                                               │
                   │   ┌──────────────┐                                   │
                   │   │ 负载均衡     │ 选择合适的后端服务器                │
                   │   └──────────────┘                                   │
                   │      │                                               │
                   │      ▼                                               │
                   │   ┌──────────────┐                                   │
   客户端 ────────> │   │ 请求转发     │ 转发请求到后端                    │
                   │   └──────────────┘                                   │
                   │      │                                               │
                   │      ▼                                               │
                   │   ┌──────────────┐                                   │
                   │   │ 响应处理     │ 接收后端响应,处理头信息            │
                   │   └──────────────┘                                   │
                   │      │                                               │
                   │      ▼                                               │
   客户端 <──────── │   ┌──────────────┐                                   │
                   │   │ 缓存处理     │ 如果配置了缓存                     │
                   │   └──────────────┘                                   │
                   │      │                                               │
                   │      ▼                                               │
                   │   ┌──────────────┐                                   │
                   │   │ 日志记录     │ 记录访问日志                      │
                   │   └──────────────┘                                   │
                   │                                                     │
                   └─────────────────────────────────────────────────────┘

1.3 反向代理的优势

# 反向代理核心优势示例

upstream backend {
    server 127.0.0.1:8080;
    server 127.0.0.1:8081;
}

server {
    listen 80;
    server_name example.com;

    # 优势 1: 隐藏真实后端
    # 客户端只能看到 Nginx,不知道后端有几台服务器
    location / {
        proxy_pass http://backend;
    }

    # 优势 2: 负载均衡
    # 自动分发请求到不同后端
    # 配合 upstream 实现

    # 优势 3: SSL 终结
    # 后端无需配置 SSL,Nginx 统一处理
    # 节省后端资源

    # 优势 4: 缓存加速
    # 静态资源缓存,减少后端压力

    # 优势 5: 安全防护
    # 过滤恶意请求,防护 DDoS

    # 优势 6: 灰度发布
    # 按比例分流到不同版本
}

2 基础反向代理配置

2.1 最简反向代理

server {
    listen 80;
    server_name example.com;

    # 代理到后端
    location / {
        proxy_pass http://127.0.0.1:8080;
    }
}

2.2 完整代理配置

server {
    listen 80;
    server_name 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_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Port $server_port;

        # HTTP 版本
        proxy_http_version 1.1;

        # 连接管理
        proxy_set_header Connection "";

        # 超时配置
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;

        # 缓冲配置
        proxy_buffering on;
        proxy_buffer_size 4k;
        proxy_buffers 8 4k;
        proxy_busy_buffers_size 8k;

        # 错误处理
        proxy_intercept_errors on;
        proxy_next_upstream error timeout http_502 http_503 http_504;
    }
}

2.3 代理头信息详解

# 常用代理头说明

# Host: 请求的主机名
# 客户端: GET / HTTP/1.1
#         Host: example.com
# Nginx:  GET / HTTP/1.1
#         Host: example.com

# X-Real-IP: 客户端真实 IP
# 客户端 IP: 203.0.113.10
# Nginx 添加: X-Real-IP: 203.0.113.10

# X-Forwarded-For: 经过的代理链
# X-Forwarded-For: 203.0.113.10, 10.0.0.1, 192.168.1.1
#                客户端IP    第一层代理  第二层代理

# X-Forwarded-Proto: 原始协议
# X-Forwarded-Proto: https

# 测试代理头
curl -v http://example.com 2>&1 | grep -E "^> (Host|X-Real-IP|X-Forwarded)"

2.4 日志配置

# 记录代理相关信息
log_format proxy_log '$remote_addr - $remote_user [$time_local] '
                     '"$request" '
                     '$status $body_bytes_sent '
                     '"$http_referer" '
                     '"$http_user_agent" '
                     'rt=$request_time '
                     'uct="$upstream_connect_time" '
                     'uht="$upstream_header_time" '
                     'urt="$upstream_response_time" '
                     'u="$upstream_addr"';

access_log /var/log/nginx/proxy.log proxy_log;

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://backend;
        # 只记录错误日志
        access_log off;
    }

    location /api/ {
        proxy_pass http://api_backend;
        # 详细记录 API 请求
        access_log /var/log/nginx/api.log proxy_log;
    }
}

3 负载均衡策略

3.1 轮询(Round Robin)

# 默认策略,按顺序逐个分配
upstream backend {
    server 127.0.0.1:8080;
    server 127.0.0.1:8081;
    server 127.0.0.1:8082;
}

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://backend;
    }
}

# 请求分配序列:
# 请求1 -> 127.0.0.1:8080
# 请求2 -> 127.0.0.1:8081
# 请求3 -> 127.0.0.1:8082
# 请求4 -> 127.0.0.1:8080
# ...循环

3.2 加权轮询(Weighted Round Robin)

# weight 越大,被选中的概率越高
upstream backend {
    server 127.0.0.1:8080 weight=5;
    server 127.0.0.1:8081 weight=2;
    server 127.0.0.1:8082 weight=1;
}

# 请求分配比例:
# 8080: 5/(5+2+1) = 62.5%
# 8081: 2/(5+2+1) = 25%
# 8082: 1/(5+2+1) = 12.5%

3.3 IP 哈希(IP Hash)

# 同一 IP 的请求始终发送到同一后端
upstream backend {
    ip_hash;
    server 127.0.0.1:8080;
    server 127.0.0.1:8081;
    server 127.0.0.1:8082;
}

# 场景:需要会话保持时使用
# 注意:后端服务器变更时,可能导致会话丢失

3.4 最少连接(Least Connections)

# 将请求发送到当前连接数最少的服务器
upstream backend {
    least_conn;
    server 127.0.0.1:8080;
    server 127.0.0.1:8081;
    server 127.0.0.1:8082;
}

# 场景:请求处理时间差异较大时使用

3.5 Hash 哈希(Generic Hash)

# 根据任意 key 分配请求
upstream backend {
    hash $request_uri consistent;
    server 127.0.0.1:8080;
    server 127.0.0.1:8081;
}

# consistent: 开启一致性哈希,减少服务器变更时的数据迁移
# $request_uri: 根据请求 URI 分配
# 也可以用 $cookie_jsessionid 等

3.6 随机(Random)

# 随机选择两台服务器,然后选择其中一台
upstream backend {
    random two [method=round_robin];
    server 127.0.0.1:8080;
    server 127.0.0.1:8081;
    server 127.0.0.1:8082;
    server 127.0.0.1:8083;
}

# method:
# round_robin: 默认,选择连接数最少的
# iqm: 至少 2 个请求后比较
# fair: 连接数最少的(需要第三方模块)

3.7 负载均衡算法对比

算法 特点 适用场景
round_robin 默认,均匀分配 后端性能一致
weighted 按权重分配 后端性能不一致
ip_hash 会话保持 有状态服务
least_conn 负载感知 长连接服务
hash 自定义 key 缓存命中
random 随机选择 无状态服务

4 健康检查配置

4.1 被动健康检查

# 被动检查:只检查失败的请求
upstream backend {
    server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
    server 127.0.0.1:8081 max_fails=3 fail_timeout=30s;
    # max_fails: 失败次数达到此值认为服务器不可用
    # fail_timeout: 服务器不可用持续时间
}

# 参数说明:
# max_fails=3: 30 秒内连续 3 次失败,标记为不可用
# fail_timeout=30s: 30 秒后重新尝试

4.2 主动健康检查(第三方模块)

# 需要 nginx-upstream-check-module

upstream backend {
    zone backend 64k;

    # 添加健康检查
    check interval=3000 rise=2 fall=3 timeout=1000 type=http;
    check_http_send "GET /health HTTP/1.0\r\n\r\n";
    check_http_expect_alive http_2xx http_3xx;

    server 127.0.0.1:8080;
    server 127.0.0.1:8081;
}

# interval: 检查间隔(毫秒)
# rise: 连续成功次数,恢复为可用
# fall: 连续失败次数,标记为不可用
# timeout: 检查超时(毫秒)
# type: 检查类型(tcp|http|ssl_hello|mysql|ajp)

4.3 健康检查端点

# 后端应用提供健康检查端点
server {
    listen 8080;
    server_name _;

    # 健康检查
    location /health {
        access_log off;
        return 200 "OK\n";
        add_header Content-Type text/plain;
    }

    # 就绪检查(检查依赖服务)
    location /ready {
        access_log off;
        # 检查数据库连接
        # 如果依赖不可用,返回 503
        set $ready 1;
        if ($database_connected = 0) {
            set $ready 0;
        }
        if ($ready = 0) {
            return 503;
        }
        return 200 "Ready\n";
    }

    # 应用主路由
    location / {
        # 应用代码
    }
}

5 会话保持机制

HTTP 无状态协议的问题:
    1. 用户登录后,下一个请求无法识别用户身份
    2. 购物车、用户信息等无法跨请求保持

解决方案:
    1. Session + Cookie
    2. Token(JWT等)
    3. URL 参数

会话保持的挑战:
    - 多台后端服务器
    - 如何让同一用户的请求打到同一台服务器

5.2 Nginx 会话保持方案

# 方案 1: ip_hash(简单但有限制)
upstream backend {
    ip_hash;
    server 127.0.0.1:8080;
    server 127.0.0.1:8081;
}

# 方案 2: Cookie 标记
upstream backend {
    server 127.0.0.1:8080;
    server 127.0.0.1:8081;
    # 如果后端服务器会添加 cookie
    # 可以使用 $cookie_name 来做 hash
}

# 方案 3: URI 参数标记
upstream backend {
    hash $cookie_jsessionid;
    server 127.0.0.1:8080;
    server 127.0.0.1:8081;
}

# 方案 4: 基于后端的会话保持响应
# 后端在首次响应时设置 cookie
# Nginx 通过 cookie 识别用户
upstream backend {
    hash $cookie_PHPSESSID consistent;
    server 127.0.0.1:8080;
    server 127.0.0.1:8081;
}

5.3 分布式会话问题

# 问题:Nginx ip_hash 不够精确
# 原因:NAT 环境下,多个用户共享同一出口 IP

# 解决方案 1: 后端标记
# 应用在 cookie 中存储 session_id
# 后端共享 session 到 Redis/Memcached

# 解决方案 2: JWT 无状态会话
# 不需要后端存储 session
# session 信息加密在 token 中

# 解决方案 3: Sticky Session(应用层)
upstream backend {
# 使用 sticky cookie
    sticky cookie srv_id expires=1h domain=.example.com path=/;
    server 127.0.0.1:8080;
    server 127.0.0.1:8081;
}

5.4 Session 共享配置

# Redis Session 共享示例(PHP)
# /etc/php.ini 或 .user.ini
session.save_handler = redis
session.save_path = "tcp://127.0.0.1:6379?database=0"

# 或者在代码中
<?php
ini_set('session.save_handler', 'redis');
ini_set('session.save_path', 'tcp://127.0.0.1:6379?database=0');
?>

# Java Spring Session
# application.yml
# spring:
#   data:
#     redis:
#       host: localhost
#       port: 6379

6 代理缓存配置

6.1 缓存机制原理

代理缓存工作流程:

客户端请求 -> Nginx 缓存检查
                 │
                 ├── 命中(HIT)
                 │      └── 直接返回缓存
                 │
                 └── 未命中(MISS)
                        │
                        └── 转发给后端
                               │
                               ├── 后端返回
                               │      └── 存储到缓存
                               │      └── 返回给客户端
                               │
                               └── 缓存命中时直接返回

6.2 缓存配置

# 定义缓存目录和大小
proxy_cache_path /var/cache/nginx levels=1:2
                 keys_zone=api_cache:100m
                 max_size=10g
                 inactive=60m
                 use_temp_path=off;

# 定义缓存 Key
proxy_cache_key "$scheme$request_method$host$request_uri";

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://backend;

        # 启用缓存
        proxy_cache api_cache;

        # 缓存有效期
        proxy_cache_valid 200 60m;    # 200 响应缓存 60 分钟
        proxy_cache_valid 404 10m;    # 404 响应缓存 10 分钟
        proxy_cache_valid any 5m;     # 其他响应缓存 5 分钟

        # 缓存控制头
        proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
        proxy_cache_background_update on;
        proxy_cache_lock on;

        # 绕过缓存的条件
        proxy_cache_bypass $cookie_nocache $arg_nocache;
        proxy_no_cache $cookie_nocache $arg_nocache;

        # 添加缓存状态头
        add_header X-Cache-Status $upstream_cache_status;
    }
}

# $upstream_cache_status 值:
# MISS: 未命中,请求被传递到后端
# HIT: 命中,返回缓存内容
# EXPIRED: 缓存过期,验证后返回
# STALE: 返回过期缓存(后端不可用)
# UPDATING: 缓存过期,正在更新
# REVALIDATED: 缓存验证通过

6.3 缓存清理

# 缓存清理配置(需要 ngx_cache_purge 模块)

proxy_cache_path /var/cache/nginx levels=1:2
                 keys_zone=api_cache:100m
                 max_size=10g
                 inactive=60m;

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://backend;
        proxy_cache api_cache;
    }

    # 缓存清理接口
    location ~ /purge(/.*) {
        proxy_cache_purge api_cache "$scheme$request_method$host$1";
        # 仅允许特定 IP
        allow 127.0.0.1;
        allow 10.0.0.0/8;
        deny all;
    }
}

# 清理缓存示例
# curl -X PURGE http://example.com/api/data

6.4 全面缓存配置示例

proxy_cache_path /var/cache/nginx/api levels=1:2:3
                 keys_zone=api_cache:100m
                 max_size=10g
                 inactive=7d
                 use_temp_path=off;

proxy_cache_path /var/cache/nginx/static levels=1:2
                 keys_zone=static_cache:50m
                 max_size=5g
                 inactive=30d;

server {
    listen 80;
    server_name example.com;

    # API 缓存
    location /api/ {
        proxy_pass http://api_backend;
        proxy_cache api_cache;
        proxy_cache_valid 200 5m;
        proxy_cache_valid 404 1m;
        proxy_cache_use_stale error timeout updating;
        proxy_cache_lock on;
        add_header X-Cache-Status $upstream_cache_status;
        # 不缓存 POST PUT DELETE
        proxy_cache_methods GET HEAD POST;
        proxy_cache_bypass $cookie_nocache $arg_nocache $arg_cache;
        proxy_no_cache $cookie_nocache $arg_nocache $request_method;
    }

    # 静态资源缓存
    location /static/ {
        proxy_pass http://static_backend;
        proxy_cache static_cache;
        proxy_cache_valid 200 30d;
        proxy_cache_valid 404 1m;
        expires 30d;
        add_header Cache-Control "public, no-transform";
    }

    # 绕过缓存
    location /api/private/ {
        proxy_pass http://api_backend;
        proxy_cache_bypass 1;  # 永远不缓存
        proxy_no_cache 1;
    }
}

7 高可用方案

构建高可用的代理层是保障服务稳定性的关键。以下介绍几种常见的方案。

7.1 Keepalived + Nginx

通过 Keepalived 实现虚拟 IP(VIP)的漂移,当主节点故障时,备用节点接管 VIP。

# 服务器 A 配置(主)
# /etc/keepalived/keepalived.conf

vrrp_script chk_nginx {
    script "/usr/local/bin/check_nginx.sh"
    interval 2
    weight -20
}

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1234
    }
    virtual_ipaddress {
        192.168.1.100
    }
    track_script {
        chk_nginx
    }
}
# 服务器 B 配置(备)
# /etc/keepalived/keepalived.conf

vrrp_script chk_nginx {
    script "/usr/local/bin/check_nginx.sh"
    interval 2
    weight -20
}

vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 51
    priority 90
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1234
    }
    virtual_ipaddress {
        192.168.1.100
    }
    track_script {
        chk_nginx
    }
}
#!/bin/bash
# /usr/local/bin/check_nginx.sh

nginx_status=$(curl -s -o /dev/null -w "%{http_code}" http://localhost/health)
if [ $nginx_status -ne 200 ]; then
    systemctl restart nginx
    sleep 2
    nginx_status=$(curl -s -o /dev/null -w "%{http_code}" http://localhost/health)
if [ $nginx_status -ne 200 ]; then
exit 1
fi
fi
exit 0

7.2 DNS 轮询高可用

# DNS A 记录配置多个 IP
# example.com A 192.168.1.101
# example.com A 192.168.1.102
# example.com A 192.168.1.103

# 优点:简单
# 缺点:DNS 缓存问题,故障切换慢

# 建议配合健康检查

7.3 Consul + Nginx

结合 Consul 的服务发现能力,可以动态地更新 Nginx 的 upstream 配置,实现更灵活的 高可用集群管理。

# Consul Template 动态更新 upstream
# /etc/nginx/conf.d/upstream.ctmpl

upstream backend {
    {{ range service "api" }}
    server {{ .Address }}:{{ .Port }};
    {{ end }}
}

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://backend;
    }
}
#!/bin/bash
# consul-template 配置
# consul-template -config /etc/consul-template/nginx.hcl

# /etc/consul-template/nginx.hcl
# template {
#   source = "/etc/nginx/conf.d/upstream.ctmpl"
#   destination = "/etc/nginx/conf.d/upstream.conf"
#   command = "nginx -s reload"
# }

# consul 服务注册
# {
#   "services": [
#     {
#       "name": "api",
#       "address": "127.0.0.1",
#       "port": 8080,
#       "check": {
#         "http": "http://127.0.0.1:8080/health",
#         "interval": "10s"
#       }
#     }
#   ]
# }

8 实际应用场景

8.1 API 网关场景

# API 网关完整配置

upstream user_service {
    server 127.0.0.1:8001;
    server 127.0.0.1:8002;
}

upstream order_service {
    server 127.0.0.1:8003;
    server 127.0.0.1:8004;
}

upstream payment_service {
    server 127.0.0.1:8005;
}

proxy_cache_path /var/cache/nginx levels=1:2
                 keys_zone=api_cache:100m
                 max_size=10g
                 inactive=5m;

server {
    listen 80;
    server_name api.example.com;

    # 用户服务
    location /api/users {
        proxy_pass http://user_service;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        # 限流
        limit_req zone=api burst=50 nodelay;
    }

    # 订单服务
    location /api/orders {
        proxy_pass http://order_service;
        proxy_set_header Host $host;
        # 限流
        limit_req zone=api burst=30 nodelay;
        # 缓存(只读)
        proxy_cache api_cache;
        proxy_cache_valid 200 1m;
        proxy_cache_bypass $cookie_nocache;
    }

    # 支付服务(高安全)
    location /api/payment {
        proxy_pass http://payment_service;
        # 严格限流
        limit_req zone=payment burst=5 nodelay;
        # 不缓存
        proxy_cache_bypass 1;
        proxy_no_cache 1;
    }

    # 默认
    location / {
        return 404;
    }
}

8.2 单页应用(SPA)场景

# Vue/React 单页应用配置

server {
    listen 80;
    server_name app.example.com;
    root /var/www/spa/dist;
    index index.html;

    # 缓存静态资源
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        access_log off;
    }

    # HTML 不缓存
    location = /index.html {
        expires -1;
        add_header Cache-Control "no-store, no-cache, must-revalidate";
    }

    # React Router 处理:所有路由都返回 index.html
    location / {
        try_files $uri $uri/ /index.html;
    }

    # API 代理
    location /api/ {
        proxy_pass http://api_backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

8.3 WebSocket 代理

# WebSocket 代理配置

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

upstream websocket_backend {
    server 127.0.0.1:8080;
    server 127.0.0.1:8081;
}

server {
    listen 80;
    server_name ws.example.com;

    location /ws {
        proxy_pass http://websocket_backend;

        # WebSocket 必需配置
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        # 超时配置(WebSocket 可能长时间连接)
        proxy_connect_timeout 7d;
        proxy_send_timeout 7d;
        proxy_read_timeout 7d;

        # 缓冲关闭
        proxy_buffering off;
    }
}

8.4 gRPC 代理

# gRPC 代理配置

upstream grpc_backend {
    server 127.0.0.1:50051;
    server 127.0.0.1:50052;
}

server {
    listen 443 ssl http2;
    server_name grpc.example.com;

    ssl_certificate /etc/nginx/ssl/grpc.crt;
    ssl_certificate_key /etc/nginx/ssl/grpc.key;
    ssl_protocols TLSv1.2 TLSv1.3;

    location / {
        # gRPC 传输
        grpc_pass grpc://grpc_backend;

        # 错误处理
        error_page 502 = /error502grpc;
    }

    location = /error502grpc {
        internal;
        default_type application/grpc;
        add_header grpc-status 14;
        add_header content-type application/grpc;
        add_header grpc-message "unavailable";
        return 204;
    }
}

9 性能优化

9.1 连接池配置

# upstream 连接池
upstream backend {
    server 127.0.0.1:8080;
    server 127.0.0.1:8081;

    # HTTP/1.1 连接池
    keepalive 32;
    keepalive_requests 1000;
    keepalive_timeout 60s;
}

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://backend;

        # 启用 HTTP/1.1
        proxy_http_version 1.1;

        # 清空 Connection 头
        proxy_set_header Connection "";
    }
}

9.2 缓冲区优化

# 代理缓冲区
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
proxy_busy_buffers_size 16k;

# 大型响应优化
proxy_max_temp_file_size 1024m;
proxy_temp_file_write_size 8k;

# FastCGI 缓冲区(PHP)
fastcgi_buffering on;
fastcgi_buffer_size 4k;
fastcgi_buffers 8 4k;
fastcgi_busy_buffers_size 8k;

9.3 零拷贝

# 启用零拷贝传输
sendfile on;
tcp_nopush on;
tcp_nodelay on;

# AIO 异步 I/O(适合大文件)
aio on;
directio 4m;
output_buffers 1 128k;

9.4 Gzip 压缩

gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_min_length 1024;
gzip_types text/plain text/css text/xml application/json application/javascript
            application/xml application/xml+rss application/javascript
            image/svg+xml;
gzip_disable "msie6";

10 监控与故障排查

良好的监控和快速的故障排查是 运维 & 测试 工作的核心。

10.1 监控指标

#!/bin/bash
# monitor_upstream.sh - 监控 upstream 健康状态

echo "=== Upstream 健康状态 ==="

# 查看 upstream 连接状态
curl -s http://localhost/status
# 需要启用 nginx-module-vts

# 检查 upstream 响应时间
echo ""
echo "=== 响应时间测试 ==="
time curl -s -o /dev/null http://localhost/health

# 检查各 upstream
echo ""
echo "=== Upstream 可用性 ==="
for port in 8080 8081 8082; do
if timeout 1 bash -c "echo > /dev/tcp/127.0.0.1/$port" 2>/dev/null; then
echo "✓ 127.0.0.1:$port 可用"
else
echo "✗ 127.0.0.1:$port 不可用"
fi
done

# 查看错误日志
echo ""
echo "=== 最近代理错误 ==="
tail -20 /var/log/nginx/error.log | grep -E "upstream|proxy" || echo "无错误"

10.2 常见故障排查

# 1. 502 Bad Gateway
# 检查后端是否运行
ss -tlnp | grep :8080

# 检查连接
curl -v http://127.0.0.1:8080

# 查看错误日志
tail -50 /var/log/nginx/error.log | grep upstream

# 2. 504 Gateway Timeout
# 检查后端处理时间
# 查看 nginx 日志中的 uht/urt 字段

# 3. 503 Service Unavailable
# 检查限流配置
# 检查后端是否过载

# 4. 负载不均
# 查看 access_log 中 $upstream_addr
awk '{print $NF}' /var/log/nginx/access.log | sort | uniq -c | sort -rn

10.3 调试配置

# 调试代理
server {
    listen 80;
    server_name debug.example.com;

    location / {
        # 开启详细日志
        rewrite ^(.*)$ /debug$1 break;
    }

    location /debug/ {
        proxy_pass http://backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;

        # 调试头
        add_header X-Upstream-Addr $upstream_addr;
        add_header X-Upstream-Status $upstream_status;
        add_header X-Upstream-Response-Time $upstream_response_time;
    }
}

11 总结与速查

11.1 核心配置速查

# 反向代理基础配置
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 "";
}

# 负载均衡
upstream backend {
    server 127.0.0.1:8080;
    server 127.0.0.1:8081 weight=2;
    ip_hash;
    least_conn;
}

# 健康检查
upstream backend {
    server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
    server 127.0.0.1:8081 max_fails=3 fail_timeout=30s;
}

# 缓存
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=api_cache:100m;
location / {
    proxy_cache api_cache;
    proxy_cache_valid 200 60m;
}

# WebSocket
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

11.2 场景配置速查

场景 关键配置
API 网关 多 upstream、限流、缓存
SPA try_files、静态资源缓存
WebSocket Upgrade 头、长超时
gRPC HTTP/2、grpc_pass
高可用 Keepalived、DNS 轮询

11.3 排查命令速查

# 查看 upstream 状态
curl http://localhost/status

# 查看错误日志
tail -100 /var/log/nginx/error.log | grep upstream

# 测试后端
curl -v http://127.0.0.1:8080/health

# 查看连接数
ss -ant | grep :8080

# 查看负载分布
awk '{print $NF}' /var/log/nginx/access.log | sort | uniq -c | sort -rn

11.4 性能优化要点


1. 连接池:keepalive 32-64
2. 缓冲区:proxy_buffering on
3. 零拷贝:sendfile on + tcp_nopush
4. 压缩:gzip on
5. HTTP/2:listen 443 ssl http2
6. 缓存:proxy_cache 减少后端压力



上一篇:Khal抽象层发布:一套Rust代码兼容WebGPU、CUDA与CPU后端
下一篇:技术总监必备的四大核心技能:从战略解码到变革领导力
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-4-10 03:10 , Processed in 0.672960 second(s), 42 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表