Table of Contents

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
  1. 简单测试看着 TTFB 低了就留下了,埋下了祸根。
  2. 高估了小破电脑的处理能力。
  3. 没事别乱捣鼓配置,调了之后要有完整测试。

0