nginx高频流式推送延迟飙升的真凶是proxy_buffering默认开启导致响应积压。表现为前端延迟突增、p99跳变而upstream_response_time很短,可通过日志差值、error.log警告及curl首字节时间确认,并需在location中精准关闭proxy_buffering及相关缓冲配置。

高频实时推送(如 SSE、WebSocket、LLM token 流)下,Nginx 代理延迟飙升的常见真凶不是网络或后端慢,而是 proxy_buffering 默认开启导致响应数据在内存/磁盘中积压不发。这种积压表现为:前端“等几秒突然刷出一大段”,P99 延迟跳变,而 $upstream_response_time 却很短——时间全耗在 Nginx 自身缓冲逻辑里。
确认是否是缓冲区积压引发的延迟
先用日志快速验证:在 access_log 中加入 $request_time 和 $upstream_response_time,并统计差值:
- 若大量请求满足 $request_time − $upstream_response_time > 100ms,且集中在 /events、/stream、/chat 等路径,基本可锁定为 Nginx 内部处理延迟
- 检查 error.log 是否出现 "an upstream response is buffered to a temporary file" 警告——说明响应体已溢出内存缓冲,开始写磁盘,IO 开销直接拉高延迟
- 用 curl -v 访问流式接口,观察首字节时间(time_appconnect + time_starttransfer),若明显滞后于后端实际输出节奏,就是缓冲卡住了
精准定位积压发生在哪一级缓冲
Nginx 缓冲分三层,需逐层排查:
- proxy_buffering:最常见元凶。默认 on,对流式响应会攒够 proxy_buffer_size + proxy_buffers 总量或超时才发包
- proxy_buffer_size:只缓存响应头。若后端返回超大 header(如含长 JWT、多 Cookie),可能阻塞整个响应流
- 临时文件落盘:当 proxy_max_temp_file_size 不足或被设为 0,大响应体被迫同步写磁盘,触发 I/O stall
针对性关闭与补全配置
不要全局关 proxy_buffering,只在流式路径中精准关闭,并同步解除配套限制:
- 在对应 location 块内加:proxy_buffering off;(必须放在最前,其他配置依赖它生效)
- 强制 HTTP/1.1 长连接:proxy_http_version 1.1; + proxy_set_header Connection '';
- 禁用缓存干扰:proxy_cache off; + proxy_no_cache 1; + add_header Cache-Control no-cache;
- 延长空闲容忍:proxy_read_timeout 86400;(避免心跳间隙被断连)
- 显式告知不缓冲:add_header X-Accel-Buffering no;(部分 Nginx 版本更可靠)
验证与兜底手段
改完配置后,用真实流量验证效果:
- curl -N http://yourdomain.com/events | stdbuf -oL tr '\n' '\n' —— 观察是否逐行实时输出
- 抓包看 TCP payload 分布:正常应小包频发;若看到单次发送数 KB 数据,说明仍有积压
- 监控 nginx_stub_status 中 Active connections 和 Writing 数值:Writing 持续高位,说明响应发出受阻,需检查 upstream keepalive 或后端 flush 行为
- 作为兜底,可在后端代码中主动调用 flush() 或 write(":\n") 注释帧,确保 Nginx 有数据可发,避免因“无数据”误判为空闲











