这是《计算机网络 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 代理是现代网络架构的常见组件。它可以是正向代理,代表客户端访问外部;也可以是反向代理,代表服务端接收请求。网关则进一步承载协议转换、路由、认证、限流、观测和流量治理。理解代理的地址透传、协议转换、超时传递和故障语义,是定位线上问题的基础。
19.1 正向代理与反向代理
| 类型 | 方向 | 代表谁 | 典型场景 |
|---|---|---|---|
| 正向代理 | 客户端 -> 外部 | 客户端 | 出口管控、缓存、审计 |
| 反向代理 | 客户端 -> 内部服务 | 服务端 | LB、TLS 终止、路由、防护 |
正向代理:
Client -> Forward Proxy -> Internet -> Server
反向代理:
Client -> Reverse Proxy / Gateway -> Backend
对后端来说,反向代理是直接客户端;对用户来说,反向代理就是服务入口。
19.2 代理的透明性
常见头部:
| Header | 含义 |
|---|---|
| X-Forwarded-For | 客户端和代理链 IP |
| X-Real-IP | 常用于直接客户端 IP |
| X-Forwarded-Proto | 客户端原始协议 |
| X-Forwarded-Host | 原始 Host |
| X-Request-ID | 链路请求 ID |
Nginx:
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;
安全原则:
- 只信任可信入口设置的头;
- 入口代理覆盖外部传入的转发头;
- 后端根据可信代理跳数取真实 IP;
- 记录完整链路或规范化客户端 IP;
- 审计日志与访问日志统一语义。
19.3 正向代理模式
HTTP 代理
curl -x http://proxy.example.com:8080 https://www.example.com
HTTP 代理可以看到明文 HTTP 内容;访问 HTTPS 时通常使用 CONNECT 建隧道。
HTTPS CONNECT
Client -> Proxy: CONNECT www.example.com:443
Proxy -> Client: HTTP/1.1 200 Connection Established
Client <-> Server: TLS
代理知道目标域名和流量大小,若不做中间人解密,无法看到 TLS 内容。
SOCKS 代理
SOCKS5 支持 TCP 和 UDP 代理:
curl --socks5 host:port https://www.example.com
19.4 反向代理能力
反向代理常承担:
- TLS 终止;
- HTTP 路由;
- 负载均衡;
- 健康检查;
- 缓存;
- 压缩;
- 限流;
- 重写;
- 访问日志;
- 故障隔离。
示例:
upstream app {
server 10.0.1.10:8080 max_fails=3 fail_timeout=10s;
server 10.0.1.11:8080 max_fails=3 fail_timeout=10s;
}
server {
listen 443 ssl;
server_name api.example.com;
location / {
proxy_pass http://app;
proxy_connect_timeout 2s;
proxy_read_timeout 10s;
proxy_next_upstream error timeout http_502 http_503;
}
}
19.5 API 网关
API 网关是带业务治理能力的反向代理。
常见能力:
| 能力 | 示例 |
|---|---|
| 认证 | JWT、OAuth2、mTLS |
| 授权 | 路由级、租户级、API 级 |
| 限流 | 单 IP、用户、API、租户 |
| 熔断 | 下游错误率过高时快速失败 |
| 路由 | 路径、Header、权重、地域 |
| 协议转换 | REST 到内部 RPC |
| 观测 | 日志、指标、trace |
| 安全 | WAF、Bot 治理 |
边界:
- 网关不应包含复杂业务规则;
- 数据校验仍需服务端完成;
- 网关高可用影响全站可用性;
- 重试必须与幂等配合;
- 网关不能掩盖服务容量问题。
19.6 超时与重试
链路示例:
Client
-> LB
-> Gateway
-> Service
-> DB
超时设置原则:
外层超时必须覆盖内层可接受的处理时间,同时设置总上限
重试预算要小于外层超时
推荐:
- 数据库 50ms 到数秒,视查询而定;
- 内部服务 100ms 到 2s;
- 网关到服务 2s 到 10s;
- 用户请求按业务 SLA 设置;
- 连接超时小于读超时;
- 空闲超时大于心跳间隔;
- 所有组件超时来源可配置。
重试要考虑:
- 方法是否幂等;
- 业务是否有幂等键;
- 5xx 是否可重试;
- 429 和 Retry-After;
- 重试次数和总预算;
- 随机退避;
- 熔断状态。
19.7 代理与缓存
HTTP 缓存:
proxy_cache_path /var/cache/nginx keys_zone=api_cache:10m;
适合缓存:
- 公共静态资源;
- 低频变化配置;
- 可容忍短暂延迟的商品数据;
- 聚合报表。
不适合缓存:
- 用户订单列表;
- 支付结果;
- 权限数据;
- 个性化敏感数据。
私有响应不能进入共享缓存:
Cache-Control: private, no-store
19.8 故障语义
常见错误:
| 状态 | 可能原因 |
|---|---|
| 502 | 后端连接失败、握手失败、后端崩溃 |
| 503 | 后端不可用、健康检查失败、限流 |
| 504 | 后端处理超时 |
| 499 | 客户端主动断开,Nginx 语义 |
| 400 | 请求头过大、协议错误 |
| 431 | 请求头字段过大 |
排障要看两侧:
代理日志:upstream、状态、耗时、重试
后端日志:请求是否到达、处理耗时、错误
如果代理有 499 而后端无日志,可能是后端未及时收到或客户端极早断开;如果后端慢,应继续查服务与依赖。
19.9 网关高可用
要求:
- 多实例部署;
- 入口 DNS 或 LB 多活;
- 无状态或状态外置;
- 配置热更新;
- 健康检查分级;
- 后端摘除自动化;
- 过载保护;
- 管理面与数据面隔离;
- 配置版本化;
- 变更可回滚。
容量规划要同时考虑:
- QPS;
- 并发连接;
- TLS 握手;
- 请求体大小;
- 日志写入;
- 后端延迟;
- 突发重试;
- 带宽。
本章小结
正向代理代表客户端访问外部,反向代理和 API 网关代表服务端承接流量。代理通过 X-Forwarded-* 传递链路信息,但必须防止外部伪造。网关治理认证、路由、限流、熔断、观测和协议转换,超时与重试必须跨层级设计。502、503、504、499 需要结合代理与后端两侧日志定位。
思考题
- 正向代理和反向代理分别代表谁?
- 为什么不能信任外部传入的 X-Forwarded-For?
- HTTPS 经过 HTTP 代理时 CONNECT 做了什么?
- API 网关应该承载哪些能力,不应承载哪些业务?
- 设计一条 Client -> Gateway -> Service -> DB 链路的超时与重试预算。