apache代理websocket必须启用mod_proxy_wstunnel模块,proxypass须用ws://或wss://前缀,同步设置timeout和proxytimeout为3600,并透传upgrade/connection头,否则握手后帧将被丢弃导致1006错误。
apache 启用 mod_proxy_wstunnel 是代理 websocket 的前提,不是可选项——缺它就无法识别 upgrade: websocket 请求,所有握手后的帧都会被丢弃或静默中断,典型表现是连接建立后立刻报 1006 错误。
确认并启用模块
该模块依赖 mod_proxy 和 mod_proxy_http,三者必须同时启用:
- Linux(Debian/Ubuntu):运行
sudo a2enmod proxy proxy_http proxy_wstunnel,再执行sudo systemctl restart apache2 - Linux(CentOS/RHEL):检查
/etc/httpd/conf.modules.d/下是否有proxy_wstunnel.load,或在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 - Windows(XAMPP):编辑
XAMPP\apache\conf\httpd.conf,确保上述三行未被注释 - 验证是否加载成功:
httpd -M | grep -E "(proxy|wstunnel)"(Linux/macOS)或httpd -M | findstr wstunnel(Windows),输出中应含proxy_wstunnel_module (shared)
配置 ProxyPass 必须用 ws:// 或 wss:// 前缀
这是触发隧道逻辑的唯一开关。写成 http:// 看似能通,实则走普通 HTTP 代理流程,WebSocket 握手虽可能返回 101,但后续帧传输必然失败。
FastAPI + Flask 混合部署最佳实践,解决路由定义、API 代理等常见问题,适用于同时运行 FastAPI API 与 Flask 前端的场景。
- 正确示例:
ProxyPass "/ws" "ws://localhost:8080/" - 错误示例:
ProxyPass "/ws" "http://localhost:8080/ws"(即使后端路径含 /ws,协议前缀错就全错) - 路径末尾斜杠需严格匹配,建议前后都带
/,避免重写歧义
同步设置超时与透传关键请求头
WebSocket 是长连接,Apache 默认超时(如 60 秒)会主动断开空闲连接。还需确保 Upgrade 流程不被拦截:
- 在虚拟主机或全局配置中添加:
Timeout 3600ProxyTimeout 3600 - 强制透传两个关键头(尤其当 Apache 前还有 CDN 或负载均衡时):
RequestHeader set Connection "upgrade"RequestHeader set Upgrade "websocket" - 禁用缓存干扰:
ProxyRequests Off、CacheDisable *(若启用了缓存模块)
调试与验证要点
配置生效后,需验证握手和帧传输是否真正穿透:
- 开启代理日志:
LogLevel info proxy:trace5(临时使用,生产环境调为warn) - 用浏览器开发者工具查看 WebSocket 连接,确认状态码为 101,且后续帧收发正常
- 后端服务(如 Spring Boot 或 Tomcat)无需改代码,只要它本身支持 WebSocket 即可;Apache 只负责“隧道化”转发
- 若仍失败,优先检查模块是否真加载、
ProxyPass协议前缀是否为ws://或wss://、超时值是否一致










