apache代理node.js websocket长连接的核心是原样透传upgrade握手和二进制帧:必须启用mod_proxy_wstunnel模块,proxypass使用ws://或wss://前缀,路径末尾斜杠严格一致,同步设置timeout和proxytimeout为3600,并强制透传upgrade/connection头。

Apache 代理 Node.js 的 WebSocket 长连接,核心不是“转换协议”,而是**原样透传 Upgrade 握手和后续二进制帧**。Node.js(如用 ws 库)本身已实现标准 WebSocket 服务,Apache 只需当好“隧道中转站”——模块要对、协议前缀要准、超时要够长、头要不丢。
必须启用 mod_proxy_wstunnel 模块
这是唯一能识别 Upgrade: websocket 并建立隧道的模块。仅靠 mod_proxy_http 会把 WebSocket 当普通 HTTP 处理,握手成功但后续帧全被截断或静默丢弃。
- 检查是否加载:
httpd -M | grep proxy_wstunnel,应看到proxy_wstunnel_module (shared) - 若未启用,在
httpd.conf或mods-enabled中确认这三行已取消注释:LoadModule proxy_module modules/mod_proxy.soLoadModule proxy_http_module modules/mod_proxy_http.soLoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so - Debian/Ubuntu 用户可直接运行:
sudo a2enmod proxy proxy_http proxy_wstunnel
ProxyPass 必须用 ws:// 或 wss:// 前缀
写成 http:// 是最常见错误——Apache 会走 HTTP 代理流程,无法透传 WebSocket 帧流,导致连接几秒后无声断开。
使用 JSON Schema 验证 JSON 数据,从示例 JSON 生成 schema,并将其转换为 TypeScript 接口、Python 数据类或 Markdown 文档。
- 明文 WebSocket(前端为
ws://):ProxyPass /ws/ ws://127.0.0.1:8080/ws/ProxyPassReverse /ws/ ws://127.0.0.1:8080/ws/ - 加密 WebSocket(前端为
wss://):
Apache 必须配置 SSL 证书(HTTPS 终止在 Apache),目标地址写wss://:ProxyPass /ws/ wss://127.0.0.1:8080/ws/ - 路径末尾斜杠必须严格一致:前后都带
/,否则Sec-WebSocket-Location头重写错误,现代浏览器直接拒绝连接
同步调大 Timeout 和 ProxyTimeout 到 3600
默认 60 秒超时会让空闲 WebSocket 连接被 Apache 主动关闭,后端无感知,客户端只看到“连接已关闭”。这不是 Node.js 的问题,是 Apache 自己断的。
- 在对应
<virtualhost></virtualhost>块中添加:Timeout 3600ProxyTimeout 3600 - 两个值必须同时设且相等:前者控制请求生命周期,后者控制代理 socket 级空闲超时
- 不建议全局修改,只在承载 WebSocket 的站点中覆盖
强制透传 Upgrade 和 Connection 头
这两个是 hop-by-hop 头,Apache 默认可能清洗或忽略,导致浏览器收不到 101 Switching Protocols 响应。
- 在
ProxyPass所在的<location></location>或<virtualhost></virtualhost>中添加:RequestHeader set Connection "upgrade"RequestHeader set Upgrade "websocket" - 禁用可能干扰的模块(如
mod_security对Upgrade头的拦截) - 避免在
<location></location>块中加冗余指令,如ProxyRequests Off已默认启用










