大模型SSE接口配置:从零实现流式输出
大模型SSE接口配置的核心是让服务端以text/event-stream格式持续推送数据,同时确保中间层(Nginx、网关)不缓冲、不超时。
本文从零开始,带你完成从后端代码到Nginx反向代理的完整配置,并给出验证方法和常见报错处理。
先确认你的环境是否支持SSE
SSE(Server-Sent Events)基于HTTP长连接,服务器单向向客户端推送文本流。
大模型对话的“打字机效果”通常就用它实现。
开始配置前,请确认:
- 后端框架能逐块输出响应,例如Python Flask的
stream_with_context、FastAPI的StreamingResponse、Node.js的res.write。 - 服务器或容器允许长连接,没有强制短连接或请求体大小限制。
- 如果前面有Nginx、CDN或负载均衡,需要针对性关闭缓冲和延长超时。
下面以Python Flask + Nginx为例,其他语言逻辑相同。
后端输出流式响应的最小示例
先写一个模拟大模型逐字输出的接口,保存为app.py:
from flask import Flask, Response, stream_with_context
import time
app = Flask(__name__)
@app.route('/v1/chat/stream')
def stream_chat():
def generate():
for word in ['你', '好', ',', '这', '是', '流', '式', '响', '应']:
yield f'data: {word}\n\n'
time.sleep(0.2)
yield 'data: [DONE]\n\n'
return Response(stream_with_context(generate()), mimetype='text/event-stream')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
关键点:响应头Content-Type必须是text/event-stream;
每条消息以data: 开头,以两个换行\n\n结束;
结束标记可自定义,如[DONE]。
启动服务:
python app.py
用curl直接测试后端是否流式输出:
curl -N http://127.0.0.1:5000/v1/chat/stream
如果终端逐字打印,说明后端正常。-N参数关闭curl自身缓冲。
Nginx反向代理必须关闭缓冲
生产环境通常用Nginx转发。
默认的代理缓冲会把流式数据攒起来,导致客户端长时间无输出。
在站点配置的location块中加入:
location /v1/chat/stream {
proxy_pass http://127.0.0.1:5000;
proxy_http_version 1.1;
proxy_set_header Connection '';
proxy_set_header Host $host;
proxy_buffering off;
proxy_cache off;
chunked_transfer_encoding on;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
}
proxy_buffering off是核心,关闭后Nginx收到数据就转发。proxy_read_timeout根据模型响应时间调整,建议不小于300秒。
修改后执行nginx -t检查语法,再nginx -s reload重载。
如果使用宝塔面板,路径为:网站 → 设置 → 配置文件,在对应location中添加上述指令,保存后重载Nginx。
容易忽略的避坑点
- CDN或云负载均衡:部分CDN默认缓冲响应,需要在控制台开启“流式传输”或关闭压缩/缓冲,否则Nginx配置正确也会失效。
- Gzip压缩:对
text/event-stream启用gzip可能导致缓冲,建议在Nginx中对SSE路径关闭gzip:gzip off;。 - HTTP/2:某些客户端在HTTP/2下对SSE支持不一致,可暂时用HTTP/1.1测试。
- 跨域:前端直接调用时,后端需返回
Access-Control-Allow-Origin,并允许text/event-stream。 - 连接数限制:每个SSE连接占用一个长连接,并发高时注意调整Nginx的
worker_connections和后端进程数。
验证配置是否生效
从外部机器执行:
curl -N -H 'Accept: text/event-stream' http://你的域名/v1/chat/stream
观察是否逐条出现data:行。
如果卡住无输出,按顺序排查:
- 直连后端端口是否流式(排除后端问题)。
- Nginx错误日志
tail -f /var/log/nginx/error.log是否有超时或缓冲相关报错。 - 检查CDN或安全组是否拦截长连接。
- 确认
proxy_buffering off写在正确的location块内。
常见疑问
SSE和WebSocket怎么选? 大模型对话只需服务端单向推送,SSE更简单且基于HTTP,兼容性好;
需要双向实时交互时再考虑WebSocket。
为什么浏览器里能收到但前端框架没反应? 检查前端是否使用EventSource并监听message事件,或使用fetch的ReadableStream手动解析data:行。
接口返回200但内容一次性出现? 大概率是Nginx缓冲未关闭或CDN缓冲,按上文检查。
完成以上配置后,你的大模型SSE接口应能稳定输出流式内容。
建议先在测试环境用curl验证,再接入前端,遇到异常优先回看Nginx缓冲和超时设置。