Nginx反向代理大SSE流式接口
当你的后端接口基于 SSE(Server-Sent Events)持续推送大流量数据,而前端却迟迟收不到最新消息时,问题往往出在 Nginx 的 proxy_buffering 上。
Nginx 反向代理大 SSE 流式接口时,必须关闭 proxy_buffering,否则响应会被 Nginx 缓冲到结束才转发,实时推送就变成了“一次性返回”。
本文从零开始,给出关闭方法、验证步骤和常见坑。
先搞清楚:为什么 Nginx 会“吞掉”SSE 数据?
Nginx 默认开启 proxy_buffering,它的作用是先把后端响应完整读入缓冲区,再统一发给客户端。
普通接口这样没问题,但 SSE 是长连接服务端持续推送事件,如果 Nginx 一直缓冲,客户端就只能在连接结束或缓冲区满时才收到数据,实时性彻底丢失。
大 SSE 流式接口因为数据量更大、推送更频繁,更不适用于默认缓冲行为。
所以必须对这类路径单独关闭 proxy_buffering,让 Nginx 边收边发。
配置前准备:备份文件并确认 Nginx 版本
操作前先备份当前配置,避免改错后无法回滚。
执行以下命令确认版本和配置正确性:
nginx -v
nginx -t
备份配置(路径以你的实际安装为准):
cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
如果你用的是宝塔面板,一般在“网站 - 设置 - 配置文件”中直接编辑,也可以先复制一份到本地再改。
核心操作:在 location 中关闭 proxy_buffering
只对 SSE 接口所在路径关闭缓冲,不影响其他普通接口。
在对应的 server 配置里添加或修改如下 location:
location /sse {
proxy_pass http://backend;
proxy_buffering off;
proxy_cache off;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_read_timeout 3600s;
}
关键指令是 proxy_buffering off;,必须写在 location 内。proxy_http_version 1.1 和 Connection "" 是让后端复用连接,避免 SSE 连接被反复握手。proxy_read_timeout 建议调大,防止长连接中途断开。
宝塔用户直接把这段粘贴到站点的配置文件对应 server 中,保存后执行 nginx -t 检查再重载。
验证是否真正生效:curl 与日志检查
重载 Nginx:
nginx -s reload
使用 curl 的 -N 参数禁用本地缓冲,观察数据是否实时打印:
curl -N http://你的域名/sse
如果终端能逐行看到服务端推送的数据,说明 Nginx 代理链路已经生效。
搭配 curl -i 可以看响应头,例如出现 Transfer-Encoding: chunked 或无缓冲区相关字段,也说明关闭成功。
如果仍卡顿,检查是否还有 CDN、其他层 Nginx 或面板缓存插件在中间缓冲。
避坑与高频问题
- 不要全局关闭 buffering:只针对
/sse这类路径关闭,否则会影响静态文件代理和普通接口的下载性能。 - 多层 Nginx 都要关:如果前面还有一层负载均衡或 CDN,那层也需要配置相同的关闭规则。
- HTTPS 不影响这个行为:证书配置不是缓冲的原因,别在证书上浪费时间。
- 日志排查方向:查看 Nginx error log 中是否出现
upstream timed out,若出现则优先调大proxy_read_timeout,同时确认后端 SSE 心跳间隔是否超过超时时间。
总之,Nginx 反向代理大 SSE 流式接口时,proxy_buffering 必须关闭,核心配置只有一条指令,但验证和排错要看完整链路。
如果你正在处理这个问题,请按本文步骤执行,遇到异常优先检查 location 匹配和途经的缓存节点。