sse保活需服务端每25–30秒发送:keepalive注释行,nginx需设proxy_read_timeout≥65,框架须禁用响应缓冲,跨域时须返回明确access-control-allow-origin和credentials,前端仅在readystate===0或非200错误时手动重连。

SSE连接本身不管理TCP层,前端EventSource无法主动发心跳。保活必须由服务端每30秒左右发送:keepalive注释行,浏览器收到后重置内部超时计时器,防止静默断连。
服务端心跳必须用注释格式:keepalive 是标准写法,以英文冒号开头,浏览器忽略内容但会重置连接存活状态。不能用 data: 发空值,Safari等浏览器不将其视为有效事件。
避免Nginx提前切断连接
Nginx默认 proxy_read_timeout 为60秒。若服务端心跳间隔超过60秒,Nginx会在浏览器之前关闭连接。建议将心跳设为25–30秒,并同步调大Nginx配置:
location /events {
proxy_pass http://backend;
proxy_read_timeout 65;
proxy_buffering off;
}
框架响应流不能被缓冲
Express、Flask、Spring Boot等常默认启用响应缓冲,导致 res.write() 的心跳卡在内存里不下发。需显式禁用:
- Express:
res.socket.setNoDelay(true)+res.removeHeader('Content-Encoding') - Flask:用
yield+Response(..., direct_passthrough=True) - Spring Boot:必须调用
emitter.send(SseEmitter.event().name("heartbeat").data("")),不能直接写原始流
跨域场景下心跳需携带凭证
前端启用了 withCredentials: true,但服务端未返回 Access-Control-Allow-Credentials: true 或 Access-Control-Allow-Origin 写成 *,会导致后续心跳请求丢失 Cookie。必须返回明确域名,例如:
Access-Control-Allow-Origin: https://your-app.com Access-Control-Allow-Credentials: true
前端不用监听error就重建连接error 事件高频触发,可能是临时网络抖动或单条消息解析失败。应检查 eventSource.readyState:
- 值为
0(closed)才需手动重建 - 值为
1(open)或0以外的其他值,说明正在自动重连或仍有效 - 若服务端返回非200状态码(如503),EventSource会停止重试,此时才需捕获error并手动恢复,配合指数退避重连:
let attempt = 0; const reconnect = () => { eventSource = new EventSource(url, { withCredentials: true }); attempt++; const delay = Math.min(1000 * 2 ** attempt, 30000); eventSource.onerror = () => setTimeout(reconnect, delay); };
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











