结论:chunked_transfer_encoding仅是Nginx自身作为服务器时允许启用分块编码的开关,不优化速率;真正决定流式性能的是后端主动flush、proxy_buffering off禁用代理缓冲、HTTP/1.1透传三者协同。

直接说结论:chunked_transfer_encoding 本身不“配合”协议去优化速率,它只是 Nginx 在特定条件下允许启用分块编码的开关;真正决定动态脚本吐出速率和内存效率的,是后端输出行为 + Nginx 代理缓冲策略 + HTTP/1.1 流式机制三者协同的结果。
关键不在开启 chunked,而在禁用缓冲
动态脚本(如 PHP、Python WSGI、Node.js)生成内容时,若 Nginx 启用 proxy_buffering(默认 on),它会等整个响应收完再发给客户端——这彻底抵消流式价值,内存占用高、首字节延迟大。
- 必须显式关闭:
proxy_buffering off; - 搭配
proxy_buffer_size 4k;和proxy_buffers 8 4k;,让小块数据能快速转发,避免堆积 - 确保后端响应头不含
Content-Length(否则 Nginx 会忽略 chunked,转而用固定长度模式)
后端需主动 flush,且禁用自身缓冲
Nginx 只是管道,它无法强制后端“边算边发”。脚本层必须解除输出缓冲:
- PHP:调用
ob_flush(); flush();每次输出后;禁用output_buffering(php.ini 中设为 Off) - Python(如 Flask):用
Response(response_stream, headers={'Content-Type': 'text/plain'}, direct_passthrough=True),并 yield 数据块 - Node.js(Express):用
res.write(chunk); res.flush();,配合res.socket.setNoDelay(true)
HTTP/1.1 协议层面要保障连接复用与低延迟
Chunked 编码依赖 HTTP/1.1 的持久连接(Keep-Alive),但默认参数可能拖慢小块传输:
- 设置
keepalive_timeout 65;(略高于客户端超时,避免频繁重连) - 启用
tcp_nodelay on;,禁用 Nagle 算法,让每个小 chunk 不等待凑满 TCP 包 - 避免在响应头中添加
Connection: close或干扰流式的中间件(如某些压缩模块)
验证是否真正流式生效
光看 Transfer-Encoding: chunked 头不够,要确认实际行为:
- 用
curl -v http://your-api/endpoint观察响应是否“边收边打印”,而非全部返回后才显示 - 抓包看 TCP 流:应看到多个小 TCP 段,每个含一个
7\r\nxxx\r\n类结构,间隔几十毫秒级 - 浏览器开发者工具 Network → Response → 查看“Chunks”时间轴,首字节(TTFB)应 ≤ 200ms,后续 chunk 间隔稳定


















