现在很多小伙伴都会折腾各种大模型相关的服务,比如自建大模型 API 聚合网关(如 CLIProxyAPI)。

但在用 Nginx 反代大模型接口时,很多朋友往往照搬常规的 Web 反代模板,结果一测流式传输就傻眼了——明明请求参数里传了 "stream": true,但前端打字机效果完全失效,不仅没有丝滑的一个字一个字往外蹦,反而像是卡住死机了一样,直到后端模型全部生成完毕或者憋够了一大段,才瞬间“哗啦”一下子全部吐出来。

其实问题就出在 Nginx 的一个默认设置上,今天特此记录一下这个坑点及解决办法。

罪魁祸首:Nginx 的响应缓冲(proxy_buffering)

大模型的流式输出主要依赖 SSE(Server-Sent Events,服务器发送事件) 协议。SSE 本质上是一个保持开启的 HTTP 长连接(Content-Type: text/event-stream),后端每推理生成一个 token,就会以小数据块(chunk)的形式即时向客户端推送一段数据。

而 Nginx 作为高性能反向代理,默认情况下它的配置是:

1
proxy_buffering on;

1. 为什么 Nginx 默认开启缓冲?

在传统 Web 场景下,开启缓冲是为了提高网络吞吐效率并减轻后端应用服务器的压力。Nginx 会尽可能快地把后端吐出来的响应全部读进自己的内存缓冲区(如果数据太大还会暂存到磁盘临时文件),等攒满一个 buffer 或者后端响应全部完成之后,再慢慢发给网络条件参差不齐的客户端。

2. 如果不关掉它,会是什么表现?

对传统网页来说这是极好的优化,但对于 SSE 流式接口来说,这就成了灾难:

  • 假死式等待:后端大模型吐出的每一个 SSE event 通常只有几十到上百字节。Nginx 收到后不会立刻发给前端,而是默默把它扣在自己的缓冲区里等待“凑整”。
  • 卡顿/憋大招:客户端在屏幕前只能看着光标干转圈,等 Nginx 的缓冲区(通常是 4k / 8k / 16k)终于被填满了,才会把这一个缓冲区的数据一次性推给客户端。
  • 打字机变复印机:对于输出较短的回答,甚至可能一直等到后端大模型完全结束会话、关闭连接,Nginx 才把整篇回答当成一次普通响应直接甩给前端,流式交互体验荡然无存。

解决办法:明确禁用响应缓冲

解决这个问题非常简单,只需要在 Nginx 对应的 location 块中加入一行关键配置:

1
proxy_buffering off;

它的作用就是彻底关闭 Nginx 对后端上游响应的缓冲机制。一旦设置为 off,Nginx 只要从后端大模型服务收到任何数据块(哪怕只有几个字节),就会立刻同步转发给客户端,打字机流式效果瞬间恢复丝滑!

完整的大模型反代配置参考

除了 proxy_buffering off;,反代大模型接口时通常还需要兼顾长连接、超时时间等问题,这里整理了一份实用、不易踩坑的完整 location 配置供参考:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
location / {
proxy_pass http://127.0.0.1:8317; # 替换为你自己的后端大模型网关或上游服务地址

# 核心:关闭响应缓冲,确保 SSE 流式实时推送
proxy_buffering off;

# 保持 HTTP/1.1 长连接,清除 Connection 头
proxy_http_version 1.1;
proxy_set_header Connection "";

# 常用请求头透传
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

# 超时时间调大:大模型深度思考或长文生成耗时较长,避免默认 60s 读超时断连
proxy_connect_timeout 60s;
proxy_send_timeout 600s;
proxy_read_timeout 600s;
}

补充要点:

  1. proxy_read_timeout 600s;:现在的大模型(尤其是带 Thinking / Reasoning 的推理模型)在思考阶段可能会有相当长一段时间不吐字,Nginx 默认的 proxy_read_timeout 只有 60 秒,很容易在模型还在思考时就被 Nginx 主动掐断连接报 504 Gateway Time-out,因此务必把读超时调大。关于超时的详细分析与设置要点,可以参阅我之前写的这篇文章:解决Nginx反向代理OpenAI Response协议60秒超时中断的问题。
  2. X-Accel-Buffering: no:有些服务端程序会在响应头中主动附带 X-Accel-Buffering: no,通知 Nginx 临时关闭缓冲;但自己配置 Nginx 时,直接写死 proxy_buffering off; 最为稳妥,不依赖后端实现的自觉性。
  3. 前置 CDN 注意事项:如果你的 Nginx 前面还挂了 Cloudflare 等 CDN,记得在 Cloudflare 控制台或 WAF 规则里也要注意关闭压缩与缓冲,或者确认你的套餐对长连接 SSE 的超时支持情况。

修改配置后执行 nginx -t && nginx -s reload 重载配置即可生效,收工~