HTML5服务器推送心跳_HTML5SSE定时发送心跳维持长连接方法介绍【介绍】

1次阅读

sse连接需服务端每30秒发送:keepalive注释重置超时,避免浏览器静默关闭;须处理nginx超时、框架缓冲、cors凭证、cookie安全属性及Error事件误判等四层问题。

HTML5服务器推送心跳_HTML5SSE定时发送心跳维持长连接方法介绍【介绍】

html5 SSE 连接断开前没发心跳,浏览器自动关闭连接

服务端不主动发送数据,SSE 连接通常在 30–60 秒后被浏览器静默关闭(chrome/firefox 表现一致),这不是 bug,是规范行为。SSE 协议要求服务端定期发送注释行或空事件来重置超时计时器。

  • 最简方案:服务端每 30 秒发一条 :keepalive 注释(以 : 开头,浏览器忽略但重置心跳)
  • 别用 data: 发空值——部分浏览器(如 safari)不认 data:nn 为有效事件,仍会断连
  • Node.js express 示例中,别在 res.write() 后漏掉 nn(两个换行符),否则事件不完整,浏览器无法解析
  • Nginx 默认 proxy_read_timeout60 秒,若后端心跳间隔 >60s,Nginx 会先于浏览器断开连接

EventSource 监听 error 事件不等于连接失败

error 事件触发频率高,且可能由网络抖动、短暂服务不可达或单次消息解析失败引发,并非都代表连接永久中断。盲目在 error 回调里立即 new EventSource() 会导致请求风暴。

  • 检查 eventSource.readyState:只有 0closed)才需重建;0 以外的 error 大概率正在自动重连
  • 服务端返回非 200 状态码(如 503)时,EventSource 会触发 error 并停止重试——此时必须手动恢复
  • 重连间隔建议用指数退避:math.min(1000 * 2 ** attempt, 30000),避免压垮服务端

服务端流式响应被框架缓冲,心跳延迟或丢失

很多 Web 框架(如 Express、flaskspring Boot)默认启用响应体缓冲,导致即使你调用了 write(),数据也卡在内存里不下发,心跳失效。

  • Express 中必须设置 res.flushHeaders() + res.socket.setNoDelay(true),并禁用压缩:res.removeHeader('Content-Encoding')
  • Flask 需用 yield + Response(..., content_type='text/event-stream'),且禁用 Werkzeug 的 Response 自动缓冲(加 direct_passthrough=True
  • spring bootSseEmitter 要调用 emitter.send(SseEmitter.event().name("heartbeat").data("")),不能只写原始流

跨域场景下 withCredentials 不生效,心跳携带不了 Cookie

前端用 new EventSource(url, { withCredentials: true }),但服务端没配 access-Control-Allow-Credentials: trueAccess-Control-Allow-Origin 写死 *,会导致凭证被丢弃,后续心跳请求无登录态。

立即学习前端免费学习笔记(深入)”;

  • Access-Control-Allow-Origin 不能是 *,必须显式写出请求来源域名(如 https://example.com
  • 如果服务端用 Nginx 做 CORS,注意 add_header 默认不继承,需在 location 块内重复声明
  • Cookie 的 SameSite=NoneSecure 属性必须同时设置,否则 Chrome 84+ 拒绝发送

服务端心跳不是“发个空行”就完事,它卡在协议层、框架层、代理层、浏览器层四道关卡上,少一个环节,连接就在你以为稳定的时候悄无声息断掉。

text=ZqhQzanResources