proxy_read_timeout只控制响应头返回后等待首个响应体字节的空闲时间,且每次收到数据即重置;它不管理建连、发包或客户端下载,需配合HTTP/1.1透传、proxy_buffering off及后端flush header才能生效。

proxy_read_timeout 不能控制长轮询的总响应时间限制,它只管“响应头已到、但 body 还没来”这一段空闲等待期。长轮询的整个生命周期,从连接建立到最终返回,是由多个环节共同决定的。
它真正控制的是哪一段?
在长轮询中,后端通常先返回 200 OK 和响应头,然后挂起连接,等事件发生或超时才写入响应体(比如一个 JSON 或换行符)。此时:
- ✅ proxy_read_timeout 开始计时:从响应头发出后,Nginx 等待第一个字节响应体的空闲时间
- ✅ 每次收到任意数据(哪怕一个空格),计时器就重置,重新开始等待下一次空闲
- ❌ 它不控制后端处理请求前的排队、建连、读取请求体耗时——那是
proxy_connect_timeout和proxy_send_timeout的事 - ❌ 它也不控制客户端是否断开、网络是否丢包、负载均衡器是否提前切断
想让长轮询“稳住”,必须配套这三件事
单设 proxy_read_timeout 是无效的,容易白调:
- 开启 HTTP/1.1 并透传 Connection 头:
proxy_http_version 1.1+proxy_set_header Connection '',否则 Nginx 可能主动关闭连接 - 禁用响应缓冲:
proxy_buffering off,避免 Nginx 缓存住未完成的流式响应,导致客户端收不到首块数据 - 后端要先发 header 再 flush:
w.WriteHeader(200)+w.(http.Flusher).Flush()(Go)或fastcgi_finish_request()(PHP),否则 Nginx 根本不会进入“等 body”状态
数值怎么设才合理?
不是越长越好,而是要比后端最长挂起时间多出 5–10 秒缓冲:
- 若后端用
context.WithTimeout(ctx, 30*time.Second)控制等待,Nginx 设为35s或40s即可 - 别盲目设成
300s或3600s——会吃光 worker 连接,影响并发能力 - 务必检查上游云负载均衡器(如 AWS ALB 默认 60 秒、阿里云 SLB 默认 60 秒),它的 idle timeout 往往比 Nginx 更早生效
别漏掉服务端和客户端协同
光靠 Nginx 配置不够,还要两端配合:
- 服务端定期发送 keepalive 帧(如
:或空行),防止中间设备因长时间无数据而断连 - 客户端设置合理的重连策略(指数退避),并在收到 504 时主动重试而非静默失败
- 监控
$upstream_response_time日志字段:如果大量请求卡在 39 秒、59 秒、89 秒,说明当前值正在被频繁触发,需微调


















