proxy_read_timeout 应设为匹配业务心跳或处理节奏的值,如WebSocket设90–120秒、报表导出设240–300秒,并须与proxy_send_timeout一致且在location块内配置,同步调整upstream keepalive和后端超时参数。

proxy_read_timeout 不是连接总时长限制,而是读空闲超时
它只管 Nginx 从后端读数据时“等多久没动静就断”,不管 WebSocket 握手、客户端到 Nginx 的 keep-alive、也不管后端是否还在处理。设成 0 并不等于永不断连——内核 TCP 超时(如 net.ipv4.tcp_keepalive_time)和后端自身 timeout 仍会生效。
常见错误现象:upstream timed out (110: Connection timed out) 日志里没写明是 connect 还是 read,其实大概率是后端已关连接,而 Nginx 还在等数据;或者后端卡在 DB 查询,proxy_read_timeout 到了就直接 504,但后端日志里显示请求几秒后才完成。
- WebSocket 场景下,它决定两次 ping/pong 或业务帧之间的最大静默间隔,不是整个会话时长
- 报表导出类接口,它控制的是“后端开始发响应体后,Nginx 等完整流的上限”,不是从请求发起到返回第一个字节的时间
- 跨域请求中,它完全不参与 OPTIONS 预检阶段——预检失败根本走不到这一步
按场景设值:别全局统一填 300 或 86400
默认 60 秒对多数 API 偏长,对长连接又偏短。真实值必须匹配业务心跳或处理节奏:
- WebSocket 实时聊天:客户端和服务端每
30s交换一次 ping/pong,proxy_read_timeout设为90~120 - 工控设备上报(固定
45s心跳):proxy_read_timeout设180,留出网络抖动余量 - 大报表导出(P99 耗时
210s):proxy_read_timeout设240~300,且必须单独用location块隔离,避免拖累其他接口 - 低频通知通道(如审批推送):
proxy_read_timeout3600足够,再大意义不大,反而延长故障发现时间
必须同步调的三项配置,缺一不可
单改 proxy_read_timeout 是纸面功夫。下面三个不配齐,超时行为会错乱甚至失效:
安装并运行 Aperture(Lightning Labs 的 L402 闪电反向代理),用于创建 L402 付费墙、配置付费 API 端点、为其他代理托管付费内容或测试 L402 认证流程。
-
proxy_send_timeout必须与proxy_read_timeout一致(如都设300),否则请求发到一半被单向切断 -
upstream块里加keepalive 32,并确保proxy_http_version 1.1和proxy_set_header Connection ''已启用,否则连接根本不复用 - 系统级
net.ipv4.tcp_keepalive_time建议 ≥7200,否则内核可能比 Nginx 更早 kill 掉空闲连接
特别注意:若后端是 Tomcat 或 Spring Boot,其 connectionTimeout 必须 > proxy_read_timeout 至少 3~5 秒,否则后端先断,Nginx 还在等,最终报错仍是 upstream timed out。
验证方式比设值更重要
调完不验证,等于没调。重点看三处:
- 开
error_log /var/log/nginx/error.log debug(临时),搜"upstream timed out"和"client closed connection",确认是哪一环断的 - 用
curl -v http://backend-ip:port/api/xxx直连后端,对比真实耗时和 Nginx 日志里的upstream_response_time - 检查
nginx -T | grep -A5 'location /ws',确认你改的proxy_read_timeout确实落在对应location块里,没被更外层覆盖
最容易被忽略的是:改完必须 nginx -t && nginx -s reload,热重载不生效;以及 WebSocket 场景下,proxy_read_timeout 再大,也救不了没实现应用层心跳的后端——它只是探测器,不是续命符。

















