公众号旧文

TailMatrix:给自己做一张全互联延迟地图

作者:胖子阅读 —

服务器多了以后,“能连上”只是最基本的要求。我更想知道的是:这些机器之间到底连得怎么样?

从本地访问某台服务器很快,不代表它访问其他服务器也快。两台机器都加入了 Tailscale,也不代表它们之间始终能够直连。平时遇到问题,我通常会登录服务器,手动执行几次 tailscale ping,看看延迟和连接路径。

这种方式适合临时排查,但很难看清整个网络。

于是,我做了一个小项目:TailMatrix。它把 Tailscale 节点之间的定向延迟、直连与中继情况,整理成一张持续更新的矩阵,风格类似网络 Looking Glass。

TailMatrix 全互联延迟矩阵

目前,我接入了 12 台 Linux 节点。横纵轴都是 Tailscale 机器名,每个单元格对应一次“从行节点到列节点”的测量结果。12 台机器,共有 132 个有方向的节点对。

这里的“有方向”很重要:A → B 和 B → A 分别测量,不直接把一个方向的结果复制到另一个方向。两次探测的发起位置、测量时刻和连接状态可能不同,最终结果也可能不同。

单元格中的数字,是对应时间范围内成功样本的平均延迟,单位为毫秒。颜色帮助我快速找到低延迟连接和较慢的连接;对角线表示机器到自身,不进行远程探测。

除了延迟,TailMatrix 还会区分连接状态:

  • DIRECT:探测通过直连路径获得响应。
  • DERP:探测通过中继路径获得响应。
  • MIXED:当前统计范围内,既出现过直连,也出现过中继。
  • TIMEOUT:tailscale ping 明确报告探测超时。
  • SSH_ERROR:Controller 无法完成用于采集的 SSH 命令。

截图里不少格子是紫色的 MIXED。这并不表示这些连接一直在走中继,而是所选时间窗口内,两种路径都出现过。当前界面的规则是,只要统计范围内包含中继样本,就优先使用紫色提示。因此,紫色代表需要关注连接路径,并不直接等于高延迟或故障。

把这些状态分开,也能避免一种误判:Controller 登录不上某台服务器,不意味着那台服务器到目标节点的网络一定不通。采集链路故障和实际 ping 超时,需要分别记录。

实现上,我选择了一条比较简单的路线:中央控制器通过 SSH 采集,不在每台机器上部署 agent。

Controller 登录某个 Linux 节点,在远端执行:

tailscale ping --timeout=2s --c=1 <目标 Tailscale IP>

随后解析输出,提取延迟和路径类型,再将结果写入 SQLite。Controller 负责调度与汇总,真正的探测发生在 source 节点与 target 节点之间,测量值不是“经过 Controller 中转”的延迟。

为了避免一次偶然的结果影响判断,每个方向默认采样 3 次。例如:

108 ms
TIMEOUT
110 ms

这组数据的平均延迟为 109 ms,成功率为 66.7%,超时次数为 1。失败样本不会按零毫秒参与平均,也不会被悄悄忽略。

页面支持 Latest、1h、6h 和 24h。Latest 展示最近一轮完整扫描;其他窗口则从历史原始样本重新聚合。选择 24h,只表示查询最近 24 小时范围内已有的数据,并不代表程序已经积累了完整一天的记录。

鼠标悬停可以查看平均值、最小值、最大值、成功率和路径占比;点击单元格,则能打开这一方向最近 24 小时的历史趋势。这样既能看全局,也能继续追踪某一条连接。

技术栈也尽量保持轻量:

部分 实现
扫描与调度 Python asyncio
远程执行 系统 OpenSSH
数据存储 SQLite
Web API FastAPI
页面 HTML、CSS、Vanilla JavaScript
历史图表 本地 SVG

扫描采用受控并发,每条 SSH 命令都有独立的截止时间。某个节点失联,不会无限阻塞整轮扫描。数据按完整轮次提交,页面在新一轮结束前继续显示上一轮结果,避免出现一半新、一半旧的矩阵。

这个项目最初运行在 Windows 上,方便开发和验证。后来,我把后端迁移到了已有的日本 Linux 节点,由 systemd 管理,支持开机启动和故障自动重启。Windows 现在只需要打开网页,不必再承担持续采集。

迁移过程中,一个很实际的问题是超时设置。最初整条 SSH 命令的截止时间为 8 秒,出现了较多采集失败。复测发现,部分并发请求需要更长的握手和执行时间。于是,我把实际部署的 SSH 截止时间调整为 20 秒,同时针对服务器较小的内存,将并发数设为 4。

这里调整的是 SSH 命令的总时间预算,ping 本身仍使用独立的 2 秒超时。两者分开,才能更清楚地判断失败发生在哪一层。

安全方面,项目复用服务器现有的 SSH 配置,没有复制 Windows 私钥,也不保存 SSH 密码。目标节点来自配置文件,接口不接受任意远程命令;子进程使用参数化调用。网页目前只监听 Tailscale 内网地址,没有开放到公网。

TailMatrix 仍然是一个小工具。它测量的是 Tailscale 层的连接情况,不能直接替代应用层的 HTTP、数据库或实际业务性能测试。目前也还没有 Windows source 采集、p95、告警和历史数据清理策略。

但对我来说,这一版已经解决了最初的问题:不用再逐台登录、逐条手动测试,就能看到整个私有网络的连接状态。

接下来,我更想继续完善失败原因分类、历史保留和路径变化统计。先把这些基础数据记录准确,再考虑更复杂的功能。