# NGINX 反向代理与负载均衡指南

## 1. 反向代理基础

### 什么是反向代理

反向代理服务器接收客户端请求，将请求转发给后端服务器，获取响应后返回给客户端。NGINX 作为反向代理可以：

- 隐藏后端服务器真实地址
- 实现负载均衡
- 缓存响应内容
- SSL 终端加密
- 压缩响应内容
- 请求路由与重写

### 基础配置示例

```nginx
server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://backend.example.com:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
```

---

## 2. proxy_pass 指令详解

### 语法

`proxy_pass URL;`

URL 可以是：
- HTTP 地址：`http://backend:8080`
- HTTPS 地址：`https://backend:8443`
- Unix Socket：`unix:/tmp/backend.socket`
- upstream 组：`http://backend_group`
- 变量：`http://$backend`

### URI 传递规则

**带 URI 的 proxy_pass**：请求 URI 中匹配 location 的部分会被替换。

```nginx
location /name/ {
    proxy_pass http://127.0.0.1/remote/;
    # /name/test -> /remote/test
}

location /api/ {
    proxy_pass http://backend/v1/;
    # /api/users -> /v1/users
}
```

**不带 URI 的 proxy_pass**：请求 URI 以原始形式传递。

```nginx
location /some/path/ {
    proxy_pass http://127.0.0.1;
    # /some/path/test -> /some/path/test
}
```

**使用变量**：

```nginx
location / {
    proxy_pass http://$backend;
    # 需要配合 resolver 指令解析域名
}

resolver 10.0.0.1 valid=300s;
```

---

## 3. 请求头设置

### proxy_set_header

设置传递给后端服务器的请求头。

```nginx
proxy_set_header Host $host;                   # 传递原始 Host
proxy_set_header Host $http_host;              # 传递 Host 头（含端口）
proxy_set_header Host backend.example.com;     # 固定 Host 值

proxy_set_header X-Real-IP $remote_addr;       # 客户端真实 IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  # 代理链
proxy_set_header X-Forwarded-Proto $scheme;    # 原始协议

# 删除请求头
proxy_set_header Accept-Encoding "";           # 删除该字段
```

### 默认行为

| 头字段 | 默认值 |
|--------|--------|
| `Host` | `$proxy_host`（proxy_pass 中的地址） |
| `Connection` | `close` |

---

## 4. 负载均衡配置

### upstream 块定义

```nginx
upstream backend {
    server backend1.example.com weight=5;
    server backend2.example.com:8080;
    server 192.168.0.1:8080 max_fails=3 fail_timeout=30s;
    server backend3.example.com backup;        # 备份服务器
    server unix:/tmp/backend4;
}

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

### 负载均衡算法

| 算法 | 指令 | 说明 |
|------|------|------|
| **轮询** | 默认 | 请求依次分发（加权） |
| **最少连接** | `least_conn;` | 分配给活动连接最少的服务器 |
| **IP Hash** | `ip_hash;` | 同一客户端 IP 始终路由到同一服务器 |
| **Hash** | `hash key [consistent];` | 基于指定键哈希，支持一致性哈希 |
| **随机** | `random [two [method]];` | 随机选择，two 表示选两台再择优 |

### 配置示例

**轮询（默认）**：
```nginx
upstream backend {
    server srv1.example.com;
    server srv2.example.com;
    server srv3.example.com;
}
```

**加权轮询**：
```nginx
upstream backend {
    server srv1.example.com weight=5;  # 5/7 的请求
    server srv2.example.com weight=2;  # 2/7 的请求
    server srv3.example.com;           # 1/7 的请求（默认 weight=1）
}
```

**最少连接**：
```nginx
upstream backend {
    least_conn;
    server srv1.example.com;
    server srv2.example.com;
    server srv3.example.com;
}
```

**IP Hash（会话持久性）**：
```nginx
upstream backend {
    ip_hash;
    server srv1.example.com;
    server srv2.example.com;
    server srv3.example.com;
}
```

**一致性哈希**：
```nginx
upstream backend {
    hash $request_uri consistent;
    server srv1.example.com;
    server srv2.example.com;
    server srv3.example.com;
}
```

**随机负载均衡（1.15.1+）**：
```nginx
upstream backend {
    random;                              # 纯随机选择
    server srv1.example.com;
    server srv2.example.com;
    server srv3.example.com;
}

# Power of Two Choices 算法（更智能）
upstream backend {
    random two;                          # 随机选两台，按权重择优
    server srv1.example.com;
    server srv2.example.com;
    server srv3.example.com;
}

