流式响应需服务端启用transfer-encoding: chunked且不设content-length,中间链路禁用缓冲,客户端通过流式api消费数据。

直接启用 Transfer-Encoding: chunked 就能实现流式响应,前提是后端不提前写死 Content-Length,且中间链路(如代理、负载均衡器、压缩中间件)不缓冲整个响应。
确认服务端已正确启用分块传输
检查响应头是否包含 Transfer-Encoding: chunked,且不含 Content-Length。两者共存是非法的,多数服务器或网关会拒绝或自动降级为缓冲模式。若你用的是 Express、FastAPI、uWebSockets 等框架,需确保未手动设置 Content-Length,也未开启默认响应体压缩(如 gzip 中间件)——它常会预读全部数据再编码,从而破坏流式行为。
排查中间层是否在偷偷缓冲
即使服务端发出了分块数据,客户端也可能收不到“流式效果”,常见原因包括:
- 反向代理(如 Nginx)开启了
proxy_buffering on,建议设为off并配proxy_buffer_size 4k - 云服务商负载均衡器(如 AWS ALB、Cloudflare)默认缓冲响应,需开启“流式转发”或“HTTP/1.1 透传”选项
- 浏览器 DevTools 的 Network 面板可能聚合显示,建议用
curl -N或 Wireshark 抓包验证 TCP 层是否持续收到小包
客户端需支持并主动消费流式数据
前端 JS 使用 fetch 时,必须通过 response.body.getReader() 读取流;Python 用 HTTPX 要加 stream=True 并迭代 response.iter_bytes();C 语言则需实现状态机解析十六进制块头、CRLF 分隔符和终止块 0\r\n\r\n。关键点是:不能调用 .text() 或 .json() 这类等待完整响应的方法。
调试与验证的实用方法
最可靠的验证方式是抓包看原始字节流:
- 用
tcpdump -i lo port 8000 -w chunked.pcap本地捕获,Wireshark 打开后过滤http,观察响应体是否由多个带十六进制前缀的小段组成 - 若只看到一个大 TCP 包,说明某环节强制缓冲;若看到连续多个小包(如
7\r\nxxx\r\n、9\r\nyyy\r\n、0\r\n\r\n),说明流式通路已就绪 - 配合
curl -v http://localhost:8000/stream查看响应头和首几块内容,快速定位协议层问题
不复杂但容易忽略。核心就三点:服务端不设 Content-Length、中间件不缓冲、客户端不等全量数据。










