frp 隧道超时卡死排障
前言
环境:本站架构是在家宽 NAS 上跑 Nginx,使用 fatedier/frp 自建 frp 隧道暴露到云服务器,前面套 SCDN。日独立访客 120~400,单页 ~49 KB。
现象:站点长期运行会自己挂掉,访客访问站点返回源服务器超时错误。
初步排障:排除了用户浏览器到 SCDN 边缘节点,SCDN 边缘节点到 frps 服务器,frpc 到 Nginx,Nginx 到 Halo CMS 服务器。只剩下 frps 到 frpc 这一段可能出问题。
重启 frpc 后用简易脚本压测复现了这个奇怪的现象:frps 运行正常,frpc 也显示在线,但就是不干活。
怪状
用 20 并发压测 15 秒,以下是测试结果:
| 轮次 | 成功 / 失败 | 压测后 ESTAB |
|---|---|---|
| 1 | 44 / 10 | 72 |
| 2 | 53 / 20 | 71 |
| 3 | 42 / 18 | 71 |
每轮出现的失败均为 ECONNRESET。压测结束后,站点直接 504 error。
我随即进行了以下检查:
- frps 日志显示还在正常接受连接。
- 面板里 frpc 状态
online,frp proxy 也online。 - 绕过 CDN 直连 frps 做 TLS 握手,拿不到 ServerHello,
curl也一直超时。 - 每轮测试后重启 frpc,立刻恢复正常。
排障
压测结束之后使用以下命令检查连接数:
ss -tn | grep ':7000' | awk '{print $1}' | sort | uniq -c
输出 71 条 ESTAB,同时面板显示 curConns = 0。
用户连接已经结束了,但 frps 与 frpc 之间的 work connection 留着不断。
注意到配置文件:
# frps.toml
transport.tcpMux = false
transport.maxPoolCount = 10000
关闭多路复用时,每个用户连接都要在 frps 与 frpc 之间单独占一条 TCP。
压测脚本 20 并发就是同时占 20 条,结束后连接没回收,frpc 随后卡住,新连接拿不到响应,产生了之前的现象。
与此同时之前将连接数上限设置到 10000😕 ,因此同时能有这么多连接数。
猜测可能是超过了主机的处理能力,也可能是家宽限制,导致无法同时维持更多的连接。
验证
开启多路复用,让所有流共用一条连接。
# frps.toml
# transport.tcpMux 在 frps.toml 与 frpc.toml 两侧必须一致,否则无法正常连接
# 用默认配置即可,无需额外配置
# transport.tcpMux = true
# transport.maxPoolCount = 10
同样脚本再压测:
| 配置 | 成功 / 失败 | 压测后连接 |
|---|---|---|
tcpMux = false |
44/10、53/20、42/18 | 71~72 |
tcpMux = true |
53/0、55/0 | 1 |
效果:
- 中位延迟高约 1 秒(队头阻塞)
- 失败率 30% → 0%
- 连接数 71 → 1
结论
改回默认配置:
transport.tcpMux = true
- 简单测试看着 TTFB 低了就留下了,埋下了祸根。
- 高估了小破电脑的处理能力。
- 没事别乱捣鼓配置,调了之后要有完整测试。
0