Apache实现基于域名的WebSocket虚拟主机,本质是通过VirtualHost按域名区分请求,并在对应配置块中启用mod_proxy_wstunnel模块,使用ws://或wss://前缀代理、透传Upgrade/Connection头、设置长超时,从而建立WebSocket隧道。
apache 本身不直接处理 websocket 协议,所谓“基于域名的 websocket 虚拟主机”,本质是:用 <virtualhost> 按域名区分请求,再在对应虚拟主机内启用 mod_proxy_wstunnel 实现 websocket 隧道代理。关键不在 servername 本身,而在于它所属的 <virtualhost> 块里是否配对了模块、协议前缀、超时和头透传。
✅ 必须启用 mod_proxy_wstunnel 模块
这是唯一能识别 Upgrade: websocket 并建立隧道的模块。缺它,所有 WebSocket 握手都会被当作普通 HTTP 处理,后续帧全丢。
- Linux(Debian/Ubuntu):
sudo a2enmod proxy proxy_http proxy_wstunnel sudo systemctl restart apache2
- CentOS/RHEL 或源码安装:
确保
httpd.conf中这三行已取消注释:LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_http_module modules/mod_proxy_http.so LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
- 验证是否生效:
httpd -M | grep -E 'proxy|wstunnel' # 应看到 proxy_module, proxy_http_module, proxy_wstunnel_module (shared)
✅ 每个域名写独立 <VirtualHost>,ProxyPass 必须用 ws:// 或 wss://
不能复用 HTTP 代理规则(如 http://localhost:8080/),否则握手成功但后续帧无法透传。
例如,为 ws.example.com 和 chat.api.com 分别配置:
<VirtualHost *:80> ServerName ws.example.com ProxyPreserveHost On # WebSocket 专用路径 → 用 ws:// ProxyPass /ws/ ws://127.0.0.1:8080/ws/ ProxyPassReverse /ws/ ws://127.0.0.1:8080/ws/ # 其他普通 HTTP 请求 → 用 http://(可选) ProxyPass / http://127.0.0.1:8080/ ProxyPassReverse / http://127.0.0.1:8080/ </VirtualHost> <VirtualHost *:443> ServerName chat.api.com SSLEngine on SSLCertificateFile /path/to/cert.pem SSLCertificateKeyFile /path/to/key.pem ProxyPreserveHost On # WSS 必须用 wss:// 前缀(后端若没开 TLS,则仍用 ws:// + SSLProxyEngine) ProxyPass /socket/ wss://127.0.0.1:9000/socket/ ProxyPassReverse /socket/ wss://127.0.0.1:9000/socket/ </VirtualHost>
⚠️ 注意顺序:WebSocket 的 ProxyPass 规则要写在普通 http:// 规则之前,否则 /socket/ 可能被 / 规则提前截断。
✅ 强制透传 Upgrade 和 Connection 头
这两个是 hop-by-hop 头,默认会被 Apache 清洗,导致后端收不到升级请求,返回 400 或静默失败。
在对应 <VirtualHost> 内添加:
Apache Superset 是一个广泛采用的开源 BI 平台,用于 SQL 探索、图表构建和仪表板交付。当代理需要查询仓库数据、组装仪表板或使用成熟的分析界面解释指标而不是临时笔记本代码时,此技能非常有用。
RequestHeader set Connection "upgrade" RequestHeader set Upgrade "websocket"
如果启用了 mod_security,还需检查其规则是否拦截了 Upgrade 头(常见于 CRS 规则集),临时禁用或加白名单。
✅ 同步设置 Timeout 和 ProxyTimeout 为长值(如 3600)
WebSocket 是长连接,Apache 默认 60 秒超时会主动断开空闲连接,造成“掉线无提示”。
在 <VirtualHost> 内加上:
Timeout 3600 ProxyTimeout 3600
两个值必须一致且同时存在:
-
Timeout控制整个请求生命周期(含握手) -
ProxyTimeout控制代理 socket 级空闲等待时间
不建议全局修改,只在 WebSocket 专用站点中覆盖即可。
✅ 补充:HTTPS/WSS 场景下额外注意
- 若前端页面是
https://xxx.com,WebSocket 必须用wss://,否则浏览器因混合内容拦截拒绝连接。 - 后端服务若未启用 TLS(即只有
ws://),但你想对外提供wss://,需开启SSLProxyEngine on并信任后端证书(或加SSLProxyVerify none测试用):SSLProxyEngine on SSLProxyVerify none SSLProxyCheckPeerCN off SSLProxyCheckPeerName off SSLProxyCheckPeerExpire off
配置完成后重启 Apache,并用浏览器开发者工具 Network 标签页观察 WebSocket 连接是否返回 101 Switching Protocols。若仍失败,重点检查模块加载状态、ProxyPass 前缀、头透传和超时设置四项。

















