用 EdgeOne WSS 加速 FRP:双通道反向代理部署实录

用 EdgeOne WSS 加速 FRP:双通道反向代理部署实录
家里的服务器没有公网入口,业务统一由香港节点上的 Nginx 对外提供 HTTPS,再通过内网穿透访问本地服务。原来的公网直连 FRP 能用,但跨境路径延迟和抖动较大。为了改善这一段链路,我把 FRP 的主连接改为原生 WSS,让它通过腾讯云 EdgeOne 中转,同时保留原来的直连 FRP 作为自动备用线路。
最终结构不是“让 CDN 直接反代每个本地应用”,而是让 CDN 承载 FRP 客户端到服务端之间的 WSS 隧道。用户访问的业务域名仍然由香港 Nginx 统一接入和分流。

改造目标
这次改造需要同时满足四点:
- 本地服务器仍然不开放公网端口;
- FRP 跨境链路尽量经过 EdgeOne 的优化网络;
- EdgeOne 或 WSS 短暂断线时,公网服务不能随之中断;
- Halo、面板、监控、Agent 等现有服务统一使用同一套主备逻辑。
仅把普通 FRP TCP 端口放到 CDN 后面通常不可行,因为常规 CDN 主要处理 HTTP、HTTPS 和 WebSocket。FRP 0.71.0 原生支持 wss 传输,因此可以把控制连接和数据连接封装成 WebSocket Secure,再通过 EdgeOne 的 443 入口到达香港节点。
两条并行隧道
生产环境同时运行两套 FRP。
WSS 主通道
本地 frpc-wss
-> wss://ws.example.com:443
-> 腾讯云 EdgeOne
-> 香港 Nginx WebSocket 入口
-> 回环 frps-wss:7100
-> 香港回环业务端口 18190-18198
FRP 客户端的核心配置思路如下,域名和认证信息使用占位符:
serverAddr = "ws.example.com"
serverPort = 443
transport.protocol = "wss"
transport.tls.enable = true
transport.tls.serverName = "ws.example.com"
auth.method = "token"
auth.token = "<FRP_TOKEN>"
EdgeOne 在公网侧终止 TLS,并通过 HTTP/1.1 WebSocket 回源到香港 Nginx。Nginx 再把升级后的连接转发给仅监听回环地址的 frps-wss。这样 FRPS 不需要直接暴露第二个公网控制端口。
直连备用通道
本地 frpc-direct
-> 香港公网 FRPS:7000
-> 香港回环业务端口 18090-18098
这条线路不经过 EdgeOne,延迟较高,但路径简单、故障域不同。它不是临时测试线路,而是长期保留的生产备用通道。
端口规划
两套 FRP 映射同一批本地服务,香港侧使用不同的回环端口:
| 本地服务端口 | 直连备用 | WSS 主通道 | 用途 |
| 8090 | 18090 | 18190 | Halo |
| 5463 | 18091 | 18191 | 管理面板 |
| 6185 | 18092 | 18192 | AstrBot |
| 25774 | 18093 | 18193 | Komari |
| 8060 | 18094 | 18194 | Certimate |
| 5244 | 18095 | 18195 | OpenList |
| 80 | 18096 | 18196 | 网站 |
| 56789 | 18097 | 18197 | 温度接口 |
| 9119 | 18098 | 18198 | Agent |
这些端口都只在香港回环地址监听,不直接向公网开放。公网入口仍由 Nginx 按域名提供。
Nginx 自动回退
香港 Nginx 为每个业务配置两个上游:WSS 端口为主,直连端口标记为 backup。
upstream app_backend {
server 127.0.0.1:18190 max_fails=1 fail_timeout=5s;
server 127.0.0.1:18090 backup;
}
location / {
proxy_pass http://app_backend;
proxy_connect_timeout 2s;
proxy_read_timeout 60s;
proxy_next_upstream error timeout invalid_header http_502 http_503 http_504;
proxy_next_upstream_tries 2;
}
回退只在连接失败、超时、响应头无效或出现 502/503/504 时触发。业务正常返回的 302、401 等状态不会导致误切换。
这层设计很重要。实测 EdgeOne 会周期性断开 WebSocket,FRPC 通常能很快重连,但偶尔会经历数秒恢复窗口。没有备用通道时,这个窗口会直接表现为公网 502;有 Nginx 主备后,请求会自动改走直连 FRP。
部署顺序
为了避免一次切换影响全部服务,部署按以下顺序推进:
- 在香港启动独立的 `frps-wss`,仅监听回环地址;
- 为 WSS 域名增加 Nginx WebSocket 入口,并让 EdgeOne 回源该入口;
- 本地启动独立的 `frpc-wss`,先只映射温度接口;
- 连续验证真实 HTTP 数据,而不只看 FRPC 是否显示登录成功;
- 扩展到全部本地服务,对比两条线路的状态码和响应大小;
- 将 Nginx 上游切换为 WSS 主、直连备用;
- 把两套 FRP 都纳入 systemd,并配置自动重启;
- 主动停止 WSS 客户端,验证公网请求能否经备用线路继续完成。
这里最容易忽略的一点是:控制连接成功不等于业务数据面成功。测试必须请求真实接口,并核对状态码、响应大小和耗时。
实测结果
温度接口通过 WSS 连续请求 30 次,结果为 30/30 成功,响应内容保持一致:
WSS 最低:0.246 秒
WSS 平均:0.304 秒
WSS 最高:0.571 秒
同一接口在直连 FRP 路径上的观测耗时约为:
直连 FRP:3.52-7.21 秒
EdgeOne WSS:0.09-0.57 秒(不同批次)
Agent 服务也进行了双路径对比:WSS 路径约 0.063 秒,直连路径约 1.23 秒。不同时间段的绝对值会变化,但在当前网络环境下,WSS 路径的改善很明显。

