Apache代理WebSocket心跳保活超时断开的核心问题是将WebSocket误作HTTP处理而主动切断空闲TCP连接;必须启用mod_proxy_wstunnel模块、用ws/wss协议前缀配置ProxyPass、透传Upgrade/Connection头,并将ProxySet timeout与KeepAliveTimeout设为3600。
apache 代理导致 websocket 心跳保活超时断开,核心问题不是心跳没发,而是 apache 在连接空闲时主动切断了 tcp 链路——它把 websocket 当成普通 http 处理,默认不维持长连接。排查要聚焦在 apache 的代理配置、超时参数和头信息透传三方面。
检查 Apache 是否启用 WebSocket 代理支持
Apache 2.4.5 及以上版本才原生支持 WebSocket 代理(通过 mod_proxy_wstunnel)。低于此版本无法正确处理 Upgrade 流程,连接会在握手后立即关闭。
- 运行 httpd -M | grep proxy 或 a2enmod -l,确认已加载 proxy_module、proxy_http_module 和 proxy_wstunnel_module
- 若未启用 proxy_wstunnel,仅靠 proxy_http 会把 WebSocket 请求当作普通 HTTP 转发,导致服务端收不到 Upgrade 头,返回 200 而非 101
- 配置中必须使用 ProxyPass "/ws" "wss://backend:8080/ws"(或 ws://),不能写成 ProxyPass "/ws" "http://backend:8080/ws"
验证关键头信息是否完整透传
WebSocket 握手依赖特定请求头触发协议升级,Apache 必须原样转发,不能过滤或改写。
- 确保配置中包含:
ProxyPreserveHost On
RequestHeader set Connection "upgrade"
RequestHeader set Upgrade "websocket" - 特别注意:Connection 和 Upgrade 是大小写敏感的字符串,值必须是 "upgrade" 和 "websocket",不能带多余空格或引号错误
- 用 curl 模拟握手验证:
curl -i -N -H "Connection: upgrade" -H "Upgrade: websocket" -H "Sec-WebSocket-Version: 13" http://your-apache-host/ws
观察响应是否含 HTTP/1.1 101 Switching Protocols,否则说明头未透传成功
调整 Apache 超时参数防止静默断连
Apache 默认启用 keepalive,但对代理连接有独立超时控制。若未显式延长,60 秒无数据就会 RST 断开,远短于常见心跳间隔(如 30 秒发一次 ping)。
Apache Superset 是一个广泛采用的开源 BI 平台,用于 SQL 探索、图表构建和仪表板交付。当代理需要查询仓库数据、组装仪表板或使用成熟的分析界面解释指标而不是临时笔记本代码时,此技能非常有用。
- 在 Proxy 配置块中添加:
ProxySet keepalive=On
ProxySet timeout=3600
ProxySet retry=0(避免临时故障后跳过该后端) - 全局或虚拟主机中设置:
KeepAlive On
KeepAliveTimeout 3600
MaxKeepAliveRequests 0(不限制请求数) - 重点:timeout 值应 ≥ 心跳间隔 × 2(例如心跳 30 秒,则 timeout 至少设为 60;建议直接设为 3600 避免误判)
确认后端服务能响应应用层心跳
即使 Apache 代理配置正确,若后端未识别或响应客户端发送的业务心跳(如 {"type":"ping"}),连接仍会在 Apache 超时后被关闭。
- 在 Apache 日志中开启详细代理日志:
LogLevel proxy:trace4
查看是否有 proxy_wstunnel: debug 级别日志,确认 Upgrade 流程是否完成、数据帧是否双向流通 - 用浏览器 Network → WS → Frames 查看:客户端是否发出 ping、服务端是否返回 pong(文本帧)、中间是否有延迟或丢失
- 若服务端只响应协议层 Pong(RFC 6455 控制帧),而前端发的是应用层 ping 消息,则需统一协议——Apache 不干预应用层内容,但要求前后端约定一致










