apache中websocket频繁断开主因是未启用mod_proxy_wstunnel模块,导致代理层误将websocket当普通http处理,60秒空闲即静默断连;必须启用该模块、用ws://或wss://前缀配置proxypass、透传upgrade和connection头、设timeout与proxytimeout≥3600,并配合客户端≤25秒心跳。
apache 中 websocket 连接频繁断开,核心不是网络不稳,而是代理层没真正“认出” websocket 协议,把它当普通 http 处理了——60 秒一到就静默断连。解决的关键是让 apache 明确走隧道模式、透传关键头部、延长超时,并确保每一步都生效。
必须启用 mod_proxy_wstunnel 模块
仅开启 proxy 和 proxy_http 不够。WebSocket 升级(Upgrade: websocket)必须由专用隧道模块处理,否则握手后帧被丢,连接直接掉成 1006 错误。
- 检查是否已加载:
sudo a2enmod proxy proxy_http proxy_wstunnel,然后重启 Apache - 验证命令:
apache2ctl -M | grep wstunnel,输出中应含proxy_wstunnel_module (shared) - 若手动编译安装,确认
httpd.conf中三行未被注释:LoadModule proxy_module modules/mod_proxy.soLoadModule proxy_http_module modules/mod_proxy_http.soLoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
ProxyPass 必须用 ws:// 或 wss:// 前缀
写成 http://localhost:8080/ 就等于告诉 Apache:“这是个普通 HTTP 请求”,它不会触发隧道逻辑,后续所有帧都会被丢弃。
Apache Superset 是一个广泛采用的开源 BI 平台,用于 SQL 探索、图表构建和仪表板交付。当代理需要查询仓库数据、组装仪表板或使用成熟的分析界面解释指标而不是临时笔记本代码时,此技能非常有用。
- 正确写法示例:
ProxyPass "/ws" "ws://localhost:8080/" - 路径要严格匹配:前端连
wss://mydomain.xyz/ws/chat,则 ProxyPass 路径也应为/ws/或更精确的/ws/chat,避免隐式重写导致 404 或降级 - HTTPS 站点务必用
wss://后端地址(若后端本身支持 TLS),或确保 SSL 终止在 Apache 层,证书有效且 SNI 正常
同步设置 Timeout 和 ProxyTimeout 并透传 Upgrade 头
默认 60 秒超时是高频断连的直接推手;而 Upgrade 和 Connection 头若被清洗,握手根本无法完成(状态码卡在 200,而非 101)。
- 在对应
<virtualhost></virtualhost>块中添加:Timeout 3600ProxyTimeout 3600 - 强制透传协议升级头:
RequestHeader set Connection "upgrade"RequestHeader set Upgrade "websocket" - 确保已启用
mod_headers:sudo a2enmod headers - 可临时加日志辅助排查:
LogLevel info proxy:trace5,查看错误日志中是否有upgrade denied或tunnel established关键词
补充建议:配合客户端与服务端协同防断
代理配置只是基础。如果心跳间隔太长、服务端超时太短,或前端不处理重连逻辑,照样会断。
- 前端心跳建议 ≤25 秒,服务端最大空闲时间设为 ≥60 秒,留出网络抖动余量
- 遇到
onclose.code === 1006,基本可锁定是 Apache 主动发 RST;code === 1001则查服务端日志(如 heartbeat timeout) - 重连时先调
ws.close(4999, "reconnect")清旧连接,加布尔锁防止并发重连,token 过期类错误需先刷新凭证再重连










