Apache mod_proxy 默认缓冲请求体,需通过SetEnv nokeepalive 1、SetEnv downgrade-1.0 1、ProxyTimeout/TimeOut调优、禁用mod_deflate/mod_security对body的干预等措施实现流式转发,确保边接收边转发。

Apache 的 mod_proxy 默认会对请求体(request body)进行缓冲再转发,这对大流量、大体积请求(如文件上传、视频流、长连接 API)会造成内存占用高、延迟上升甚至超时失败。要实现流式转发(即边接收边转发,不缓存整块 body),关键在于禁用缓冲行为,并配合协议与超时调优。
关闭请求体缓冲,启用流式代理
mod_proxy_http 在处理 POST/PUT 等含 body 的请求时,默认启用 buffering,尤其在启用了 SSL 终止或设置了某些响应头时更易触发。需显式关闭:
- 在 ProxyPass 指令后添加 nocanon 和 disablereuse=off(仅当需复用连接时),但核心是设置:
ProxySet buffer=0或更可靠的方式 —— 使用 ProxyPass ... enablereuse=on 并配合底层内核参数 - 真正起效的是禁用 Apache 自身的 request body 缓冲:在虚拟主机或 Location 块中加入
SetEnv nokeepalive 1SetEnv downgrade-1.0 1
这会强制 Apache 以 HTTP/1.0 方式转发,跳过内部 chunked 解析与重组逻辑,实现“透传”效果 - 若后端支持 HTTP/1.1 流式,还可加:
RequestHeader set Expect ""
避免因 Expect: 100-continue 导致额外等待
调整超时与连接复用参数
流式转发依赖稳定、低干预的 TCP 连接,需防止 Apache 中途断连或重置:
- 增大代理级超时(单位秒):
ProxyTimeout 300TimeOut 300
尤其对上传类请求,避免 body 未传完就被中断 - 启用连接复用并延长空闲时间:
ProxySet keepalive=onProxySet keepalive_timeout=60ProxySet max=50
减少新建连接开销,提升吞吐连续性 - 若后端为长连接服务(如 gRPC-Web、自定义流协议),建议搭配
ProxySet acquire=3000控制连接获取等待上限
绕过缓冲模块干扰(关键细节)
某些 Apache 版本或启用了其他模块(如 mod_deflate、mod_security)会隐式读取并缓存 request body,导致流式失效:
- 确保 mod_deflate 不作用于 POST/PUT 请求体:
SetEnvIf Request_Method "POST|PUT" no-gzip - 若使用 mod_security,检查 SecRequestBodyAccess 是否为 On —— 如非必要,设为 Off;否则需配置 SecRequestBodyLimit 足够大,并启用 SecRequestBodyInMemoryLimit 0(避免磁盘缓存)
- 禁用 .htaccess 中可能存在的 php_value auto_prepend_file 或类似钩子,它们会提前触发 PHP 读取 $_POST,破坏流式上下文
验证是否真正流式转发
最直接方式是抓包或日志观测:
- 用
tcpdump -i lo port 8080观察后端端口是否有持续小包(而非等几十秒后一股脑发出) - 开启 Apache 代理日志:
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %{pid}P %{tid}P" proxyCustomLog logs/proxy.log proxy
关注%b字段:流式下该值应随传输逐步增长,而非最终才写入 - 后端服务日志中检查首次收到 body 数据的时间点 —— 应与客户端开始发送几乎同步(误差