这些数据只代表本次网络、地区和运营商条件,不能简单外推到其他环境。EdgeOne 的实际路由也会动态变化,因此生产设计不能只追求一次测速结果,还要考虑线路失效时如何恢复。
2026-09-09 复测:20 轮交替请求
为了排除先测某条线路带来的顺序偏差,这次从香港中转机交替请求直连 FRP 与 EdgeOne WSS 两个端口。每条通道测试 20 轮,每次关闭缓存并读取完整约 180 KB 的温度接口响应体。
| 指标 | FRP 直连备用 | EdgeOne WSS 主通道 |
|---|---|---|
| 成功率 | 20/20 | 20/20 |
| 平均耗时 | 4.9365 秒 | 0.2378 秒 |
| 中位数 | 4.1763 秒 | 0.2560 秒 |
| P95 | 9.1181 秒 | 0.3462 秒 |
| 最低值 | 2.1323 秒 | 0.0967 秒 |
| 最高值 | 11.1451 秒 | 0.4267 秒 |

本轮两条线路均为 20/20 成功。WSS 的平均响应耗时约为直连 FRP 的 1/20.76,平均延迟降低 95.18%。共享纵轴用于呈现两条线路的数量级差异,图中数据均为原始观测值,没有进行平滑处理。
这组结果仍然只代表测试当时的网络条件,不构成固定性能保证。直连线路虽然慢,但故障域与 EdgeOne WSS 不同,继续保留它作为自动备用仍有必要。
补充测试:丢包、TCP 重传与最终失败率
仅有 20/20 请求成功不能说明网络层没有丢包。FRP 直连和 WSS 都使用 TCP,底层丢包通常会被 TCP 重传修复,因此这里分别测量三种不同口径:
- 本地服务器到入口节点的 ICMP 路径基线;
- 受控传输窗口内,FRPC 主数据连接新增 TCP 重传字节占比;
- 两条隧道各 50 次完整约 180 KB HTTP 响应的最终失败率。
| 指标 | FRP 直连 / 香港公网 | EdgeOne WSS / EdgeOne 节点 |
|---|---|---|
| ICMP 包数 | 100 | 100 |
| ICMP 丢包率 | 7% | 3% |
| 平均 RTT | 268.8 ms | 63.1 ms |
| TCP 重传字节占比 | 3.5843% | 0.1186% |
| 完整 HTTP 请求 | 50/50 | 50/50 |
| 应用最终失败率 | 0% | 0% |
| 50 轮平均耗时 | 6.3904 秒 | 0.2528 秒 |
| 50 轮 P95 | 9.6144 秒 | 0.4779 秒 |

本轮直连路径的 TCP 重传字节占比约为 WSS 的 30.23 倍。两条 TCP 隧道最终都能完整交付请求,但直连路径较高的丢包与重传会被转化为明显的等待时间和抖动。
需要注意,ICMP 丢包率、TCP 重传占比和应用失败率不是同一个指标:ICMP 只描述到入口节点的路径基线;TCP 重传反映可靠传输为修复丢包或乱序付出的代价;应用失败率则表示在超时限制内是否拿到了完整响应。
故障演练
部署完成后,我主动停止了本地 frpc-wss。香港侧 WSS 映射端口随控制连接断开而消失,Nginx 随即尝试直连 FRP 备用端口。所有业务域名仍返回预期状态,随后恢复 frpc-wss,主端口重新注册并继续承载请求。
这次演练验证了三个层面:
- WSS 线路确实是当前主通道;
- 直连 FRP 不是纸面配置,而是可用的数据通道;
- Nginx 的失败判定和重试条件能够覆盖 WSS 断线窗口。
这套方案解决了什么
EdgeOne 改善的是本地到香港之间的 FRP WSS 长连接路径,不是绕过香港 Nginx,也不是让每个本地应用单独接入 CDN。香港 Nginx 仍然负责证书、域名分流、上游选择和故障回退。
最终请求逻辑可以概括为:
用户 -> 香港 Nginx
|-> WSS FRP 主通道 -> 本地服务
`-> 直连 FRP 备用 -> 本地服务
主通道提供更低延迟,备用通道覆盖 EdgeOne 周期断连和重连失败窗口。两条线路使用不同入口和不同 FRPS 实例,避免单一链路故障拖垮全部公网服务。
安全与运维注意事项
- FRP Token、MCP 密钥、对象存储密钥和 SSH 凭据都不应写入文章或公开配置;
- FRPS 的业务映射端口只监听回环地址,由 Nginx 统一暴露;
- WSS FRPS 与直连 FRPS 使用独立服务和配置文件;
- systemd 配置 `Restart=always`,同时监控重连日志和端口注册状态;
- 发布配置前先执行 `nginx -t`,成功后再 reload;
- 定期进行真实故障演练,而不是只确认服务显示 `active`。
这次改造的关键并不是单纯“套一层 CDN”,而是把链路优化和故障回退同时纳入设计。WSS 负责速度,直连 FRP 负责兜底,Nginx 负责在两者之间自动选择。
