边界说明:本次输入未提供任何官方文档正文,因此本文不对 DeepSeek API 的具体超时默认值、请求参数名、错误码或端点行为作断言,这些需以官方文档为准。下文全部属于通用工程分析,讨论的是 SSE 长连接在 Node.js / Python 服务与反向代理之间的稳定性配置方法。

一、把「超时」拆成四段
一次流式请求至少要区分四种时间预算,混用同一个 timeout 值是排查困难的根源。
1. 连接超时:TCP 与 TLS 握手完成的时间上限,通常设为几秒。
2. 首字节超时:从请求发出到收到响应头的时间上限。排队、鉴权、限流都会拉长这一段。
3. 空闲读取超时:两次数据块之间的最大间隔。这是流式场景真正该盯的值——整条流可能持续几分钟,但块与块的间隔通常很短。
4. 总时长上限:整条流允许的最长持续时间,作为兜底。
最常见的错误是把读取超时设成整条流的总时长:上游一旦卡住,客户端要等到总超时才报错;反过来把总时长当成读取超时,则会在正常回答中被提前截断。

二、Node.js 侧
用 fetch(undici)或 axios 时,超时通过 AbortSignal 实现。做法是先用 AbortController 配合 setTimeout 约束首字节阶段,收到响应头后清除该定时器,改用一个每收到数据块就重置的空闲计时器。关键点是:拿到流之后不能让首字节定时器继续跑,否则长回答会在中途被 abort。
读取循环里应当在每次 read 之前 rearm 计时器,而不是在循环外设一个固定的 deadline。如果使用 axios,注意 responseType 与 stream 选项决定了拿到的是流还是完整缓冲,选错会直接让流式退化成一次性响应。

三、Python 侧
httpx 的 Timeout 对象支持 connect、read、write、pool 四项分别设置,其中 read 表示两次读之间的空闲上限,正好对应流式场景;aiohttp 的 ClientTimeout 提供 total 与 sock_read 两类语义,sock_read 更接近空闲读取超时。同步客户端同理。无论用哪种,都应显式设置 read 类超时而不是依赖默认值,并在异常处理里区分「连接阶段失败」与「流中途断开」:前者通常可安全重试,后者重试可能产生重复输出或重复计费,需要业务侧自行判断。

四、半开连接与心跳
半开连接指链路已不可用但双方都没收到 FIN/RST,表现为读取一直阻塞而不报错。识别手段有三种。一是依赖操作系统 TCP keepalive,但其默认触发时间常以小时计,需要显式调小。二是依赖应用层心跳:SSE 允许以冒号开头的注释行作为心跳,它不产生业务事件,却能刷新读取计时器并抑制中间设备的空闲回收。三是把客户端空闲读取超时设为明显大于心跳间隔的值,例如心跳间隔的 2~3 倍,超过即主动断开并重连。若上游不发心跳,只能由应用层按固定间隔自行写入注释行。

五、反向代理必须关缓冲
Nginx 默认会缓冲上游响应,这会让 SSE 变成「攒够一整块才发」,表现为客户端长时间无数据后突然收到一大段,或流在代理层被截断。至少检查以下几项:proxy_buffering off(或对该 location 单独关闭);proxy_cache off;proxy_http_version 1.1 并正确设置 Connection 头,避免退回 1.0 的短连接语义;proxy_read_timeout 设为大于客户端空闲读取超时——它约束的是代理等待上游两次读之间的时间,设小了会在流中途返回 504;send_timeout 与 keepalive_timeout 同样参与长连接行为;压缩链路中的 gzip 会引入缓冲,流式接口通常直接关闭。此外,若上游支持,可在响应中带 X-Accel-Buffering: no 让 Nginx 对单次响应关闭缓冲,但该头由上游控制,应用侧不能假定它一定存在。

六、客户端断开后终止上游
用户关闭页面或取消请求时,如果服务端不终止上游请求,会持续占用连接与配额。Node.js 侧监听 res 或 req 的 close 事件,触发 AbortController.abort(),注意「请求体读完」与「连接关闭」不是同一个事件。Python 侧在异步生成器被取消时会抛 CancelledError,需要在 finally 中显式关闭上游响应上下文。原则是:客户端连接的生存期与上游请求的生存期绑成一对,任一侧结束就释放另一侧。

七、排查顺序
建议按此顺序定位:先看服务端日志里首字节耗时与块间隔的分布,确认是「迟迟不来」还是「中途停」;再绕过反向代理直连上游,判断是否为代理引入;然后在代理与客户端两侧分别记录时间戳,找出是哪一段的空闲计时先触发;最后检查压缩与缓冲配置。日志中至少记录开始时间、首字节时间、最后一块时间与结束原因,否则只能靠猜。

小结:流式通道的稳定性不取决于单个 timeout 值多大,而取决于四类超时是否分开设置、心跳与读取超时是否匹配、代理是否真的关闭了缓冲,以及断开时上游是否被释放。