Nginx主动断连是SSE流式中断主因,关键在proxy_read_timeout(两次数据包间隔上限)和proxy_buffering(必须关闭);需配proxy_http_version 1.1、proxy_set_header Connection '',并用tcpdump确认RST来源。

大模型 SSE 流式输出被 Nginx 代理切断,通常不是后端没发数据,而是 Nginx 在“等不及”的瞬间主动断开了连接——连接已建好、响应已开始,但中间某次空闲超时触发了 504 或静默中断。排查要聚焦在 Nginx 主动终止行为上,而非后端是否存活。
重点查 proxy_read_timeout 是否被误用
这是最常见也最容易误解的环节。proxy_read_timeout 不是“整个响应耗时上限”,而是“两次收到后端数据包之间的最大空闲间隔”。大模型流式输出(如 token 逐个生成)若某次生成间隔超过该值(默认 60 秒),Nginx 就会断连。
- 检查 location 块中是否显式设置了 proxy_read_timeout 3600s 或更长(建议至少 1h,匹配大模型单次推理最大容忍空闲)
- 确认该配置未被上级 http/server 块中的短值覆盖(可用 nginx -T 验证最终生效值)
- 注意:若后端每 45 秒 flush 一次,但你配了 60 秒,仍可能因网络抖动或 GC 暂停导致第 N 次间隔超限
必须关闭 proxy_buffering 并禁用缓存链
SSE 是持续分块输出,Nginx 默认开启的缓冲机制会攒够 buffer 才转发,造成前端“卡几秒后突然刷出一整段”,掩盖真实延迟,也容易触发超时重试。
- 在对应 SSE 路径(如 /v1/chat/completions/event)的 location 中加:proxy_buffering off;
- 同步关闭干扰项:proxy_cache off; proxy_request_buffering off; gzip off;
- 不关 buffering,其他所有优化都无效;gzip 开着会导致浏览器无法按行解析 data: 字段,直接卡死
验证协议与连接头是否透传正确
SSE 依赖 HTTP/1.1 持久连接和 chunked 传输。Nginx 若回落到 HTTP/1.0 或篡改 Connection 头,会导致连接反复重建,破坏流连续性。
- 确保 location 中有:proxy_http_version 1.1; 和 proxy_set_header Connection '';
- 用 curl -v 直连后端,确认响应头含 Transfer-Encoding: chunked 或无 Content-Length
- 若后端返回 X-Accel-Buffering: no,Nginx 会忽略它;必须靠 proxy_buffering off 强制关闭
抓包确认断连发生在哪一环
仅看日志不够,需定位是 Nginx 主动 RST,还是后端提前 FIN,或是中间设备(云 LB、防火墙)劫持断连。
- 在 Nginx 服务器执行:tcpdump -i any 'host 后端IP and port 后端端口' -w sse-debug.pcap
- 复现问题后用 Wireshark 打开,过滤 tcp.flags.reset == 1 查谁发的 RST 包
- 若看到 Nginx IP 发出 RST,且时间点紧贴 proxy_read_timeout 设定值,基本锁定为 Nginx 主动断连
- 若 RST 来自云厂商 LB(如阿里云 SLB 默认 60 秒空闲超时),需同步在控制台调大其 timeout


















