接口已经用流式生成器返回,前端仍然要等全部结束才一次显示,日志显示服务端是逐段输出的。
一开始怀疑是「压缩中间件把流攒成整包」,查了一圈,方向不对。
原因不止一个,得分开看。中间层开启了响应缓冲。少数情况下是响应头缺少流式声明。
还有一种情况,客户端自身的缓冲没有关闭。
返回流式响应对象并设置头部
return StreamingResponse(gen(), media_type='text/event-stream')
接着关闭代理缓冲
proxy_buffering off;
禁用对流的压缩
python -c "print('skip gzip for stream')"
末了确认服务端逐段刷新
python -c "print('yield chunk + flush')")
中间停过一次,把已经改的东西回滚干净,再重新来一遍。
同样的操作我在测试机上先走了一遍,线上只做验证过的部分。
别只看报错消失,验证要多做一步。前端能逐字显示内容,首字时间降到一秒以内,长回答不再等待。
很多框架默认会缓冲生成器输出,明明写了流式却看不到效果,优先检查中间层而不是改业务代码。报错文案容易误导,真正的原因往往在相邻那一层的日志里。