11 KiB
里程碑
每个里程碑都以“可运行、可验证”作为完成标准;可执行程序在各自的目标 RID 上(见 project-layout.md 第 9 节,Probe 包括 linux-musl-x64 和 linux-musl-arm64)的 NativeAOT 发布必须通过,并且零 AOT/trim 警告。
M0 骨架
- 按 project-layout.md 建立仓库:
backend/下的 props、.editorconfig、BannedSymbols.txt与BannedSymbols.Node.txt、backend/fleet/骨架、三个.slnx、两个 Monitor 共享库、Backend 的六个项目。 - CI:Windows/Linux 矩阵、路径过滤、
dotnet format --verify-no-changes、scripts/check-deps、scripts/check-openapi、AOT 发布,并记录体积和内存基线。
验收:
- 三个空程序以 AOT 方式发布并启动;
- 在 Agent 中调用
Process.Start时构建失败; - 空的 Probe 能在 OpenWrt aarch64 真机或 QEMU 上启动,并完成一次 TLS 握手(验证 musl 与
libopenssl3); - 给出
linux-musl-arm(armv7)工具链的验证结论。
F1 Fleet 核心(与 M1 并行)
Fleet.Core、Fleet.Identity、Fleet.Rpc、Fleet.Link(连接服务端、点对点会话、发件箱、期望状态同步)、Fleet.Hosting、Fleet.Enrollment.Client、fleet-enroll、Fleet.Server.Enrollment、Fleet.Server.Link、Fleet.Server.Sqlite。samples/EchoNode与EchoServer:用不依赖 Monitor 的方式跑通注册 → 认证 → 状态同步 → 发件箱上报 → 断线重连。
验收:
scripts/check-deps证明backend/fleet/**不引用Monitor.*;- EchoNode 在 Backend 重启、网络中断 10 分钟后能恢复,上报的消息不重复也不丢失(队列未满时);
- 伪造签名、重放 nonce、调用本地未允许的方法,全部被拒绝。
M1 声明与积木(本机回环)
Protocol:ParamSpec、KindSpec、自描述 RawChunk 编解码(附黄金字节测试)、JSON-RPC 信封。Measurement:Transport(udp/tcp/tls)、Pacer(fixed/ladder)、Payload、Behavior(echo/sink/source/connect/hold)、Sampler(tcp_info),以及 Recorder、KindAssembler、BudgetGuard。tools/monitor-bench:用两个本地进程运行任意 Kind,导出 RawChunk,用来调试引擎。- 测试:通过丢包注入中继验证逐包记录的完整性;100 Mbps 下发送节奏误差 < 1%;只加一条 Kind 声明、不写代码,就能运行一种新的组合。
M2 Probe ↔ 多个 Agent
- Probe 与 Agent 之间的签名认证、会话、MAC、重放窗口、限速、源地址漫游;
TaskReconciler;列的交付与合并;每 10 秒切块。 - Probe 同时与多个 Agent 维持会话(先用静态列表)。
- 开发模式:Agent 把 RawChunk 写入本地目录(正式运行时不落盘)。
验收:一个家宽 Probe 同时连接 3 台以上 VPS,连续运行 24 小时;原始块完整,内存稳定;宽带重拨后能自动恢复。
M3 Backend:注册、RPC、存储
- 在 Fleet 之上接入:
IFleetStore实现、TaskSet状态提供者(有效任务集的计算与下发)、RawChunk收件箱、monitor.*方法、monitor.probe.agents同步。 - 段文件与索引、发件箱 ACK、去重、缺口;管理员账号、Cookie 会话、API 令牌;
/api/admin中的节点、令牌、Probe 身份、任务管理。
验收:用一行安装命令部署一台新 VPS,自动注册 → 自动生成线路任务 → Probe 自动连接 → 1 分钟内在 /api/admin 中看到它的原始块。整个过程不需要手工配置。
M4 分析层与实时
- 累加器、算子、首批
MetricDef、base/mc/hy2/reality模型 v1;流式路径与持久路径;降采样;指标指纹与回填。 - 查询(query.md):
RangeResolver、SourcePlanner、1s 热层(1 小时)、metric_10s、现场合并、精确汇总;/overview?range=、/series、/compare、/distribution、/heatmap、/catalog/*(包括 presets);SSE 的series和overview主题;按需测试与测试结果。 - 查询验收:近 5 分钟 1s 步长和近 15 分钟 2s 步长的响应时间 < 50 ms;7 天 15 分钟步长的响应时间 < 200 ms;同一时间段内,汇总值与“从原始块直接计算”的结果一致(直方图分位数误差 ≤ 4.5%)。
验收:
- 扩展性:新增一个指标只需一行
MetricDef,重启后通过 API 可以看到它,并且 30 天历史已经回填; - 校准:在两条线路上实际部署 Hysteria2 和 REALITY 服务并实测,与推算结果对比,把偏差记录进
docs/calibration.md。
M5 规模与保留
- 用模拟数据验证 15 个 Agent 运行 30 天的情况:存储量、查询延迟(30 天跨度 < 500 ms)、回填耗时、SSE 在 100 个连接下的表现。
- 保留清理、磁盘占用指标、目标任务(
icmp_echo、connect)与allowed_target_cidrs。
F2 Fleet 更新(在 M6 之前)
Fleet.Update、fleet-updater(systemd 与 Windows 服务适配器、健康信标、回滚、防回滚)、fleet-release(CI 签名)、Fleet.Server.Releases(通道、灰度、版本汇总)。
验收:
- 用 EchoNode 和 monitor-agent 两个应用验证“同一个 updater 管理多个产品”;
- 验签失败、sha256 不符、新版本健康检查超时,这三种情况都能正确拒绝或回滚;
- 面板被替换为恶意面板时,节点不会安装未签名的版本。
M6 加固与部署
- OpenWrt 打包:procd 脚本、ipk/apk 包、sysupgrade 保留列表、
libopenssl3依赖检查;在 aarch64 路由器上跑满 24 小时,并运行一次hy2_ladder(观察 CPU 饱和标记)。 - 安装脚本的下载和验签(现在的
install.sh从解压好的发布目录安装)、install.ps1和 Windows 服务、fleet-updater的配置。 - 安全:对 UDP 包、控制帧、RawChunk、JSON-RPC 做模糊测试;伪造签名和重放测试;检查登录限流和 CSRF。
以后
- 告警(Webhook);真实 QUIC 握手积木(依赖 msquic,需要单独评估);pcap/eBPF 采集。
实现状态(后端与 Agent)
已实现并有自动化测试(287 个,另有 2 个跳过的测试,其中 1 个需要运行中 NativeAOT 产物):
-
多 Probe:Probe 身份由 Backend 生成(创建、轮换密钥、吊销、删除),一条线路是一对(Probe,Agent),Agent 为每个 Probe 会话各起一组流,数据按
line:<probe_id>隔离;Agent 上报连着的 Probe(id、版本、远端地址、时间),管理端可以断开某个 Probe;吊销立即生效。 -
tcp_bulk原语:批量传输(fwd / rev、本地码率上限、两端的 tcp_info),评分用持续 1 秒的吞吐峰值。 -
Agent 主机状态:只上报汇总数字(没有型号和 IP),实时推给展示页,每分钟存一个样本。
-
前端:
web/display(Agent 卡片总览、线路详情、按 Probe 的线路对比,拖动放大、只提供有数据的时间范围)和web/admin(Agent、Probe、任务、按需测试、系统),共享「纸墨」主题;页面里可以把数据源指到别的后端(API 令牌 + 可选的 CORS 白名单Monitor__CorsOrigins)。 -
真实线路试跑:广东移动家宽 → 日本 IIJ 的 VPS(见 deployment.md)。
-
F1 的服务端部分:
Fleet.Core/Identity/Rpc、Fleet.Server.Abstractions/Enrollment/Link(注册、签名认证、期望状态同步、发件箱收件箱、服务端发起的调用)。 -
M3:注册、RPC、段文件与 SQLite、任务集下发、管理 API。
-
M4(除校准外):累加器、算子、指标注册制、四个模型、流式与持久两条路径、降采样、指标指纹与回填、查询层(范围、步长、数据分层、精确汇总、列式响应)、SSE、按需测试。
-
M5 的一部分:保留清理。
-
F1 的节点部分:
Fleet.Link(链路、发件箱、点对点监听与连接)、Fleet.Hosting、Fleet.Enrollment.Client与fleet-enroll。 -
Agent(M1 的一部分):
Monitor.Agent(NativeAOT 可发布)与Monitor.Measurement(列块合并、预算守卫)。UDP/TCP 数据面(认证、重放窗口、限速、端点学习)、线路任务调和、目标任务(icmp_echo、connect)、按需测试编排(udp_train由 Agent 发包)。测试里的假 Probe(ProbeSimulator)通过真实的点对点握手连接真实的 Agent 与后端,端到端覆盖。详见backend/agent/README.md。 -
Probe(M0/M2 的一部分):
Monitor.Probe(NativeAOT,5.6 MB,常驻约 22 MB)——Agent 列表(bootstrap → 由 Agent 代为查询 → 推送,写回agents.json)、每个 Agent 一个自动重连的会话、udp_echo/tcp_echo/connect/hold角色、udp_train接收端(按序号范围切块)、时钟偏移估计、有界发件箱。真实 Probe + 真实 Agent + 真实后端的端到端测试,以及用发布的 AOT 二进制做过的冒烟(内存稳定、CPU < 1%)。详见backend/probe/README.md。 -
采集积木统一(重构):Probe 和 Agent 的数据面合并成
Monitor.Measurement里的一份实现(每种采集方法一个文件、拨号方和监听方一对角色,UdpMux/Tcp/RowStore共用);合并改成由 Kind 的流声明(Driver、Key)驱动;测试方案移回 Backend;架构测试禁止采集层出现业务概念。 -
TCP 内核采样与长尾:
tcp_echo两端各自采样套接字的TCP_INFO(Linux,union流拼接);tcp.rtt增加p999、max、长尾比tail,新增tcp.slow(块内基线的慢回显占比);序列接口增加anchor=latest。 -
打包与部署(M6 的一部分):
scripts/publish.sh(linux-musl-x64、linux-x64 在 NativeAOT SDK 容器里构建)、scripts/package.sh、packaging/(install.sh、systemd 单元、OpenWrt procd 脚本)、节点启动时的 OpenSSL 自检。在 Alpine、Debian、OpenWrt 官方 rootfs、带 systemd 的 Debian 容器里验证过。详见docs/deployment.md。
未实现:
monitor-bench(M0/M2);arm64 构建(需要 arm64 主机或 CI)、真正的 OpenWrt 设备;udp_train只支持direction=rev;跨公网线路只试跑过一条(几分钟),还没有长期试跑。- 告警;定时调度和按需测试的长期峰值趋势;Windows Probe 没有 tcp_info;Probe 会话结束时最后 ≤10 秒的数据(不修,极端情况)。多个 Probe 同时连时,码率和包速率的预算按单个 Probe 会话计算,总负载是它的倍数,靠会话数上限(默认 8)约束。
fleet-updater、fleet-release、Fleet.Update、Fleet.Server.Releases、Fleet.Server.Sqlite(F2;Monitor 自己实现IFleetStore)。/api/admin/releases、/install.sh、/install.ps1(安装脚本返回 501,依赖打包 M6)。- M4 的校准(需要在真实线路上部署 Hysteria2 与 REALITY 对比)和 M5 的 30 天规模验证;模型评分曲线是 v1 的经验值。
- 查询的
tz只支持 UTC(其他值返回 400);probe.endpoint_changes指标未进入注册表(计数在 Agent 运行时状态里)。