Apache 反向代理下配置 WebSocket 完整教程
适用场景:后端为 Go 二进制(如监听
127.0.0.1:8091),前面使用 Apache(宝塔面板常见)做 HTTP/HTTPS 反向代理。
不装 Nginx 也可以,但 必须在 Apache 里单独处理 WebSocket 握手,否则会出现实时消息、售后聊天、通知推送连不上的问题。
一、先搞懂:为什么会出现这条报错?
后端日志里若看到类似:
WebSocket 升级失败: websocket: the client is not using the websocket protocol:
'upgrade' token not found in 'Connection' header
含义是:到达 Go 的请求是普通 HTTP GET,不是 WebSocket 握手。
常见原因分三类:
| 类型 | 说明 | 是否影响业务 |
|---|---|---|
| 误访问 | 浏览器地址栏直接打开 http://域名/api/ws/... |
一般可忽略 |
| 反代未配 WS | Apache 只写了 ProxyPass,未转发 Upgrade |
会导致聊天/通知失效 |
| 探活/扫描 | 监控工具用 HTTP 探测 WS 路径 | 可忽略 |
结论:你即使用二进制启动 Go、不装 Nginx,只要域名前面有 Apache 反代,就必须给 WebSocket 单独加规则。
二、架构示意
浏览器 --wss/https--> Apache (80/443) --ws/http--> Go 二进制 (127.0.0.1:8091)
普通页面 /API:ProxyPass http://
WebSocket:需 Upgrade 转发到 ws://
本项目中 WebSocket 入口示例:
- 售后/全局消息:
/api/ws/aftersale?token=你的JWT - 接单大厅:
/api/ws/lobby?token=你的JWT
前端在 HTTPS 页面下应连接:wss://你的域名/api/ws/aftersale?token=xxx
三、前置条件检查清单
在改配置前,请确认:
- Go 服务已监听
8091(或你自定义端口),本机可访问:curl http://127.0.0.1:8091/health - 防火墙/安全组 已放行对外 80、443(Apache);8091 通常只本机访问,不必对公网开放。
- 站点已配置反代 到
http://127.0.0.1:8091/(你当前的宝塔写法)。 - 若站点启用 HTTPS,必须同时改 443 的 VirtualHost,不能只改 80。
四、第一步:启用 Apache 模块(宝塔)
路径:软件商店 → Apache → 设置 → 模块 / 加载模块
请确保已启用:
proxyproxy_httpproxy_wstunnel(WebSocket 关键模块)rewrite
保存后 重载配置 或 重启 Apache。
若没有
proxy_wstunnel,RewriteRule ... ws://... [P]无法生效,WebSocket 一定失败。
五、第二步:修改站点 Apache 配置(核心)
5.1 找到配置位置
宝塔:网站 → 你的站点 → 设置 → 配置文件(Apache)。
找到类似段落:
# HTTP反向代理相关配置开始 >>>
...
# HTTP反向代理相关配置结束 <<<
5.2 推荐完整写法(80 端口示例)
将中间反代段 整体替换 为:
# HTTP反向代理相关配置开始 >>>
<IfModule mod_proxy.c>
ProxyRequests Off
SSLProxyEngine on
ProxyPreserveHost On
# ---------- WebSocket 升级转发(必须) ----------
RewriteEngine On
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteCond %{HTTP:Connection} upgrade [NC]
RewriteRule ^/(.*) ws://127.0.0.1:8091/$1 [P,L]
# ---------- 普通 HTTP 请求 ----------
ProxyPass / http://127.0.0.1:8091/
ProxyPassReverse / http://127.0.0.1:8091/
</IfModule>
# HTTP反向代理相关配置结束 <<<
说明:
8091改成你 Go 程序实际监听端口。RewriteRule必须在ProxyPass之前生效:带Upgrade: websocket的请求走ws://,其余走普通 HTTP。[P,L]表示通过代理模块处理并停止后续规则。
5.3 你原来的配置缺了什么?
仅下面两行时,页面和 API 正常,WebSocket 会失败:
ProxyPass / http://127.0.0.1:8091/
ProxyPassReverse / http://127.0.0.1:8091/
因为 Apache 默认不会把 WebSocket 握手头转发成后端所需的 Connection: Upgrade。
六、HTTPS(443)站点也要同样配置
若用户访问 https://pp.example.com,浏览器 WebSocket 使用 wss,走的是 443 的 VirtualHost。
请务必在 SSL 站点 的配置里加入 与 80 相同 的 RewriteEngine + ProxyPass 段。
只改 80、不改 443 的典型现象:
- 网站能打开(https)
- 接口大部分正常
- 实时消息、未读气泡、聊天一直连不上
七、验证是否配置成功
7.1 浏览器开发者工具
- 登录你的前台/后台页面。
- 按
F12→ 网络 (Network) → 筛选 WS。 - 找到类似:
/api/ws/aftersale?token=... - 正常状态应为:101 Switching Protocols(已建立 WebSocket)。
若显示失败、一直 pending、或很快断开,优先检查 Apache 模块与 443 配置。
7.2 看 Go 日志
配置正确后:
- 不应再频繁刷
upgrade token not found(偶发误访问可忽略)。 - 连接成功会有业务侧日志(视项目而定)。
7.3 本机直连对比(排查用)
在服务器上:
curl http://127.0.0.1:8091/health
若本机正常、域名不正常,问题在 Apache 反代层,不是 Go 程序本身。
八、与「不装 Nginx、二进制启动」的关系
| 说法 | 是否正确 |
|---|---|
| Go 二进制直接跑,可以不装 Nginx | 对 |
| 前面没有反代,浏览器直连 IP:8091 | 一般不需要 Apache 配置 |
| 域名走宝塔 Apache 反代到 8091 | 必须配 WebSocket,与是否 Nginx 无关 |
你当前属于第三种:Apache 反代 + Go 二进制,按本文配置即可,无需再装 Nginx。
九、前端连接注意事项(开发参考)
- 协议跟随页面:HTTPS 页面必须用
wss://,HTTP 用ws://。 - Token 建议 URL 编码:
token=${encodeURIComponent(jwt)},避免特殊字符截断。 - 路径与后端一致:例如
/api/ws/aftersale。
示例:
const wsUrl = `wss://${location.host}/api/ws/aftersale?token=${encodeURIComponent(token)}`
const ws = new WebSocket(wsUrl)
十、常见问题 FAQ
Q1:配了 Rewrite 仍连不上?
- 确认
proxy_wstunnel已启用并重载 Apache。 - 确认改的是 用户实际访问的端口(https 改 443)。
- 确认 Go 监听地址是
127.0.0.1:8091与配置一致。
Q2:只有 WebSocket 报错,网站正常?
说明 HTTP 反代 OK,仅缺 WS 规则,按第五节补 RewriteEngine 即可。
Q3:可以用宝塔「反向代理」界面吗?
可以填目标 URL http://127.0.0.1:8091,有 WebSocket 开关请打开;但 Apache 环境下仍建议在 配置文件 中保留 RewriteRule,最稳妥。
Q4:需要给 8091 开端口给外网吗?
通常 不需要。外网只访问 80/443,由 Apache 转发到本机 8091。
Q5:和 Nginx 的配置等价吗?
思路相同:都要转发 Upgrade 和 Connection。Nginx 写法是 proxy_set_header Upgrade $http_upgrade; 等;Apache 用本文 RewriteRule + proxy_wstunnel。
十一、配置模板速查
仅本机 Go、无反代: ws://服务器IP:8091/api/ws/aftersale?token=xxx
域名 + Apache + HTTPS: wss://你的域名/api/ws/aftersale?token=xxx
Apache 反代核心三行逻辑:
RewriteEngine On- 检测
Upgrade=websocket→ 转发到ws://127.0.0.1:端口 - 其余请求
ProxyPass到http://127.0.0.1:端口
十二、小结
- 不装 Nginx、二进制跑 Go 完全可行。
- 只要 Apache(宝塔)反代 到你的 Go 端口,就必须配置 WebSocket 升级转发。
- 核心是启用
proxy_wstunnel,并添加RewriteRule ... ws://... [P,L]。 - HTTPS 站点(443) 与 HTTP(80)要同步修改。
- 用浏览器 WS 面板看到 101 即表示成功。
按本文操作后,实时聊天、消息推送、接单大厅等依赖 WebSocket 的功能即可与 API 一样稳定对外服务。
本文由小氢云相关部署实践整理,如有环境差异(OpenLiteSpeed、CDN 等)可在评论补充。