Apache代理WebSocket无响应主因是未启用mod_proxy_wstunnel模块、ProxyPass未用ws://或wss://前缀、未透传Upgrade/Connection头、超时设置过短;需逐一验证模块加载、协议前缀、请求头透传及Timeout/ProxyTimeout同步延长至3600秒。
apache 代理 websocket 后端无响应,通常不是后端挂了,而是代理链路在协议握手、头透传或连接维持环节被中断。核心问题在于 apache 没把 websocket 当“隧道”来处理,而是当普通 http 请求转发——结果握手成功但后续帧全丢,前端 readystate 停在 1(open),发消息没日志、没报错、也没回包。
确认 mod_proxy_wstunnel 已启用且生效
这是前提,缺它一切免谈:
- 运行
httpd -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 - 重启 Apache 后再验证,别跳过这步
ProxyPass 必须用 ws:// 或 wss:// 协议前缀
写成 http:// 就等于放弃 WebSocket 支持:
- 错误示例:
ProxyPass /ws http://localhost:8080/ws→ 走 HTTP 代理流程,Upgrade 握手后帧被静默截断 - 正确写法:
ProxyPass /ws ws://localhost:8080/ws/(注意末尾/与后端路径严格一致) - WSS 场景下,前端必须是 HTTPS 页面,且 Apache 虚拟主机需配置 SSL,并使用
wss://前缀
强制透传 Upgrade 和 Connection 头
这两个是 hop-by-hop 头,Apache 默认会清洗,导致后端收不到有效升级请求:
- 在
或块中添加:RequestHeader set Connection "upgrade"RequestHeader set Upgrade "websocket" - 同时启用
mod_headers模块(多数系统默认已启) - 用
curl -i -N -H "Connection: upgrade" -H "Upgrade: websocket" http://your-domain/ws测试,应返回101 Switching Protocols
超时设置必须同步延长到 3600 秒
默认 60 秒 Timeout 会让空闲连接被 Apache 主动 kill,表现为“连着但发不了消息”:
- 在对应虚拟主机内加两行(缺一不可):
Timeout 3600ProxyTimeout 3600 - 不要全局改,只在 WebSocket 专用站点中覆盖
- 若后端本身也有空闲超时(如 Python websockets 的
ping_interval),建议设为略小于 Apache 的值(如 3500),避免后端先断
不复杂但容易忽略:WebSocket 代理成败不在后端代码,而在 Apache 是否真正“放手”让它走隧道。只要模块对、协议对、头对、超时对,90% 的“无响应”问题就解决了。











