在 apache 中配置 mod_proxy_wstunnel 实现 websocket 代理,核心步骤是启用 proxy、proxy_http 和 proxy_wstunnel 模块,并在 virtualhost 或 directory 中使用 proxypass 和 proxypassreverse 指令将请求转发到后端。必须配合 rewriterule 使用 mod_rewrite 来升级连接协议,确保 websocket 握手成功。

如何启用必要的 Apache 模块
要使用 mod_proxy_wstunnel,首先需要确保 Apache 已加载相关模块。在 Debian/Ubuntu 系统中,通常使用 a2enmod 命令;在 CentOS/RHEL 系统中,则需要在 httpd.conf 或 conf.d/ 目录下取消注释 LoadModule 行。主要需要启用的模块包括 proxy(基础代理功能)、proxy_http(HTTP 代理支持)以及 proxy_wstunnel(WebSocket 隧道支持)。

# Debian/Ubuntu sudo a2enmod proxy sudo a2enmod proxy_http sudo a2enmod proxy_wstunnel sudo a2enmod rewrite # 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 LoadModule rewrite_module modules/mod_rewrite.so
启用模块后,重启 Apache 服务使配置生效。验证模块是否加载可以通过执行 apachectl -M 查看输出列表中包含上述模块名。
如何在 VirtualHost 中配置代理规则
在 VirtualHost 配置块中,需要定义两个关键部分:一是处理 HTTP 请求的普通代理,二是处理 WebSocket 连接的升级请求。对于 WebSocket,Apache 需要识别 Upgrade 和 Connection 头部,并将其传递给后端服务器。这通常通过 ProxyPass 指令指定 ws:// 或 wss:// 前缀来实现,同时结合 RewriteRule 来处理连接升级逻辑。

<virtualhost>
ServerName websocket.example.com
# 启用重写引擎
RewriteEngine On
# 如果请求不是 WebSocket 升级请求,则按普通 HTTP 代理处理
RewriteCond %{REQUEST_URI} ^/ws [NC]
RewriteCond %{QUERY_STRING} transport=websocket [NC]
RewriteRule .* ws://localhost:8080%{REQUEST_URI} [P,L]
# 或者更通用的方式,直接匹配 Upgrade 头
# RewriteRule ^/ws$ ws://localhost:8080/ws [P,L]
# 普通 HTTP 代理
ProxyPass / http://localhost:8080/
ProxyPassReverse / http://localhost:8080/
</virtualhost>
上述配置中,ProxyPass 将根路径映射到本地 8080 端口的 HTTP 服务,而针对 /ws 路径的请求,如果符合 WebSocket 条件,则被转发到后端的 WebSocket 服务。注意 [P] 标志表示代理,[L] 表示最后一条规则。实际部署时,建议根据前端发送的具体路径调整 ReWriteRule 的正则表达式。
当后端返回非 101 状态码时代理行为是什么
当客户端发起 WebSocket 连接请求时,Apache 会尝试与后端建立隧道。如果后端服务器没有正确响应 101 Switching Protocols 状态码,而是返回其他 HTTP 状态码(如 404 Not Found 或 500 Internal Server Error),mod_proxy_wstunnel 的行为取决于具体的 Apache 版本和配置。通常情况下,如果后端返回非 101 状态,Apache 会将该错误响应直接返回给客户端,导致 WebSocket 连接失败。此时,客户端通常会收到一个 HTTP 错误,而不是 WebSocket 断开连接的通知。为了调试此问题,可以检查后端日志确认其是否正确处理了 Upgrade 请求,并确保 Apache 配置中的路径和后端口号准确无误。











