背景
-
服务:Spring AI MCP Server,SSE 端点
/sse,消息端点/mcp/message -
环境:AWS EC2,Nginx 反代到本地 8049 端口
-
现象:
-
本机直连:
curl -N -H "Accept: text/event-stream" http://localhost:8049/sse正常 -
外部访问:
curl -N -H "Accept: text/event-stream" https://ai.example.com/sse连接建立后一直“卡住”,无事件推送
-
问题原因定位
SSE 依赖长连接、流式输出,常被代理缓冲或压缩导致卡住。排查要点:
-
代理层是否开启了响应缓冲/缓存
-
是否强制压缩(gzip 等)
-
转发协议是否保持 HTTP/1.1(HTTP/1.0 会断流)
-
是否有路径前缀被重写(本例已去掉
/some-api前缀)
最终解决方案(Nginx 配置)
对 /sse 单独关闭缓冲、缓存和压缩,明确使用 HTTP/1.1,延长超时:
server {
listen 443 ssl;
server_name ai.example.com;
# ssl 证书配置略
# 其他接口的通用转发
location / {
proxy_pass http://127.0.0.1:8049;
proxy_http_version 1.1;
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_read_timeout 1800s;
proxy_send_timeout 1800s;
}
# SSE 专用:必须关闭缓冲/压缩
location /sse {
proxy_pass http://127.0.0.1:8049;
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_buffering off; # 关键:关闭缓冲
proxy_cache off;
proxy_request_buffering off;
add_header X-Accel-Buffering no;
add_header Cache-Control "no-cache";
gzip off; # SSE 不要压缩
proxy_read_timeout 1h; # 长连接
proxy_send_timeout 1h;
chunked_transfer_encoding on;
}
}
部署后执行:
nginx -t && nginx -s reload验证步骤
-
外网测试(带 verbose 查看握手与头部):
curl -v -N -H "Accept: text/event-stream" https://ai.example.com/sse正常时会持续挂起并收到
id:/event:流。 -
若前面还有 CDN/ALB:
-
关闭缓存/压缩
-
确保转发使用 HTTP/1.1,不要降级到 1.0
-
-
若前端有跨域需求,可在
/sse加:add_header Access-Control-Allow-Origin "*" always;
经验总结
-
SSE 要求“不断流、不过缓冲、不过压缩”,Nginx 默认缓冲/压缩会导致“连上不出数据”。
-
明确
proxy_http_version 1.1和Connection "",避免被强制短连接。 -
将 SSE 路径单独配置是一种简单且安全的做法,避免影响其他接口。
文章评论