# 结合最少连接策略
upstream backend {
    random two least_conn;               # 随机选两台，选连接数少的
    server srv1.example.com;
    server srv2.example.com;
}
```

**random 算法参数说明**：

| 参数 | 说明 |
|------|------|
| `two` | 随机选择两台服务器，再根据策略择优 |
| `least_conn` | 与 `two` 配合，选择连接数较少的服务器 |
| `least_time=header` | 与 `two` 配合，选择响应头时间最短的服务器（NGINX Plus）|
| `least_time=last_byte` | 与 `two` 配合，选择完整响应时间最短的服务器（NGINX Plus）|

**适用场景**：
- 多个负载均衡器共享后端时避免锁竞争
- 对一致性要求不高但需要低延迟的场景
- 配合 `zone` 实现无锁负载均衡

### server 指令参数

| 参数 | 说明 | 默认值 |
|------|------|--------|
| `weight=N` | 权重值 | 1 |
| `max_conns=N` | 最大并发连接数 | 0（无限制） |
| `max_fails=N` | 失败次数阈值 | 1 |
| `fail_timeout=T` | 失败统计时间及不可用持续时间 | 10s |
| `backup` | 备份服务器（主服务器不可用时使用） | - |
| `down` | 标记为永久不可用 | - |
| `resolve` | 监控域名 IP 变化（需 zone + resolver） | - |

```nginx
upstream backend {
    zone backend 64k;
    resolver 10.0.0.1;

    server backend1.example.com weight=5 max_fails=3 fail_timeout=30s;
    server backend2.example.com resolve;
    server backup1.example.com backup;
}
```

---

## 5. 健康检查

### 被动健康检查（内置）

```nginx
upstream backend {
    server srv1.example.com max_fails=3 fail_timeout=30s;
    server srv2.example.com max_fails=3 fail_timeout=30s;
}
```

**机制**：
- 在 `fail_timeout` 时间内连续失败 `max_fails` 次，服务器标记为不可用
- `fail_timeout` 时间后再次尝试

### 主动健康检查（NGINX Plus）

```nginx
upstream backend {
    zone backend 64k;

    server srv1.example.com;
    server srv2.example.com;

    health_check interval=5s fails=3 passes=2;
    health_check uri=/health;
}
```

---

## 6. 超时配置

### 主要超时指令

| 指令 | 说明 | 默认值 |
|------|------|--------|
| `proxy_connect_timeout` | 建立连接超时 | 60s |
| `proxy_send_timeout` | 传输请求超时 | 60s |
| `proxy_read_timeout` | 读取响应超时 | 60s |

```nginx
location / {
    proxy_connect_timeout 5s;
    proxy_send_timeout 10s;
    proxy_read_timeout 30s;
    proxy_pass http://backend;
}
```

---

## 7. 缓冲配置

### 响应缓冲

```nginx
proxy_buffering on;                  # 默认 on
proxy_buffer_size 4k;                # 响应头缓冲区大小
proxy_buffers 8 16k;                 # 响应体缓冲区数量和大小
proxy_busy_buffers_size 32k;         # 同时发送给客户端的缓冲区总大小
proxy_max_temp_file_size 1024m;      # 临时文件最大大小
proxy_temp_file_write_size 64k;      # 每次写入临时文件大小
```

### 禁用缓冲（实时传输）

```nginx
location /stream/ {
    proxy_buffering off;
    proxy_pass http://backend;
}
```

---

## 8. 缓存配置

### 缓存路径定义

```nginx
http {
    proxy_cache_path /data/nginx/cache
        levels=1:2                    # 目录层级（1:2 表示 16*256 个子目录）
        keys_zone=one:10m             # 共享内存区名称和大小（1MB 约 8000 个键）
        inactive=60m                  # 非活动数据保留时间
        max_size=1g                   # 缓存最大大小
        use_temp_path=off;            # 临时文件存放位置
}
```

### 启用缓存

```nginx
server {
    location / {
        proxy_cache one;              # 使用定义的缓存区
        proxy_cache_key "$host$request_uri";  # 缓存键
        proxy_cache_valid 200 302 10m;        # 200/302 响应缓存 10 分钟
        proxy_cache_valid 404 1m;             # 404 响应缓存 1 分钟
        proxy_cache_valid any 1m;             # 其他响应缓存 1 分钟
        proxy_pass http://backend;
    }
}
```

### 缓存条件控制

```nginx
# 不从缓存获取响应的条件
proxy_cache_bypass $cookie_nocache $arg_nocache;

# 不将响应保存到缓存的条件
proxy_no_cache $http_pragma $http_authorization;
```

### 使用过期缓存

```nginx
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
# 在后端错误、超时、正在更新时使用过期缓存
```

### 缓存锁

```nginx
proxy_cache_lock on;                 # 同时刻只允许一个请求填充缓存
proxy_cache_lock_timeout 5s;         # 锁超时时间
```

---

## 9. 故障转移

### proxy_next_upstream

定义在何种情况下将请求传递给下一台服务器。

```nginx
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_next_upstream_timeout 30s;     # 限制总时间
proxy_next_upstream_tries 3;         # 限制尝试次数
```

**条件类型**：

| 条件 | 说明 |
|------|------|
| `error` | 与后端建立连接出错 |
| `timeout` | 连接、传输或读取超时 |
| `invalid_header` | 后端返回空或无效响应头 |
| `http_XXX` | 后端返回指定状态码 |
| `non_idempotent` | 非幂等请求（POST、LOCK）也进行重试 |

---

## 10. SSL/HTTPS 代理

### 代理到 HTTPS 后端

```nginx
location / {
    proxy_pass https://backend.example.com;
    proxy_ssl_verify on;                         # 验证后端证书
    proxy_ssl_trusted_certificate /path/to/ca.crt;
    proxy_ssl_verify_depth 2;
    proxy_ssl_server_name on;                    # 启用 SNI
}
```

### 代理 SSL 配置

| 指令 | 说明 | 默认值 |
|------|------|--------|
| `proxy_ssl` | 启用 HTTPS 代理 | off |
| `proxy_ssl_protocols` | 启用的协议 | TLSv1.2 TLSv1.3 |
| `proxy_ssl_ciphers` | 加密套件 | DEFAULT |
| `proxy_ssl_verify` | 验证后端证书 | off |
| `proxy_ssl_verify_depth` | 验证深度 | 1 |
| `proxy_ssl_server_name` | 启用 SNI | off |
| `proxy_ssl_certificate` | 客户端证书 | - |
| `proxy_ssl_certificate_key` | 客户端密钥 | - |

---

## 11. WebSocket 代理

### 基础配置

```nginx
location /chat/ {
    proxy_pass http://backend;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}
```

### 动态处理

```nginx
http {
    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    }

    server {
        location /chat/ {
            proxy_pass http://backend;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
            proxy_read_timeout 3600s;  # 增加超时时间
        }
    }
}
```

---

## 12. 高级代理指令

### proxy_bind

指定连接后端时使用的源地址，用于多网卡服务器选择出口IP。

```nginx
语法: proxy_bind address [transparent];
默认: —
上下文: http, server, location
```

```nginx
proxy_bind $server_addr;              # 使用服务器IP
proxy_bind 192.168.1.1 transparent;   # 透明代理（需要root权限）
```

### proxy_intercept_errors

拦截后端错误响应，配合 error_page 自定义错误页面。

```nginx
语法: proxy_intercept_errors on | off;
默认: off
上下文: http, server, location
```

```nginx
proxy_intercept_errors on;
error_page 500 502 503 504 /50x.html;
```

### proxy_hide_header / proxy_pass_header

控制后端响应头的传递行为：

```nginx
# 隐藏后端返回的特定头
proxy_hide_header X-Powered-By;
proxy_hide_header X-Runtime;

