Computer NetworkNotes

第 19 章:代理与网关

zjc 于 2026-01-19 发布

这是《计算机网络 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 代理是现代网络架构的常见组件。它可以是正向代理,代表客户端访问外部;也可以是反向代理,代表服务端接收请求。网关则进一步承载协议转换、路由、认证、限流、观测和流量治理。理解代理的地址透传、协议转换、超时传递和故障语义,是定位线上问题的基础。

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;

安全原则:

  1. 只信任可信入口设置的头;
  2. 入口代理覆盖外部传入的转发头;
  3. 后端根据可信代理跳数取真实 IP;
  4. 记录完整链路或规范化客户端 IP;
  5. 审计日志与访问日志统一语义。

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 反向代理能力

反向代理常承担:

  1. TLS 终止;
  2. HTTP 路由;
  3. 负载均衡;
  4. 健康检查;
  5. 缓存;
  6. 压缩;
  7. 限流;
  8. 重写;
  9. 访问日志;
  10. 故障隔离。

示例:

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 治理

边界:

  1. 网关不应包含复杂业务规则;
  2. 数据校验仍需服务端完成;
  3. 网关高可用影响全站可用性;
  4. 重试必须与幂等配合;
  5. 网关不能掩盖服务容量问题。

19.6 超时与重试

链路示例:

Client
  -> LB
     -> Gateway
        -> Service
           -> DB

超时设置原则:

外层超时必须覆盖内层可接受的处理时间,同时设置总上限
重试预算要小于外层超时

推荐:

  1. 数据库 50ms 到数秒,视查询而定;
  2. 内部服务 100ms 到 2s;
  3. 网关到服务 2s 到 10s;
  4. 用户请求按业务 SLA 设置;
  5. 连接超时小于读超时;
  6. 空闲超时大于心跳间隔;
  7. 所有组件超时来源可配置。

重试要考虑:

  1. 方法是否幂等;
  2. 业务是否有幂等键;
  3. 5xx 是否可重试;
  4. 429 和 Retry-After;
  5. 重试次数和总预算;
  6. 随机退避;
  7. 熔断状态。

19.7 代理与缓存

HTTP 缓存:

proxy_cache_path /var/cache/nginx keys_zone=api_cache:10m;

适合缓存:

  1. 公共静态资源;
  2. 低频变化配置;
  3. 可容忍短暂延迟的商品数据;
  4. 聚合报表。

不适合缓存:

  1. 用户订单列表;
  2. 支付结果;
  3. 权限数据;
  4. 个性化敏感数据。

私有响应不能进入共享缓存:

Cache-Control: private, no-store

19.8 故障语义

常见错误:

状态 可能原因
502 后端连接失败、握手失败、后端崩溃
503 后端不可用、健康检查失败、限流
504 后端处理超时
499 客户端主动断开,Nginx 语义
400 请求头过大、协议错误
431 请求头字段过大

排障要看两侧:

代理日志:upstream、状态、耗时、重试
后端日志:请求是否到达、处理耗时、错误

如果代理有 499 而后端无日志,可能是后端未及时收到或客户端极早断开;如果后端慢,应继续查服务与依赖。

19.9 网关高可用

要求:

  1. 多实例部署;
  2. 入口 DNS 或 LB 多活;
  3. 无状态或状态外置;
  4. 配置热更新;
  5. 健康检查分级;
  6. 后端摘除自动化;
  7. 过载保护;
  8. 管理面与数据面隔离;
  9. 配置版本化;
  10. 变更可回滚。

容量规划要同时考虑:

  1. QPS;
  2. 并发连接;
  3. TLS 握手;
  4. 请求体大小;
  5. 日志写入;
  6. 后端延迟;
  7. 突发重试;
  8. 带宽。

本章小结

正向代理代表客户端访问外部,反向代理和 API 网关代表服务端承接流量。代理通过 X-Forwarded-* 传递链路信息,但必须防止外部伪造。网关治理认证、路由、限流、熔断、观测和协议转换,超时与重试必须跨层级设计。502、503、504、499 需要结合代理与后端两侧日志定位。

思考题

  1. 正向代理和反向代理分别代表谁?
  2. 为什么不能信任外部传入的 X-Forwarded-For?
  3. HTTPS 经过 HTTP 代理时 CONNECT 做了什么?
  4. API 网关应该承载哪些能力,不应承载哪些业务?
  5. 设计一条 Client -> Gateway -> Service -> DB 链路的超时与重试预算。