4. Nginx 作为 API Gateway 的超时配置

在微服务架构中,Nginx 常被部署为反向代理层或轻量级 API Gateway。上游微服务实例的网络波动、慢查询或线程阻塞,会直接导致客户端连接挂起。合理配置 proxy_connect_timeout、proxy_read_timeout、proxy_send_timeout 是保障网关稳定性的第一道防线。

4.1 三个超时指令的核心差异

指令 作用阶段 默认值 超时触发条件 典型影响
proxy_connect_timeout TCP 三次握手阶段 60s Nginx 与上游服务器建立 TCP 连接未完成 上游宕机或防火墙丢包时快速失败
proxy_read_timeout 两次连续读操作之间 60s 上游已建立连接,但超过设定时间未发送任何数据 上游慢 SQL、长任务、死锁导致连接挂起
proxy_send_timeout 两次连续写操作之间 60s Nginx 向上游发送请求体时,两次写操作间隔超时 客户端上传大文件或网络拥塞时写阻塞
关键认知: 这三个超时都是 阶段间空闲超时,而非整个请求的总耗时上限。例如 proxy_read_timeout 只监控两次 read() 调用之间的间隔,不限制上游处理一个请求的总时间。

4.2 超时配置的典型场景与推荐值

以下配置基于生产环境经验,按业务场景分类给出推荐初始值:

业务场景 proxy_connect_timeout proxy_read_timeout proxy_send_timeout 说明
实时查询 API(< 200ms) 5s 10s 10s 快速失败,避免占用连接池
文件上传服务 10s 60s 300s 写超时需匹配大文件传输时间
报表导出 / 批处理 5s 300s 60s 读超时放宽,等待上游生成结果
WebSocket 长连接 5s 0(禁用) 0(禁用) 长连接需关闭读/写超时
# 典型实时 API 场景配置示例
location /api/ {
    proxy_pass http://backend_upstream;

    # 连接超时:5 秒
    proxy_connect_timeout 5s;

    # 读超时:10 秒
    proxy_read_timeout 10s;

    # 写超时:10 秒
    proxy_send_timeout 10s;

    # 建议同时设置代理缓冲,避免上游慢速响应拖垮 Nginx
    proxy_buffering on;
    proxy_buffer_size 4k;
    proxy_buffers 8 4k;
}
常见陷阱: 将 proxy_read_timeout 设置得过大(如 600s)并不能解决上游慢查询问题,反而会耗尽 Nginx 的 worker 连接数。应配合上游服务的超时熔断机制,形成端到端的超时链。

4.3 超时链与错误传递机制

Nginx 的超时配置必须与上游微服务的超时设置形成 递减链,才能实现快速失败:

  1. 客户端 → Nginx: client_header_timeout / client_body_timeout(通常 10-30s)
  2. Nginx → 上游: proxy_connect_timeout / proxy_read_timeout / proxy_send_timeout
  3. 上游服务内部: 数据库连接超时、HTTP 客户端超时、业务处理超时

超时链原则:外层超时 > 内层超时,但外层应尽量接近内层,避免无谓等待。例如上游服务内部设置 8s 超时,Nginx 的 proxy_read_timeout 应设为 10s,而不是 60s。

最佳实践: 在 Nginx 日志中记录 $upstream_response_time 和 $upstream_connect_time,通过监控告警识别哪些上游频繁触发超时,反向推动上游服务优化。

4.4 超时配置的并发影响与调优

超时配置直接影响 Nginx 的并发连接容量。以下 SVG 展示了超时时间与最大并发连接数的关系:

超时时间与 Nginx 最大并发连接数关系 并发连接数 超时时间 (s) 10000 5000 2000 0 10s 30s 60s 120s 调优结论 超时时间越长,单个连接占用 worker 的时间越长,并发容量越低 10s / 9000 60s / 2800

4.5 生产环境配置清单与验证

以下清单帮助你在上线前完成超时配置的全面检查:

检查项 验证方法 预期结果
连接超时是否过短 模拟上游端口延迟响应(iptables + tc) Nginx 在设定时间后返回 504
读超时是否匹配上游 P99 响应时间 压测上游服务,观察 $upstream_response_time 读超时 > 上游 P99 响应时间 + 1s 缓冲
写超时是否覆盖最大请求体传输 上传最大允许文件,抓包确认传输时间 写超时 > 最大文件传输时间 + 2s 缓冲
超时链是否形成递减 检查 Nginx 与上游服务的超时配置 Nginx 超时 > 上游超时,且差值合理
错误页面是否友好 触发超时后观察客户端响应 返回 504 并附带 JSON 错误体
# 完整生产级超时配置模板
upstream backend {
    server 10.0.1.10:8080 max_fails=3 fail_timeout=10s;
    server 10.0.1.11:8080 max_fails=3 fail_timeout=10s;
    keepalive 32;
}

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

    # 客户端超时
    client_header_timeout 10s;
    client_body_timeout 30s;
    send_timeout 10s;

    location /api/ {
        proxy_pass http://backend;
        proxy_http_version 1.1;
        proxy_set_header Connection "";

        # 核心超时配置
        proxy_connect_timeout 5s;
        proxy_read_timeout 15s;
        proxy_send_timeout 10s;

        # 缓冲与重试
        proxy_buffering on;
        proxy_buffer_size 4k;
        proxy_buffers 8 4k;
        proxy_next_upstream error timeout invalid_header;
        proxy_next_upstream_tries 2;

        # 错误页面
        proxy_intercept_errors on;
        error_page 502 504 /custom_504.json;
    }

    location = /custom_504.json {
        default_type application/json;
        return 200 '{"code":504,"message":"upstream timeout, please retry"}';
    }
}
监控建议: 在 Prometheus 中采集 nginx_http_upstream_seconds(upstream 响应时间),设置告警规则:当 upstream 响应时间超过 proxy_read_timeout 的 80% 时触发 Warning,超过 100% 时触发 Critical。

4.6 超时与重试的协同策略

超时配置必须与重试策略配合,避免因超时导致雪崩:

  • 幂等请求(GET/HEAD/PUT/DELETE): 允许重试,设置 proxy_next_upstream_tries 2,重试间隔由上游的 fail_timeout 控制。
  • 非幂等请求(POST/PATCH): 禁止自动重试,或仅在连接超时时重试(proxy_next_upstream error timeout),避免重复扣款、重复下单。
  • 重试放大效应: 当上游整体负载较高时,重试会加剧压力。建议配合 max_fails 和 fail_timeout 将故障节点临时摘除。
Nginx 超时与重试决策流程 客户端请求到达 proxy_connect_timeout 触发? 是 重试(幂等请求) 否 继续发送请求 proxy_read_timeout 触发? 重试策略: 幂等请求重试1次,非幂等不重试