ELB空闲超时是WebSocket长连接被强制断开的主因,默认60秒无数据即关闭;需调高ALB/NLB空闲超时至≤4000秒、服务端启用STOMP双向心跳(如15秒)、客户端同步配置,并补充应用层心跳(≤30秒)及抓包与日志验证。

ELB(Amazon Elastic Load Balancing)空闲超时是 WebSocket 长连接被强制断开的常见原因,尤其在使用 Application Load Balancer(ALB)或 Classic Load Balancer 时,默认 60 秒无数据交互就会关闭连接。这不是客户端或服务端代码问题,而是基础设施层的主动回收行为,必须从配置和心跳协同两方面解决。
调整 ELB 空闲超时设置
ALB 和 NLB 支持自定义空闲超时时间,最大可设为 4000 秒(约 66 分钟),NLB 更支持 TCP 层长连接维持:
- ALB:进入控制台 → 目标组(Target Group)→ 编辑属性 → “Idle timeout” 修改为 3600 秒(1 小时)或更高;注意该值需 ≥ 客户端与服务端的心跳间隔
- NLB:更适配 WebSocket,因工作在四层(TCP),不解析 HTTP 头,天然绕过 ALB 的协议限制;其空闲超时默认为 3600 秒,也可调至 4000 秒
- Classic ELB 已逐步弃用,若仍在使用,务必升级——它对 WebSocket 升级头支持不完整,易导致握手失败
服务端启用 STOMP 心跳(Spring Boot 场景)
当使用 @EnableWebSocketMessageBroker 时,底层是 STOMP over WebSocket,必须显式配置双向心跳,否则 ELB 虽延长了超时,Broker 仍会在 sessionTimeout 后销毁会话:
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
- 在
WebSocketConfig中添加:
stompEndpointRegistry.addEndpoint("/ws").setAllowedOrigins("*");
registry.setHeartbeatTime(15000, 15000); // 发送/接收心跳间隔均为 15 秒 - 确保客户端(如 Stomp.js)也启用对应心跳:
const client = Stomp.over(socket);
client.heartbeat.outgoing = 15000;
client.heartbeat.incoming = 15000; - 心跳帧由 STOMP 协议自动处理,无需手动 send "ping" 字符串
客户端补充应用层心跳兜底
ELB 或网络中间设备可能忽略或丢弃 STOMP 心跳帧(尤其在某些 NAT 或防火墙策略下),建议在业务层叠加轻量心跳:
- 每 25 秒发送一次简单 JSON 消息:
if (socket.readyState === WebSocket.OPEN) {
socket.send(JSON.stringify({ type: "keepalive", ts: Date.now() }));
} - 服务端收到后不做业务处理,仅响应 ACK 或记录日志,避免引入额外逻辑负担
- 此心跳间隔需严格 小于 ELB 设置的 idle timeout(例如 ELB 设为 3600s,则心跳 ≤ 30s)
验证与监控要点
光改配置不够,需确认生效并持续观测:
- 抓包验证:用 Wireshark 或 tcpdump 检查 TCP 层是否有 RST 包出现;若有,说明 ELB 或下游服务主动中断,而非客户端断开
- 服务端日志:开启 Spring WebSocket DEBUG 日志,搜索
StompSubProtocolHandler和SessionDisconnectEvent,确认是否因 heartbeat timeout 触发断连 - 浏览器控制台:监听
onclose事件,打印event.code和event.reason;若为1006且无明显错误信息,大概率是 ELB 或网络层静默断连










