websocket需自定义双向心跳机制,客户端每30秒发ping、5秒未收pong则重连;服务端收到ping立即回pong,不走业务逻辑;双方超时阈值错开(如客户端5秒、服务端45秒),并适配nginx的proxy_read_timeout等配置。

WebSocket 本身不内置心跳机制,但可以通过定时发送自定义消息(如 "ping" / "pong")来实现双向心跳包,用以检测连接是否存活、防止中间代理(如 Nginx、负载均衡器)断连。关键在于客户端和服务端**各自独立维护发送与响应逻辑**,且需避免单方面超时误判。
客户端:主动发 ping,监听 pong 响应
浏览器中 WebSocket 没有原生 onpong 事件,所以需约定消息类型,用普通消息模拟心跳。推荐在连接建立后启动定时器,同时设置响应超时监控:
- 连接成功(
onopen)后,每 30 秒发送一次{ type: "ping" }字符串或 JSON - 收到服务端返回的
{ type: "pong" }时,清除当前超时计时器,并立即启动下一轮 - 若发送 ping 后 5 秒内未收到 pong,则认为连接异常,可触发重连
- 注意:不要在
onmessage中无差别处理所有消息——先判断data.type再分流
服务端:收到 ping 立即回 pong,不延迟
以 Node.js + ws 库为例,服务端应最小化处理延迟,确保 pong 响应及时:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 监听
message事件,检查data是否为{"type":"ping"}(建议用JSON.parse安全解析) - 匹配后立刻调用
socket.send('{"type":"pong"}'),不 await 异步操作,不加日志或中间件 - 避免把 pong 当作普通业务消息走完整路由——心跳必须旁路处理
- 可选:在连接对象上记录最后收到 ping 的时间戳,用于后续连接健康度统计
连接状态协同管理:避免假死和误断
单靠一方心跳容易误判。理想做法是双方都“发 ping + 等 pong”,并各自设超时阈值(建议服务端超时略长于客户端):
- 客户端超时设为 5 秒,服务端等待 ping 的间隔容忍设为 45 秒(即连续 1.5 个周期没收到 ping 才标记异常)
- 服务端也可主动向客户端发 ping(尤其在长连接低频场景),但需客户端同样支持响应 pong
- 网络抖动时可能丢包,允许 1–2 次心跳失败后才触发重连,避免雪崩式重连
- 重连前清空旧定时器,关闭旧 socket,避免多个心跳定时器并发运行
补充:Nginx 等反向代理的心跳适配
如果 WebSocket 经过 Nginx,需显式开启长连接支持,否则默认 60 秒无数据会断开:
- Nginx 配置中添加:
proxy_read_timeout 300;(建议 ≥ 客户端 ping 间隔 × 2) - 同时设置:
proxy_set_header Connection 'upgrade'; proxy_http_version 1.1; - 确认后端服务(如 ws 库)未设置自身心跳(例如
ws.Server({ heartbeatInterval: ... })),避免与应用层心跳冲突
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










