chunked_transfer_encoding仅控制nginx自身直出响应(如静态文件、error_page)是否允许在无content-length时启用chunked编码,默认on,设off则直接断连;它对proxy_pass等代理场景完全无效,流式关键在于后端持续输出+proxy_buffering off+http/1.1透传。

chunked_transfer_encoding 不是“智能启用”的开关,它只是一个允许或禁止 Nginx 自身作为源服务器(非代理)在无 Content-Length 时使用分块编码的布尔指令。真正决定是否走分块、能否实现稳定流式下发的,是后端行为、代理配置与协议协同,而非该指令本身。
明确 chunked_transfer_encoding 的作用边界
该指令仅影响 Nginx 直出场景(如静态文件、error_page、autoindex),默认值为 on,表示允许;设为 off 时,若响应既无 Content-Length 又非空,Nginx 会直接关闭连接,不发响应体。它对 proxy_pass、FastCGI 等 upstream 场景完全无效——这些场景下是否出现 Transfer-Encoding: chunked,取决于上游服务是否以分块方式输出,以及 Nginx 是否缓冲。
流式下发的核心不在“开启 chunked”,而在“禁用缓冲”
要让大文本真正逐块透传,关键不是让 Nginx “生成” chunked,而是让它不拦、不等、不攒:
- proxy_buffering off;:强制 Nginx 边收边发,避免等待整个响应体收完再转发
- proxy_http_version 1.1; + proxy_set_header Connection '';:维持 HTTP/1.1 长连接,清除可能干扰的 Connection 头
- proxy_cache off;:防止缓存层截断或重写响应流
- proxy_read_timeout 300;:延长读取超时,适配长周期流式输出(如 AI 生成、日志推送)
后端与客户端必须同步配合
Nginx 只是通道,两端不协调,流式就会卡住或退化:
-
后端需主动 flush:例如 Python FastAPI 用
yield、Node.js 用res.write()+res.flush(),PHP 要关 output buffering 并调用flush() -
后端响应头不能含 Content-Length,且建议显式声明
Content-Type: text/plain或text/event-stream -
前端必须流式消费:fetch 需用
response.body.getReader(),不可调.text()或.json();curl 测试用curl -N避免内置缓冲
验证是否真正在流式传输
别信响应头,要看 TCP 层实际行为:
- 用
tcpdump -i lo port 8000 -w stream.pcap抓包,Wireshark 中过滤http,观察响应体是否由多个带十六进制前缀的小段组成(如7\r\nhello\r\n、5\r\nworld\r\n、0\r\n\r\n) - 若只看到一个大 TCP 包,说明某环节(Nginx、LB、gzip 中间件)仍在缓冲
- 用
curl -v http://your-domain/stream检查响应头是否同时存在Transfer-Encoding: chunked且不含Content-Length
不复杂但容易忽略。核心就三点:后端持续输出、Nginx 不缓冲、客户端不等全量。