# 传递被默认隐藏的头
proxy_pass_header X-Accel-Redirect;
proxy_pass_header X-Accel-Limit-Rate;
```

### proxy_ignore_headers

忽略后端的特定响应头（如缓存控制），允许NGINX处理这些头：

```nginx
proxy_ignore_headers Cache-Control Expires X-Accel-Redirect X-Accel-Expires;
```

### proxy_cookie_* 系列

修改后端返回的 Set-Cookie 头：

```nginx
# 修改域名
proxy_cookie_domain localhost example.com;
proxy_cookie_domain off;              # 禁用域名修改

# 修改路径
proxy_cookie_path /foo/ /bar/;
proxy_cookie_path off;                # 禁用路径修改

# 添加安全标志
proxy_cookie_flags session httponly secure samesite=strict;
proxy_cookie_flags * samesite=lax;    # 应用到所有cookie
```

### proxy_limit_rate

限制从后端读取响应的传输速率：

```nginx
proxy_limit_rate 100k;                # 100KB/s
```

### proxy_request_buffering

控制请求是否先完整缓冲再发送到后端：

```nginx
proxy_request_buffering on;           # 默认，完整缓冲
proxy_request_buffering off;          # 流式传输，支持上传进度
```

### proxy_redirect

修改后端返回的重定向头 Location 和 Refresh：

```nginx
proxy_redirect default;                                    # 使用默认替换
proxy_redirect off;                                        # 禁用替换
proxy_redirect http://localhost:8080/ http://$host/;       # 自定义替换
proxy_redirect ~^http://([^/]+)/(.+)$ http://$host/$2;      # 使用正则
```

---

## 13. SSL 客户端证书认证 (proxy_ssl_*)

用于 mTLS 双向认证场景，NGINX 作为客户端向后端提供证书：

```nginx
location / {
    proxy_pass https://backend.example.com;

    # mTLS 双向认证
    proxy_ssl_certificate /path/to/client.crt;
    proxy_ssl_certificate_key /path/to/client.key;

    # 验证后端证书
    proxy_ssl_verify on;
    proxy_ssl_trusted_certificate /path/to/ca.crt;
    proxy_ssl_verify_depth 2;

    # SSL协议和加密套件
    proxy_ssl_protocols TLSv1.2 TLSv1.3;
    proxy_ssl_ciphers HIGH:!aNULL;

    # 会话复用
    proxy_ssl_session_reuse on;

    # SNI支持
    proxy_ssl_server_name on;
    proxy_ssl_name backend.example.com;
}
```

| 指令 | 说明 | 默认值 |
|------|------|--------|
| `proxy_ssl_certificate` | 客户端证书路径 | — |
| `proxy_ssl_certificate_key` | 客户端私钥路径 | — |
| `proxy_ssl_verify` | 验证后端证书 | off |
| `proxy_ssl_trusted_certificate` | 受信任CA证书 | — |
| `proxy_ssl_verify_depth` | 验证深度 | 1 |
| `proxy_ssl_protocols` | 启用的协议 | TLSv1.2 TLSv1.3 |
| `proxy_ssl_ciphers` | 加密套件 | DEFAULT |
| `proxy_ssl_session_reuse` | 会话复用 | on |
| `proxy_ssl_name` | SNI名称 | — |

---

## 14. 高级缓存指令

### proxy_cache_methods

指定可缓存的请求方法：

```nginx
proxy_cache_methods GET HEAD POST;    # 可缓存 POST 请求
```

### proxy_cache_min_uses

设置最小访问次数才开始缓存，避免缓存低频请求：

```nginx
proxy_cache_min_uses 3;               # 第3次访问才开始缓存
```

### proxy_cache_background_update

后台异步更新过期缓存（类似 stale-while-revalidate）：

```nginx
proxy_cache_background_update on;
```

### proxy_cache_revalidate

使用 If-Modified-Since 和 If-None-Match 重新验证缓存：

```nginx
proxy_cache_revalidate on;            # 减少数据传输
```

### proxy_cache_convert_head

自动将 HEAD 请求转为 GET 以获取响应体：

```nginx
proxy_cache_convert_head on;          # 默认启用
```

### proxy_cache_purge

支持 PURGE 方法清除缓存（需编译时启用）：

```nginx
location ~ /purge(/.*) {
    proxy_cache_purge cache_zone $1;
}
```

---

## 15. FastCGI 代理

### 基础配置

```nginx
location ~ \.php$ {
    fastcgi_pass  localhost:9000;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
}
```

### FastCGI 指令完整列表

| 指令 | 语法 | 默认值 | 上下文 |
|------|------|--------|--------|
| `fastcgi_pass` | fastcgi_pass address; | — | location |
| `fastcgi_index` | fastcgi_index name; | — | http, server, location |
| `fastcgi_param` | fastcgi_param parameter value [if_not_empty]; | — | http, server, location |
| `fastcgi_split_path_info` | fastcgi_split_path_info regex; | — | location |
| `fastcgi_buffer_size` | fastcgi_buffer_size size; | 4k/8k | http, server, location |
| `fastcgi_buffers` | fastcgi_buffers number size; | 8 4k/8k | http, server, location |
| `fastcgi_busy_buffers_size` | fastcgi_busy_buffers_size size; | 8k/16k | http, server, location |
| `fastcgi_temp_file_write_size` | fastcgi_temp_file_write_size size; | 8k/16k | http, server, location |
| `fastcgi_temp_path` | fastcgi_temp_path path [level1 [level2 [level3]]]; | — | http, server, location |
| `fastcgi_cache` | fastcgi_cache zone; | — | http, server, location |
| `fastcgi_cache_key` | fastcgi_cache_key string; | — | http, server, location |
| `fastcgi_cache_valid` | fastcgi_cache_valid [code...] time; | — | http, server, location |
| `fastcgi_cache_methods` | fastcgi_cache_methods method...; | GET HEAD | http, server, location |
| `fastcgi_cache_min_uses` | fastcgi_cache_min_uses number; | 1 | http, server, location |
| `fastcgi_cache_bypass` | fastcgi_cache_bypass string...; | — | http, server, location |
| `fastcgi_no_cache` | fastcgi_no_cache string...; | — | http, server, location |
| `fastcgi_cache_use_stale` | fastcgi_cache_use_stale condition...; | — | http, server, location |
| `fastcgi_cache_background_update` | fastcgi_cache_background_update on/off; | off | http, server, location |
| `fastcgi_cache_revalidate` | fastcgi_cache_revalidate on/off; | off | http, server, location |
| `fastcgi_cache_lock` | fastcgi_cache_lock on/off; | off | http, server, location |
| `fastcgi_cache_lock_timeout` | fastcgi_cache_lock_timeout time; | 5s | http, server, location |
| `fastcgi_cache_convert_head` | fastcgi_cache_convert_head on/off; | on | http, server, location |
| `fastcgi_connect_timeout` | fastcgi_connect_timeout time; | 60s | http, server, location |
| `fastcgi_send_timeout` | fastcgi_send_timeout time; | 60s | http, server, location |
| `fastcgi_read_timeout` | fastcgi_read_timeout time; | 60s | http, server, location |
| `fastcgi_send_lowat` | fastcgi_send_lowat size; | 0 | http, server, location |
| `fastcgi_request_buffering` | fastcgi_request_buffering on/off; | on | http, server, location |
| `fastcgi_intercept_errors` | fastcgi_intercept_errors on/off; | off | http, server, location |
| `fastcgi_hide_header` | fastcgi_hide_header field; | — | http, server, location |
| `fastcgi_pass_header` | fastcgi_pass_header field; | — | http, server, location |
| `fastcgi_ignore_headers` | fastcgi_ignore_headers field...; | — | http, server, location |
| `fastcgi_limit_rate` | fastcgi_limit_rate rate; | 0 | http, server, location |

### FastCGI 缓存完整配置示例

```nginx
http {
    # 缓存路径定义
    fastcgi_cache_path /var/cache/nginx/php
        levels=1:2
        keys_zone=php:10m
        max_size=100m
        inactive=60m
        use_temp_path=off;

    server {
        listen 80;
        server_name example.com;

        location ~ \.php$ {
            # 启用缓存
            fastcgi_cache php;
            fastcgi_cache_key "$scheme$request_method$host$request_uri";

            # 缓存有效期
            fastcgi_cache_valid 200 302 1h;
            fastcgi_cache_valid 404 1m;
            fastcgi_cache_valid any 5m;

            # 使用过期缓存
            fastcgi_cache_use_stale error timeout updating http_500 http_503;

            # 后台更新
            fastcgi_cache_background_update on;

            # 重新验证
            fastcgi_cache_revalidate on;

            # 缓存锁
            fastcgi_cache_lock on;
            fastcgi_cache_lock_timeout 5s;

            # 绕过缓存条件
            fastcgi_cache_bypass $cookie_nocache $arg_nocache;
            fastcgi_no_cache $http_pragma $http_authorization;

            # FastCGI 后端
            fastcgi_pass unix:/run/php/php-fpm.sock;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

            # 超时设置
            fastcgi_connect_timeout 5s;
            fastcgi_send_timeout 60s;
            fastcgi_read_timeout 60s;

            # 缓冲配置
            fastcgi_buffer_size 16k;
            fastcgi_buffers 8 16k;
            fastcgi_busy_buffers_size 32k;

            # 错误处理
            fastcgi_intercept_errors on;

            include fastcgi_params;
        }
    }
}
```

---

## 16. 内置变量

### 代理相关变量

| 变量 | 说明 |
|------|------|
| `$proxy_host` | proxy_pass 中的服务器名称和端口 |
| `$proxy_port` | proxy_pass 中的端口 |
| `$proxy_add_x_forwarded_for` | X-Forwarded-For 头 + 客户端 IP |

### Upstream 响应时间变量（用于性能监控）

| 变量 | 说明 | 单位 |
|------|------|------|
| `$upstream_addr` | 上游服务器地址（IP:端口）| - |
| `$upstream_connect_time` | 与上游建立连接的时间（含 SSL 握手）| 秒 |
| `$upstream_header_time` | 接收到上游响应头的时间 | 秒 |
| `$upstream_response_time` | 完整响应时间（从建立连接到接收完成）| 秒 |
| `$upstream_response_length` | 上游响应体长度 | 字节 |
| `$upstream_bytes_received` | 从上游接收的总字节数 | 字节 |
| `$upstream_bytes_sent` | 发送到上游的总字节数 | 字节 |
| `$upstream_status` | 上游返回的 HTTP 状态码 | - |
| `$upstream_cache_status` | 缓存命中状态（HIT/MISS/EXPIRED 等）| - |
| `$upstream_queue_time` | 请求在队列中等待的时间（NGINX Plus）| 秒 |

**日志格式中使用响应时间变量**：

```nginx
log_format detailed '$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" '
                    'upstream=$upstream_addr '
                    'upstream_status=$upstream_status '
                    'upstream_bytes=$upstream_response_length';

