Content‑Type:
text/event-stream,长连接、单向推送,Nginx 默认配置很容易断连、超时。
一、核心问题
SSE 是长连接 HTTP 流,Nginx 默认超时很短,会主动断开;同时默认开启缓冲,会把 event‑stream 缓存住不实时下发到浏览器。
必须关闭缓存、调大超时、禁用代理缓冲
二、最简可用配置片段
location /sse {
proxy_pass http://127.0.0.1:8080;
# 关键 SSE 参数
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "keep-alive";
# 关闭Nginx响应缓冲,数据立刻发给客户端
proxy_buffering off;
proxy_cache off;
# 长连接超时,设置很大,SSE依靠客户端心跳断开
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
# 可选:关闭gzip,部分浏览器代理压缩会卡住流
proxy_set_header Accept-Encoding "";
}
参数逐条解释
proxy_http_version 1.1Nginx 默认向后端用 HTTP/1.0,Connection: close,长连接直接废掉,SSE 必断。必须切 1.1。proxy_set_header Connection "keep-alive"维持后端长连接。
WebSocket 需要
Upgrade,纯 SSE 不需要 Upgrade;写上也无害。
proxy_buffering off;最关键!Nginx 默认缓存后端返回流,攒够一块再发给浏览器,text/event-stream消息延迟、收不到。proxy_read_timeout 86400sNginx 默认proxy_read_timeout 60s:后端 60 秒没发任何数据 → Nginx 主动关闭连接。 SSE 如果长时间没有推送消息就会被断开。后端最好定时发: ping\n\n心跳包保活。
三、后端心跳保活(推荐)
服务端定时发送注释心跳,防止 Nginx 超时切断:
: ping
以冒号开头为 SSE 注释,浏览器忽略,仅用来占住连接。
四、HTTPS + SSE 完整站点示例
server {
listen 443 ssl;
server_name sse.example.com;
ssl_certificate cert/fullchain.pem;
ssl_certificate_key cert/privkey.pem;
location /stream {
proxy_pass http://127.0.0.1:3000;
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_set_header X‑Forwarded‑Proto $scheme;
proxy_set_header Connection "keep-alive";
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
proxy_set_header Accept-Encoding "";
}
}
五、常见坑 & 排错清单
- 每隔 60 秒断开连接 👉 原因:
proxy_read_timeout默认 60s,改大 + 后端发心跳。 - 收不到消息,浏览器一直 pending 👉 大概率忘记
proxy_buffering off。 - 连接很快断掉,根本连不上 👉 没加
proxy_http_version 1.1 - Nginx gzip 卡住流 👉
proxy_set_header Accept-Encoding "";让后端不返回压缩内容。
六、Nginx 开源版 vs Nginx‑Plus
开源版 Nginx 原生支持 SSE 代理,不需要任何额外模块。
七、前端 JS 测试代码
const evtSource = new EventSource("https://sse.example.com/stream");
evtSource.onmessage = (e)=>{
console.log("收到",e.data);
};
evtSource.onerror = err=>{
console.error("连接错误",err);
};
正文完
可以使用微信扫码关注公众号(ID:xzluomor)