SSE 流式请求避免 nginx 缓冲导致块式输出的解决办法
- 前端开发
- 2025-06-08
- 216热度
- 0评论
在前端以 SSE(Server Sent Event) 调用大模型 API 请求时,正常应该是流畅的按字符响应,但却出现了断断续续按块式输出的现象,使得体验较差。
这主要是因为 Nginx 默认会启用代理缓冲 proxy_buffering
,从而导致 SSE 数据被缓存并按块返回。可以通过修改 Nginx 配置禁用缓冲来解决。
1 Nginx 禁用 proxy_buffering
配置示例
以下是一个简单的 Nginx 配置示例,它禁用了代理缓冲:
server {
listen 443 ssl http2;
server_name example.com;
# 处理静态文件的路径
location /static/ {
alias /home/lzw.me/test-sse/static/;
}
# 正常 API 请求转发到后端
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $http_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;
}
# 转发 SSE 请求,匹配以 /sse/ 开头的路径
location ~ ^/sse/ {
# 后端服务器地址
proxy_pass http://127.0.0.1:8000;
# proxy_pass http://backend_upstream;
# 关闭代理缓冲
proxy_buffering off;
# 关闭代理缓存
proxy_cache off;
# 设置代理的响应头部,保持传输编码为 chunked
proxy_set_header X-Accel-Buffering no;
# 设置 HTTP 版本为 HTTP/1.1
proxy_http_version 1.1;
# 保持连接活性,不发送 `Connection: close` 连接关闭 header 信息
proxy_set_header Connection '';
# 设置代理读取服务器响应的超时时间,避免 SSE 长连接被断开
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
# 设置客户端连接的超时时间
proxy_connect_timeout 1h;
# 转发访问端使用的 Host 头信息
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 禁用客户端缓存
add_header Cache-Control no-cache;
# 禁用 Nginx 的响应缓冲。也可以在程序代码中设置此 header,例如(Java示例):
# res.setHeader('X-Accel-Buffering', 'no');
add_header X-Accel-Buffering "no";
# 启用分块传输编码
chunked_transfer_encoding on;
# 防止 gzip 压缩,避免 chunked 被打包
gzip off;
# 允许 CORS 跨域(CORS 跨域为可选,视实际情况而定)
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Origin,Authorization,Accept,X-Requested-With' always;
# 支持 CORS 预检请求,返回 204
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Origin,Authorization,Accept,X-Requested-With';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
}
}
2 APISIX 禁用 proxy_buffering
配置示例
APISIX 是基于 Nginx 的 API 网关,可以通过配置 proxy-rewrite
插件的 disable_buffering
参数来达到同样的效果。示例配置如下:
{
"uri": "/sse",
"plugins": {
"proxy-buffering": {
"disable_proxy_buffering": true
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"your-backend-service:80": 1
}
}
}
此外也可以通过 response-rewrite
插件添加 X-Accel-Buffering: no
头信息来实现同样的效果:
{
"disable": false,
"headers": {
"X-Accel-Buffering": "no"
}
}