access_log /var/log/nginx/access.log detailed;
```

**响应时间变量解读**：

```
请求时间线:
客户端 ──▶ NGINX ──▶ 连接上游 ──▶ 发送请求 ──▶ 接收响应头 ──▶ 接收响应体 ──▶ 客户端
              │           │              │                │                │
              │           │              │                │                │
              └───────────┴──────────────┴────────────────┴────────────────┘
                          │              │                │
                    $upstream_     $upstream_       $upstream_
                    connect_time   header_time      response_time
```

- `$upstream_connect_time`：TCP 连接 + SSL 握手时间
- `$upstream_header_time`：从开始到收到响应头
- `$upstream_response_time`：完整请求处理时间
- `$request_time`：从客户端发起请求到响应完成（包含所有上游）

**基于响应时间的告警配置示例**：

```nginx
# 慢请求日志
map $upstream_response_time $slow_log {
    default 0;
    "~^[2-9]\." 1;    # 2秒以上
    "~^[0-9]{2,}" 1;  # 10秒以上
}

server {
    location /api/ {
        # 记录慢请求
        access_log /var/log/nginx/slow.log detailed if=$slow_log;
        proxy_pass http://backend;
    }
}
```

---

## 17. 综合配置示例

```nginx
http {
    upstream backend {
        zone backend 64k;
        least_conn;

        server backend1.example.com weight=5 max_fails=3 fail_timeout=30s;
        server backend2.example.com resolve;
        server backup.example.com backup;

        keepalive 32;
    }

    proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=main:10m inactive=60m max_size=1g;

    server {
        listen 80;
        server_name example.com;

        location / {
            proxy_pass http://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_connect_timeout 5s;
            proxy_read_timeout 30s;

            proxy_cache main;
            proxy_cache_key "$host$request_uri";
            proxy_cache_valid 200 10m;

            proxy_next_upstream error timeout http_502 http_503;
        }

        location /api/ {
            proxy_pass http://backend;
            proxy_set_header Host $host;
            proxy_buffering off;
        }

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

---

## 18. 主动健康检查详解

### 18.1 被动检查 vs 主动检查

| 特性 | 被动健康检查 (Passive) | 主动健康检查 (Active) |
|------|----------------------|---------------------|
| **实现方式** | 基于真实客户端请求响应判断 | 独立的探测请求周期性检测 |
| **触发时机** | 实际请求失败时 | 按配置间隔主动发起 |
| **资源占用** | 无额外开销 | 需要额外的连接和请求 |
| **发现速度** | 慢（依赖真实流量） | 快（独立探测） |
| **可用性** | 开源 NGINX 内置 | NGINX Plus 商业版 / 第三方模块 |
| **配置位置** | `server` 指令参数 | `upstream` 块或 `location` 指令 |
| **典型参数** | `max_fails`, `fail_timeout` | `interval`, `fails`, `passes`, `match` |

**被动检查机制**：
```nginx
upstream backend {
    # 在 fail_timeout(30s) 内连续失败 max_fails(3) 次，标记为不可用
    server srv1.example.com max_fails=3 fail_timeout=30s;
}
```

**主动检查优势**：
- 不依赖真实客户端流量即可检测后端状态
- 可以检测特定的健康检查端点（如 `/health`）
- 支持自定义匹配规则验证响应内容
- 支持 gRPC、TCP、UDP 等多种协议

### 18.2 HTTP 健康检查指令详解 (NGINX Plus)

**注意**：HTTP 主动健康检查模块 (`ngx_http_upstream_hc_module`) 是 NGINX Plus 商业订阅的一部分。

#### health_check 指令

**语法**：`health_check [parameters];`
**上下文**：`location`
**功能**：启用 upstream 服务器组的定期健康检查

**参数说明**：

| 参数 | 语法 | 默认值 | 说明 |
|------|------|--------|------|
| `interval` | `interval=time` | `5s` | 检查间隔时间 |
| `jitter` | `jitter=time` | — | 随机延迟时间，避免多个服务器同时检查 |
| `fails` | `fails=number` | `1` | 连续失败次数判定为不健康 |
| `passes` | `passes=number` | `1` | 连续成功次数判定为健康 |
| `uri` | `uri=uri` | `/` | 健康检查请求的 URI |
| `port` | `port=number` | 服务器端口 | 健康检查使用的端口 |
| `match` | `match=name` | — | 引用 `match` 块进行响应验证 |
| `mandatory` | `mandatory [persistent]` | — | 初始状态为 "checking"；`persistent` 在 reload 后保持状态 |
| `keepalive_time` | `keepalive_time=time` | — | 启用健康检查连接的 keepalive |
| `type=grpc` | `type=grpc [grpc_service=name] [grpc_status=code]` | — | 启用 gRPC 健康检查 |

#### match 指令

**语法**：`match name { ... }`
**上下文**：`http`
**功能**：定义响应验证测试集

**测试项**：

| 测试项 | 语法 | 说明 |
|--------|------|------|
| `status` | `status [!] code [code...]` | 状态码匹配，支持范围如 `200-399` |
| `header` | `header header [operator] value` | 响应头匹配，`=` 精确匹配，`~` 正则匹配 |
| `body` | `body ~ "regex"` | 响应体正则匹配（只检查前 256KB） |
| `require` | `require $variable` | 变量非空且不为 "0" |

**header 操作符**：
- `=` 或 `==`：精确相等
- `!=`：不相等
- `~`：正则匹配（区分大小写）
- `~*`：正则匹配（不区分大小写）

#### 配置示例

**基础健康检查**：
```nginx
upstream dynamic {
    zone upstream_dynamic 64k;  # 共享内存区必须

    server backend1.example.com weight=5;
    server backend2.example.com:8080 fail_timeout=5s slow_start=30s;
}

server {
    location / {
        proxy_pass http://dynamic;
        health_check;  # 使用默认配置
    }
}
```

**高级配置**：
```nginx
server {
    location / {
        proxy_pass http://backend;
        health_check interval=10s jitter=2s fails=3 passes=2
                     uri=/health port=8080 match=server_ok
                     keepalive_time=60s;
    }
}

match server_ok {
    status 200;                              # 状态码必须是 200
    header Content-Type = application/json;  # Content-Type 精确匹配
    header X-Health-Status ~ ^ok$;          # 正则匹配头值
    body ~ "\"status\":\\s*\"healthy\"";      # 响应体包含状态标记
}
```

**gRPC 健康检查**（不兼容 `uri` 和 `match`）：
```nginx
upstream grpc_backend {
    zone grpc_zone 64k;
    server grpc1.example.com:50051;
    server grpc2.example.com:50051;
}

server {
    location / {
        grpc_pass grpc://grpc_backend;
        health_check mandatory type=grpc grpc_service=myapp.HealthCheck grpc_status=12;
    }
}
```

### 18.3 Stream 健康检查指令详解 (NGINX Plus)

**注意**：Stream 主动健康检查模块 (`ngx_stream_upstream_hc_module`) 是 NGINX Plus 商业订阅的一部分。

#### 指令概览

| 指令 | 上下文 | 默认值 | 说明 |
|------|--------|--------|------|
| `health_check` | `server` | — | 启用健康检查 |
| `health_check_timeout` | `stream`, `server` | `5s` | 健康检查超时 |
| `match` | `stream` | — | 定义响应验证规则 |

#### health_check 参数（Stream）

| 参数 | 默认值 | 说明 |
|------|--------|------|
| `interval` | `5s` | 检查间隔 |
| `jitter` | — | 随机延迟 |
| `fails` | `1` | 失败次数阈值 |
| `passes` | `1` | 成功次数阈值 |
| `match` | — | 引用 match 块 |
| `port` | 服务器端口 | 检查端口 |
| `udp` | — | 使用 UDP 协议 |
| `mandatory` | — | 初始状态为 "checking" |
| `persistent` | — | reload 后保持状态 |

#### match 块（Stream）

| 测试项 | 语法 | 说明 |
|--------|------|------|
| `send` | `send "string"` | 发送给服务器的字符串（支持 `\x` 十六进制） |
| `expect` | `expect "string"` / `expect ~ "regex"` | 期望的响应 |

**注意**：只检查服务器返回数据的前 `proxy_buffer_size` 字节。

#### 配置示例

**TCP 基础检查**：
```nginx
upstream tcp_backend {
    zone tcp_zone 64k;
    server backend1.example.com:12345 weight=5;
    server backend2.example.com:12345;
}

server {
    listen 12346;
    proxy_pass tcp_backend;
    health_check interval=5s;
}
```

**UDP 健康检查**：
```nginx
upstream dns_upstream {
    zone dns_zone 64k;
    server dns1.example.com:53;
}

server {
    listen 53 udp;
    proxy_pass dns_upstream;
    health_check udp interval=3s;  # 发送探测并期望无 ICMP 不可达回复
}
```

**自定义匹配规则（MySQL 检查）**：
```nginx
upstream mysql_backend {
    zone mysql_zone 10m;
    server db1.example.com:3306;
    server db2.example.com:3306;
}

match mysql_handshake {
    # 发送 MySQL 握手包（十六进制）
    send "\x3a\x00\x00\x01\x0a\x35\x2e\x35\x2e\x32\x2d\x6d\x32\x00\x01...";
    # 期望收到包含版本信息的响应
    expect ~ "\x4a\x00\x00\x00\x0a";
}

server {
    listen 3307;
    proxy_pass mysql_backend;
    health_check match=mysql_handshake interval=5s;
    health_check_timeout 10s;
}
```

**HTTP 风格的 TCP 检查**：
```nginx
match http_check {
    send     "GET /health HTTP/1.0\r\nHost: localhost\r\n\r\n";
    expect ~ "200 OK";
}

server {
    listen 80;
    proxy_pass backend;
    health_check match=http_check interval=5s fails=3 passes=2;
}
```

### 18.4 自定义健康检查配置示例

#### 场景一：API 网关健康检查

```nginx
http {
    upstream api_backend {
        zone api_zone 64k;

        server api1.example.com:8080;
        server api2.example.com:8080;
        server api3.example.com:8080;
    }

    # 健康检查匹配规则
    match api_healthy {
        status 200;
        header Content-Type = application/json;
        body ~ "\"status\":\\s*\"up\"";
    }

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

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

            # 健康检查配置
            health_check interval=5s jitter=1s fails=3 passes=2
                         uri=/api/health
                         match=api_healthy;
        }

        # 健康检查状态页（NGINX Plus）
        location /upstream_status {
            upstream_status;
            access_log off;
            allow 10.0.0.0/8;
            deny all;
        }
    }
}
```

#### 场景二：多协议混合检查

```nginx
# TCP 服务健康检查
stream {
    upstream redis_backend {
        zone redis_zone 64k;
        server redis1.example.com:6379;
        server redis2.example.com:6379;
    }

    match redis_ping {
        send "PING\r\n";
        expect ~ "\+PONG";
    }

    server {
        listen 6379;
        proxy_pass redis_backend;
        health_check match=redis_ping interval=10s fails=2 passes=2;
        health_check_timeout 3s;
    }
}

# HTTP 服务健康检查
http {
    upstream web_backend {
        zone web_zone 64k;
        server web1.example.com:80;
        server web2.example.com:80;
    }

    server {
        location / {
            proxy_pass http://web_backend;
            health_check interval=5s uri=/nginx_health;
        }
    }
}
```

#### 场景三：微服务 gRPC 健康检查

```nginx
upstream grpc_services {
    zone grpc_zone 64k;
    server service1.example.com:50051;
    server service2.example.com:50051;
}

server {
    listen 50051 http2;

    location / {
        grpc_pass grpc://grpc_services;
        # gRPC 健康检查：使用标准 gRPC Health Checking Protocol
        # grpc_status=12 (UNIMPLEMENTED) 表示服务未实现健康检查接口
        # grpc_status=0 (OK) 表示服务健康
        health_check mandatory type=grpc grpc_service=grpc.health.v1.Health
                         interval=5s fails=3 passes=2;
    }
}
```

### 18.5 健康检查与负载均衡配合

#### 状态流转机制

```
         初始状态
            |
            v
      ┌───────────┐     ┌──────────────┐
      │ checking  │────▶│   unhealthy  │
      └─────┬─────┘     └──────────────┘
            │                   │
            │  passes 次成功     │ fails 次失败
            v                   v
      ┌───────────┐     ┌──────────────┐
      │  healthy  │◀────│              │
      └───────────┘     └──────────────┘
```

**关键行为**：
- `checking` 状态：初始或 reload 后，不接收客户端请求
- `mandatory` 参数：强制等待首次健康检查完成才标记为健康
- `persistent` 参数：reload 后如之前是健康状态则保持 healthy

#### 与负载均衡算法结合

```nginx
upstream backend {
    zone backend 64k;
    least_conn;  # 最少连接算法

    server srv1.example.com weight=5;
    server srv2.example.com;
    server srv3.example.com;

    # 被动检查参数与主动检查并存
    # 被动检查作为兜底，主动检查提供快速发现
}

server {
    location / {
        proxy_pass http://backend;
        health_check interval=5s fails=3 passes=2;

        # 故障转移配置
        proxy_next_upstream error timeout http_502 http_503 http_504;
        proxy_next_upstream_timeout 5s;
        proxy_next_upstream_tries 2;
    }
}
```

**监控指标集成**：

```nginx
log_format health_log '$remote_addr - $remote_user [$time_local] '
                      '"$request" $status '
                      'upstream=$upstream_addr '
                      'upstream_status=$upstream_status '
                      'health_check=$upstream_health_check_status';

server {
    location / {
        proxy_pass http://backend;
        health_check interval=5s;
        access_log /var/log/nginx/health.log health_log;
    }
}
```

### 18.6 开源 NGINX 的替代方案

由于主动健康检查是 NGINX Plus 商业特性，开源版本需要使用第三方模块。

#### nginx_upstream_check_module (Tengine)

由阿里巴巴 Tengine 团队开发的第三方模块，支持主动健康检查。

**源码地址**：https://github.com/yaoweibin/nginx_upstream_check_module

**安装方法**：
```bash
# 下载模块源码
git clone https://github.com/yaoweibin/nginx_upstream_check_module.git

# 下载 NGINX 源码并解压
cd /usr/local/src
tar -xzvf nginx-1.24.0.tar.gz
cd nginx-1.24.0

# 应用补丁（根据版本选择）
patch -p1 < /path/to/nginx_upstream_check_module/check.patch
# 或 patch -p1 < /path/to/nginx_upstream_check_module/check_1.20.1+.patch

# 编译安装
./configure \
    --prefix=/etc/nginx \
    --add-module=/path/to/nginx_upstream_check_module \
    --with-http_ssl_module \
    --with-http_v2_module

make && make install
```

**指令说明**：

| 指令 | 语法 | 默认值 | 说明 |
|------|------|--------|------|
| `check` | `check interval=ms [fall=N] [rise=N] [timeout=ms] [default_down=true\|false] [type=tcp\|http\|ssl_hello\|mysql\|ajp\|fastcgi]` | 见右侧 | 启用健康检查<br>`interval`: 检查间隔(ms)<br>`fall`: 失败次数<br>`rise`: 成功次数<br>`timeout`: 超时(ms)<br>`default_down`: 默认下线状态<br>`type`: 检查协议 |
| `check_keepalive_requests` | `check_keepalive_requests num` | `1` | 长连接检查次数 |
| `check_http_send` | `check_http_send "packet"` | `GET / HTTP/1.0\r\n\r\n` | HTTP 检查请求包 |
| `check_http_expect_alive` | `check_http_expect_alive [http_2xx] [http_3xx] [http_4xx] [http_5xx]` | `http_2xx` `http_3xx` | 视为健康的 HTTP 状态码 |
| `check_fastcgi_param` | `check_fastcgi_param parameter value` | — | FastCGI 检查参数 |
| `check_status` | `check_status [html\|csv\|json]` | `html` | 状态查看页面格式 |

**配置示例**：
```nginx
upstream backend {
    server 192.168.0.1:80;
    server 192.168.0.2:80;

    # 每 5 秒检查一次，失败 3 次下线，成功 2 次上线，超时 4 秒
    check interval=5000 rise=2 fall=3 timeout=4000 type=http;

    # HTTP 健康检查配置
    check_http_send "GET /health HTTP/1.0\r\n\r\n";
    check_http_expect_alive http_2xx http_3xx;

    # 启用长连接检查（可选）
    check_keepalive_requests 100;
}

server {
    listen 80;

    location / {
        proxy_pass http://backend;
    }

    # 健康检查状态页
    location /status {
        check_status json;  # 可选 html, csv, json
        access_log off;
        allow 10.0.0.0/8;
        deny all;
    }
}
```

**支持的健康检查类型**：
- `tcp`：仅建立 TCP 连接
- `http`：发送 HTTP 请求并验证响应
- `ssl_hello`：发送 SSL Client Hello
- `mysql`：发送 MySQL ping 包
- `ajp`：发送 AJP ping 包
- `fastcgi`：发送 FastCGI 请求

#### 其他替代方案对比

| 方案 | 类型 | 活跃度 | 特点 |
|------|------|--------|------|
| **nginx_upstream_check_module** | 第三方模块 | 中等 | 功能完整，Tengine 使用 |
| **nginx-upsync-module** | 第三方模块 | 低 | 结合 Consul/etcd 动态发现 |
| **OpenResty + lua-resty-healthcheck** | Lua 扩展 | 高 | 灵活可编程 |
| **Traefik** | 替代代理 | 高 | 原生支持主动健康检查 |
| **Envoy** | 替代代理 | 高 | 云原生，功能强大 |

#### OpenResty + Lua 实现示例

```nginx
lua_shared_dict healthcheck 1m;

upstream backend {
    server 127.0.0.1:8081;
    server 127.0.0.1:8082;
    server 127.0.0.1:8083;
}

init_worker_by_lua_block {
    local hc = require "resty.healthcheck"
    local checker = hc.new({
        name = "my-checker",
        shm_name = "healthcheck",
        checks = {
            active = {
                healthy = {
                    interval = 5,
                    successes = 2,
                },
                unhealthy = {
                    interval = 5,
                    http_failures = 3,
                },
            },
        },
    })

    checker:add_target("127.0.0.1", 8081)
    checker:add_target("127.0.0.1", 8082)
    checker:add_target("127.0.0.1", 8083)
}
```

**选型建议**：
- 商业环境且有预算：**NGINX Plus**（完整支持，商业支持）
- 开源替代且功能优先：**nginx_upstream_check_module**
- 需要动态配置：**OpenResty + lua-resty-upstream-healthcheck**
- 新架构选型：**Traefik** 或 **Envoy**（原生支持服务发现）

---

## 19. Upstream 模块源码实现分析

基于 nginx 1.31.0 源码（`lib/nginx/src/http/`）。

### 19.1 核心数据结构

#### ngx_http_upstream_t - 上游请求结构

```c
// src/http/ngx_http_upstream.h:336-420
struct ngx_http_upstream_s {
    ngx_http_upstream_handler_pt     read_event_handler;
    ngx_http_upstream_handler_pt     write_event_handler;

    ngx_peer_connection_t            peer;      // 对端连接

    ngx_event_pipe_t                *pipe;      // 管道（流式传输）

    ngx_chain_t                     *request_bufs;  // 请求缓冲

    ngx_http_upstream_conf_t        *conf;      // upstream 配置
    ngx_http_upstream_srv_conf_t    *upstream;  // upstream 组配置

    ngx_http_upstream_headers_in_t   headers_in;  // 上游响应头

    ngx_buf_t                        buffer;    // 响应缓冲

    // 回调函数
    ngx_int_t                      (*create_request)(ngx_http_request_t *r);
    ngx_int_t                      (*reinit_request)(ngx_http_request_t *r);
    ngx_int_t                      (*process_header)(ngx_http_request_t *r);
    void                           (*finalize_request)(ngx_http_request_t *r, ngx_int_t rc);

    ngx_msec_t                       start_time;

    ngx_http_upstream_state_t       *state;     // 状态信息

    unsigned                         store:1;
    unsigned                         cacheable:1;
    unsigned                         buffering:1;
    unsigned                         keepalive:1;
    unsigned                         upgrade:1;   // WebSocket 升级
};
```

#### ngx_http_upstream_rr_peer_t - 服务器节点

```c
// src/http/ngx_http_upstream_round_robin.h
struct ngx_http_upstream_rr_peer_s {
    ngx_str_t                       name;       // 服务器名称
    ngx_addr_t                     *addrs;      // 地址数组
    ngx_uint_t                      naddrs;     // 地址数

    ngx_uint_t                      weight;     // 配置权重
    ngx_uint_t                      effective_weight;  // 有效权重（故障恢复）
    ngx_uint_t                      current_weight;    // 当前权重（轮询用）

    ngx_uint_t                      max_conns;  // 最大连接数
    ngx_uint_t                      conns;      // 当前连接数

    ngx_uint_t                      max_fails;  // 最大失败次数
    time_t                          fail_timeout; // 失败超时
    time_t                          accessed;   // 最后访问时间
    time_t                          checked;    // 最后检查时间

    ngx_uint_t                      fails;      // 失败次数

    ngx_uint_t                      down;       // 是否下线

    unsigned                         backup:1;   // 是否备份服务器
};
```

### 19.2 加权轮询算法（平滑分配）

```c
// src/http/ngx_http_upstream_round_robin.c:810-895
ngx_http_upstream_get_peer(ngx_peer_connection_t *pc, void *data)
{
    // 平滑加权轮询：避免突发集中分配
    for (p = peers->peer; p; p++) {
        if (p 已尝试过 || p down || 超过 max_fails || 超过 max_conns)
            continue;

        p->current_weight += p->effective_weight;  // 累加有效权重
        total += p->effective_weight;

        // 慢恢复：失败后逐步恢复权重
        if (p->effective_weight < p->weight)
            p->effective_weight++;

        // 选 current_weight 最高的
        if (best == NULL || p->current_weight > best->current_weight)
            best = p;
    }

    // 选中后扣减总权重
    best->current_weight -= total;
    return best;
}
```

**算法特点**：
- 权重平滑分配，避免请求集中到某台服务器
- 故障恢复时权重逐步回升，而不是直接恢复
- 支持 backup 服务器组切换

### 19.3 一致性哈希实现

```c
// src/http/modules/ngx_http_upstream_hash_module.c
typedef struct {
    uint32_t                            hash;
    ngx_str_t                          *server;
} ngx_http_upstream_chash_point_t;

typedef struct {
    ngx_uint_t                          number;
    ngx_http_upstream_chash_point_t     point[1];  // 虚拟节点数组
} ngx_http_upstream_chash_points_t;

// 虚拟节点分布在 0-2^32 的圆环上
// 根据 key 的 hash 值查找最近的节点（二分查找）
ngx_http_upstream_find_chash_point(points, hash);
```

### 19.4 Upstream 请求处理流程

```
ngx_http_upstream_init(r)
  |
  v
ngx_http_upstream_init_request(r)
  |
  +-- 解析 upstream 名称
  +-- 创建 peer 连接 (peer.get = ngx_http_upstream_get_round_robin_peer)
  |
  v
ngx_http_upstream_connect(r, u)
  |
  +-- ngx_event_connect_peer() 连接到上游服务器
  |
  v
ngx_http_upstream_send_request() --> 发送客户端请求到上游
  |
  v
ngx_http_upstream_process_header(r, u)
  |
  +-- 解析上游响应头
  +-- ngx_http_upstream_process_headers() 处理 set-cookie 等
  |
  v
分支:
  +-- 缓冲模式: ngx_http_upstream_process_request()
  |     (读完整上游响应到临时文件/内存，再转发给客户端)
  |
  +-- 非缓冲模式: ngx_http_upstream_process_upgraded()
        (双向透传，用于 WebSocket 等升级连接)
  |
  v
ngx_http_upstream_finalize_request(r, u, rc)
  |
  +-- peer.free() 记录失败/成功，更新权重
  +-- 清理资源
```

### 19.5 故障转移机制

```c
// src/http/ngx_http_upstream.c
#define NGX_HTTP_UPSTREAM_FT_ERROR           0x00000002
#define NGX_HTTP_UPSTREAM_FT_TIMEOUT         0x00000004
#define NGX_HTTP_UPSTREAM_FT_INVALID_HEADER  0x00000008
#define NGX_HTTP_UPSTREAM_FT_HTTP_500        0x00000010
#define NGX_HTTP_UPSTREAM_FT_HTTP_502        0x00000020
#define NGX_HTTP_UPSTREAM_FT_HTTP_503        0x00000040
#define NGX_HTTP_UPSTREAM_FT_HTTP_504        0x00000080

ngx_http_upstream_next(r, u, ft_type)
{
    if (u->peer.tries > u->conf->next_upstream_tries)
        return finalize;

    if (ft_type & u->conf->next_upstream) {
        // 符合重试条件，选择下一台服务器
        ngx_http_upstream_connect(r, u);
    } else {
        // 不符合条件，直接结束请求
        ngx_http_upstream_finalize_request(r, u, status);
    }
}
```

### 19.6 关键源码路径

| 功能 | 文件路径 | 大小 |
|------|----------|------|
| Upstream 核心 | `src/http/ngx_http_upstream.c` | 187KB |
| Upstream 头文件 | `src/http/ngx_http_upstream.h` | 16KB |
| Round Robin 负载均衡 | `src/http/ngx_http_upstream_round_robin.c` | 32KB |
| Least Connections | `src/http/modules/ngx_http_upstream_least_conn_module.c` | 4KB |
| Hash/一致性哈希 | `src/http/modules/ngx_http_upstream_hash_module.c` | 8KB |
| Random 负载均衡 | `src/http/modules/ngx_http_upstream_random_module.c` | 6KB |
| Proxy 模块 | `src/http/modules/ngx_http_proxy_module.c` | 80KB |

---

*源码分析基于 nginx 1.31.0*
*源码目录：`lib/nginx/src/http/`*