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 的超时配置必须与上游微服务的超时设置形成 递减链,才能实现快速失败:
- 客户端 → Nginx: client_header_timeout / client_body_timeout(通常 10-30s)
- Nginx → 上游: proxy_connect_timeout / proxy_read_timeout / proxy_send_timeout
- 上游服务内部: 数据库连接超时、HTTP 客户端超时、业务处理超时
超时链原则:外层超时 > 内层超时,但外层应尽量接近内层,避免无谓等待。例如上游服务内部设置 8s 超时,Nginx 的 proxy_read_timeout 应设为 10s,而不是 60s。
最佳实践: 在 Nginx 日志中记录 $upstream_response_time 和 $upstream_connect_time,通过监控告警识别哪些上游频繁触发超时,反向推动上游服务优化。
4.4 超时配置的并发影响与调优
超时配置直接影响 Nginx 的并发连接容量。以下 SVG 展示了超时时间与最大并发连接数的关系:
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将故障节点临时摘除。