docs: describe the unified Agent topology and link controls
Align architecture, protocol, API, storage, security and deployment documentation with default mutual measurements and the Agent link board.
This commit is contained in:
1 parent
15f0023614
commit
c9beeee8e3
16 files changed
+363
-383
No files matched your search
+31
-35
@@ -2,11 +2,11 @@
|
||||
|
||||
## 1. 目标
|
||||
|
||||
1. 三个独立项目加一个前端:Probe、Agent、Backend 各自拥有解决方案,可以单独构建、测试和发布;Web 是独立的 Vite 项目(`web/`)。
|
||||
2. 通用能力只写一次:TCP/QUIC Datagram/TLS/ICMP 采集积木(类似 iperf3 的能力,但只记录原始数据)放在 `MoShiro.Measurement` 中,Probe 和 Agent 共用;采集方法(Kind)由积木组合声明而成。
|
||||
1. 两个独立程序加一个前端:Agent、Backend 各自拥有解决方案,可以单独构建、测试和发布;Web 是独立的 Vite 项目(`web/`)。
|
||||
2. 通用能力只写一次:TCP/QUIC Datagram/TLS/ICMP 采集积木(类似 iperf3 的能力,但只记录原始数据)放在 `MoShiro.Measurement` 中,Agent 共用;采集方法(Kind)由积木组合声明而成。
|
||||
3. 节点机制通用化:注册、身份、连接、RPC、可靠上报、状态同步、宿主,由与业务无关的 Fleet 框架提供(见 [Fleet 文档](../../backend/fleet/README.md))。MoShiro 只写业务,其他产品也可以复用 Fleet。
|
||||
4. 单一真源:协议、原始数据格式、测试方案、指标、错误码、版本号、编译设置、代码风格都只有一处定义,改动后下游自动更新,或在编译期、CI 中报错。
|
||||
5. 模块化:Probe/Agent 由可插拔的模块组成;Backend 按层分成多个项目,层之间的依赖在编译期强制。
|
||||
5. 模块化:Agent 由可插拔的模块组成;Backend 按层分成多个项目,层之间的依赖在编译期强制。
|
||||
6. 轻量:运行时只依赖 BCL 和仓库内的库,不引用任何 NuGet 包。
|
||||
|
||||
## 2. 仓库布局
|
||||
@@ -35,7 +35,6 @@ moshiro/
|
||||
│ ├─ MoShiro.Protocol/ # 契约真源:Kind 目录、任务集、moshiro.* 方法、测量包、RawChunk、错误码
|
||||
│ ├─ MoShiro.Measurement/ # 采集引擎:积木、行表、合并、预算(见 measurement.md)
|
||||
│ └─ tests/
|
||||
├─ probe/ src/MoShiro.Probe/ tests/ # 家宽端采集器
|
||||
├─ agent/ src/MoShiro.Agent/ tests/ # VPS 端采集器
|
||||
├─ src/ # Backend(面板)
|
||||
│ ├─ MoShiro.Backend/ # 宿主与组合根(Program.cs)
|
||||
@@ -49,13 +48,13 @@ moshiro/
|
||||
└─ (解决方案见 backend/MoShiro.slnx)
|
||||
```
|
||||
|
||||
节点机器上的发布物是两个独立进程,注册和采集分开:`fleet-enroll`(一次性运行)和 `moshiro-agent`(或 `moshiro-probe`,常驻)。更新:Quadlet 装的 Agent、Probe 由节点退出后 systemd 重新拉镜像,Backend 和一行脚本装的节点由宿主机上的 `moshiro-update` 完成,见 [deployment.md](../ops/deployment.md)。
|
||||
节点机器上的发布物是两个独立进程,注册和采集分开:`fleet-enroll`(一次性运行)和 `moshiro-agent`(常驻)。更新:Quadlet 装的 Agent 由节点退出后 systemd 重新拉镜像,Backend 和一行脚本装的节点由宿主机上的 `moshiro-update` 完成,见 [deployment.md](../ops/deployment.md)。
|
||||
|
||||
## 3. 依赖关系
|
||||
|
||||
```text
|
||||
┌────────┐ ┌────────┐ ┌──────────────────────────────┐ ┌─────┐
|
||||
│ Probe │ │ Agent │ │ Backend (Api/Gateway/App/ │─openapi─>│ Web │
|
||||
│ 拨号方 │ │ Agent │ │ Backend (Api/Gateway/App/ │─openapi─>│ Web │
|
||||
└─┬──┬───┘ └─┬──┬───┘ │ Analysis/Storage) │ └─────┘
|
||||
│ └───┬───┘ │ └───┬───────────────┬──────────┘
|
||||
│ ▼ │ │ │
|
||||
@@ -76,8 +75,8 @@ moshiro/
|
||||
简要来说:
|
||||
|
||||
```text
|
||||
Probe, Agent ──> Measurement ──> MoShiro.Protocol ──> Fleet.Core / Fleet.Rpc
|
||||
Probe, Agent ──> Fleet.Link / Fleet.Hosting / Fleet.Identity
|
||||
Agent ──> Measurement ──> MoShiro.Protocol ──> Fleet.Core / Fleet.Rpc
|
||||
Agent ──> Fleet.Link / Fleet.Hosting / Fleet.Identity
|
||||
Backend.* ──> MoShiro.Protocol + Fleet.Server.* (不引用 Measurement)
|
||||
fleet-enroll ──> Fleet.Enrollment.Client ──> Fleet.Identity / Core
|
||||
Web ──> openapi/v1.json
|
||||
@@ -89,7 +88,7 @@ Web ──> openapi/v1.json
|
||||
| `Fleet.Server.*` | ASP.NET Core、`Microsoft.Data.Sqlite`(仅 Sqlite 项目)、节点侧 Fleet 库 | 任何 `MoShiro.*` |
|
||||
| `MoShiro.Protocol` | Fleet.Core、Fleet.Rpc | 任何 I/O、套接字、日志 |
|
||||
| `MoShiro.Measurement` | MoShiro.Protocol、Fleet.Core | NuGet;日志(只通过计数接收器上报);读取配置;统计或解释逻辑 |
|
||||
| Probe / Agent | 上述库,以及 Fleet.Link / Hosting / Identity | NuGet 运行时包;彼此互相引用;Fleet.Enrollment.Client |
|
||||
| Agent | 上述库,以及 Fleet.Link / Hosting / Identity | NuGet 运行时包;彼此互相引用;Fleet.Enrollment.Client |
|
||||
| Backend.* | MoShiro.Protocol、Fleet.Server.*,以及第 5.2 节列出的包 | Measurement、EF Core 等依赖反射的库 |
|
||||
|
||||
分析器类包(`PrivateAssets="all"`)不受限制。`ArchitectureTests` 在构建时检查上述规则。
|
||||
@@ -105,7 +104,7 @@ Web ──> openapi/v1.json
|
||||
```text
|
||||
MoShiro.Protocol/
|
||||
├─ ProtocolLimits MoShiroErrors(在 Fleet 错误码基础上扩展) IpVersions PublicAddress Ipv6Diagnostic
|
||||
├─ Ids/ AgentId(= Fleet NodeId)、ProbeId、TaskId、TestId
|
||||
├─ Ids/ AgentId(= Fleet NodeId)、NodeId、TaskId、TestId
|
||||
├─ Catalog/
|
||||
│ ├─ Kinds/ Kind 声明(积木组合 + ParamSpec + 记录列 + 预算)
|
||||
│ ├─ KindSpec Kind 与记录流(StreamSpec)的类型定义
|
||||
@@ -127,31 +126,28 @@ MoShiro.Protocol/
|
||||
- `BlockCatalog`:Kind 到拨号方 / 监听方积木的映射;
|
||||
- `BudgetGuard`:参数校验与本地硬上限。
|
||||
|
||||
任务调和在 Agent 的 `TaskManager` 与 Probe 中完成。
|
||||
任务调和在 Agent 的 `TaskManager` 与 拨号方 中完成。
|
||||
|
||||
详见 [measurement.md](../design/measurement.md) 第 6 节。
|
||||
|
||||
## 5. 模块化
|
||||
|
||||
### 5.1 Agent 与 Probe:组装
|
||||
### 5.1 Agent:组装
|
||||
|
||||
节点的组装点是 `AgentApp` 和 `ProbeApp`:在构造函数里显式组装,不使用 DI 容器,也不做反射扫描;没有全局状态,测试可以在同一进程里启动多个。连接、认证、重连、发件箱、状态同步都由 Fleet 提供,MoShiro 只写业务:
|
||||
节点组装点为 `AgentApp`,显式连接各模块,不使用 DI 容器或反射扫描:
|
||||
|
||||
```text
|
||||
AgentApp Probe(ProbeApp)
|
||||
FleetLink(到面板) FleetLink(到面板)
|
||||
状态 TaskSet、方法 moshiro.test.* 状态 probe_agents(Agent 列表)、hello 带系统和构建信息
|
||||
发件箱 RawChunk(通道 16) 心跳带更新器的状态;moshiro.update.* 通知
|
||||
心跳带更新器的状态;moshiro.update.* AgentDirectory → 每个 Agent 一个 AgentConnection(点对点会话)
|
||||
PeerListener / PeerHub(Probe 会话) 会话内:线路任务集 line_task_set 的调和、角色、列块发件箱(通道 17)
|
||||
QuicDatagramTransport / TcpAcceptor(数据端口)
|
||||
AgentApp
|
||||
FleetLink -> Backend;TaskSet、DialTargets、心跳和 RawChunk 发件箱
|
||||
DialerHost / DialDirectory -> 每个目标及 IP 族一个 DialConnection
|
||||
DialConnection -> TLS 控制会话、TaskLink、任务角色和列块发件箱
|
||||
PeerListener / PeerHub <- 其他 Agent 的接入会话
|
||||
QUIC / TCP <- 数据面监听(listen.enabled 默认 true)
|
||||
TaskManager / TestRunner / ChunkAssembler
|
||||
RestartUpdater(只报告有无新版本、请求时退出) RestartUpdater
|
||||
RestartUpdater / OpenWrtUpdater
|
||||
```
|
||||
|
||||
模块之间通过构造函数传入的接口或 `Channel<T>` 通信,禁止通过静态全局状态共享数据。
|
||||
|
||||
新增 RPC 方法:在 `MoShiro.Protocol/Rpc` 中定义 params/result,然后在组装处加一行 `.On(Methods.X, HandleX)`。
|
||||
拨出和接入可同时运行。Backend 的线路策略默认建立所有可拨号 Agent 之间的双向有向线路,排除自连接。节点通过同一条 FleetLink 上报两侧状态。模块使用构造参数或 `Channel<T>` 通信。
|
||||
|
||||
### 5.2 Backend:分层与 API 层
|
||||
|
||||
@@ -168,7 +164,7 @@ AgentApp Probe(ProbeApp)
|
||||
▼ │
|
||||
┌─────────────────────────────────────────────────────────┐ ┌───────────────────┴──┐
|
||||
│ Backend.Application │───>│ LiveHub(Application)│
|
||||
│ Agents · Probe · Tasks(有效任务集的计算与下发) │ │ 内存快照 + 主题订阅 │
|
||||
│ Agents · 拨号方 · Tasks(有效任务集的计算与下发) │ │ 内存快照 + 主题订阅 │
|
||||
│ Tests · Ingest(chunk → 存储 → 分析队列) │ └──────────────────────┘
|
||||
│ Analysis(AnalysisScheduler 等)· Query · Auth · Updates │ 调用 ─> Backend.Analysis
|
||||
└───────────────────────────▲─────────────────────────────┘ 纯计算:算子/指标/模型
|
||||
@@ -202,8 +198,8 @@ Backend 允许的包:ASP.NET Core 共享框架、`Microsoft.Data.Sqlite`、`Mi
|
||||
## 6. 编译设置
|
||||
|
||||
- 所有 .NET 项目共用 `backend/Directory.Build.props`(目标框架、可空引用、警告当错误、最新分析器、确定性构建、禁用 API 清单 `BannedSymbols.txt`、版本号)和根目录的 `Directory.Packages.props`(NuGet 版本、SQLite 源码版本),SDK 版本在根目录的 `global.json`。
|
||||
- `backend/probe/`、`backend/agent/` 另有 `Directory.Build.props`:NativeAOT、体积优先、关闭 EventSource、调试支持和 Server/Concurrent GC 等,具体开关以文件为准;保留 StackTraceSupport,线上崩溃需要可读的调用栈。
|
||||
- `BannedSymbols.Node.txt` 适用于常驻节点进程(Probe、Agent,以及 Fleet 的节点侧运行库),主要条目:
|
||||
- `backend/agent/` 另有 `Directory.Build.props`:NativeAOT、体积优先、关闭 EventSource、调试支持和 Server/Concurrent GC 等,具体开关以文件为准;保留 StackTraceSupport,线上崩溃需要可读的调用栈。
|
||||
- `BannedSymbols.Node.txt` 适用于常驻节点进程(Agent,以及 Fleet 的节点侧运行库),主要条目:
|
||||
- `System.Diagnostics.Process`;
|
||||
- `System.Reflection.Assembly.Load*`;
|
||||
- `System.Runtime.InteropServices.NativeLibrary.Load*`;
|
||||
@@ -216,7 +212,7 @@ Backend 允许的包:ASP.NET Core 共享框架、`Microsoft.Data.Sqlite`、`Mi
|
||||
|
||||
| 程序 | 发布体积 | 空闲常驻内存 | 负载 |
|
||||
| --- | --- | --- | --- |
|
||||
| Probe | ≤ 8 MB(Linux/OpenWrt,静态链接了 .NET 的加密、压缩、网络库;Windows 实测 5.6 MB) | ≤ 32 MB(Linux 实测约 21 MB) | 同时连接 15 个 Agent 并运行默认模板时 CPU < 2%;`hy2_ladder` 100 Mbps 时 CPU < 50%(单核) |
|
||||
| 拨号方 | ≤ 8 MB(Linux/OpenWrt,静态链接了 .NET 的加密、压缩、网络库;Windows 实测 5.6 MB) | ≤ 32 MB(Linux 实测约 21 MB) | 同时连接 15 个 Agent 并运行默认模板时 CPU < 2%;`hy2_ladder` 100 Mbps 时 CPU < 50%(单核) |
|
||||
| Agent | ≤ 10 MB(Linux 实测 8.4 MB) | ≤ 48 MB(Linux 实测约 23 MB) | 运行默认模板时 ≤ 64 MB;同时跑一个 200 Mbps 测试时 CPU < 60%(1 vCPU) |
|
||||
| fleet-enroll | ≤ 4 MB | — | 一次性运行 |
|
||||
| Backend | 不设硬性限制 | ≤ 150 MB | — |
|
||||
@@ -235,28 +231,28 @@ Backend 允许的包:ASP.NET Core 共享框架、`Microsoft.Data.Sqlite`、`Mi
|
||||
| 程序 | RID | 说明 |
|
||||
| --- | --- | --- |
|
||||
| Agent | `linux-x64`、`linux-arm64` | VPS |
|
||||
| Probe | `linux-x64`、`linux-arm64`、`win-x64` | 普通 PC 或服务器 |
|
||||
| Probe(OpenWrt) | `linux-musl-x64`、`linux-musl-arm64` | 正式支持;`linux-musl-arm`(armv7)视工具链验证结果决定是否支持 |
|
||||
| 拨号方 | `linux-x64`、`linux-arm64`、`win-x64` | 普通 PC 或服务器 |
|
||||
| 拨号方(OpenWrt) | `linux-musl-x64`、`linux-musl-arm64` | 正式支持;`linux-musl-arm`(armv7)视工具链验证结果决定是否支持 |
|
||||
| fleet-enroll | 与所在节点相同 | |
|
||||
| Backend | `linux-x64`、`linux-arm64`、`win-x64` | |
|
||||
|
||||
- MIPS 不支持(NativeAOT 没有 MIPS 目标)。使用 MIPS 路由器(例如 MT7621)时,把 Probe 运行在局域网内的其他设备上,比如 NAS、树莓派或 PC,测量结果同样代表这条家宽。
|
||||
- MIPS 不支持(NativeAOT 没有 MIPS 目标)。使用 MIPS 路由器(例如 MT7621)时,把 拨号方 运行在局域网内的其他设备上,比如 NAS、树莓派或 PC,测量结果同样代表这条家宽。
|
||||
- NativeAOT 需要目标平台的原生工具链:musl 目标在 Alpine 容器中构建,arm64 使用交叉编译镜像。CI 矩阵为 Windows、Linux glibc、Linux musl。
|
||||
- `scripts/publish.sh <probe|agent|backend|fleet-enroll> <rid>` 输出到 `backend/artifacts/publish/<project>/<rid>/`。
|
||||
- `scripts/publish.sh <agent|backend|fleet-enroll> <rid>` 输出到 `backend/artifacts/publish/<project>/<rid>/`。
|
||||
- 容器镜像由 CI 构建并对镜像 digest 签名,节点的宿主机更新器验签后更新,见 [deployment.md](../ops/deployment.md);纯二进制节点的更新见 [路线图](../roadmap.md)。
|
||||
- Linux 上 TLS 依赖系统 OpenSSL(`libssl.so.3`)。
|
||||
|
||||
### 8.1 OpenWrt 上的 Probe
|
||||
### 8.1 OpenWrt 上的 拨号方
|
||||
|
||||
| 事项 | 做法 |
|
||||
| --- | --- |
|
||||
| C 库 | musl:使用 `linux-musl-*` 目标发布 |
|
||||
| TLS | .NET 在 Linux 上依赖 OpenSSL,而 OpenWrt 默认使用 mbedTLS/wolfSSL。需要安装 `libopenssl3`(安装脚本自动检查并提示)。启动时自检,缺少时明确报错,不会静默降级 |
|
||||
| 全球化 | 已启用 `InvariantGlobalization`,不依赖 ICU |
|
||||
| 服务管理 | procd:提供 `/etc/init.d/moshiro-probe`(`procd_set_param respawn`,前台运行,日志输出到 logd);`Fleet.Hosting.ServiceShell` 在 procd 下不需要 `sd_notify` |
|
||||
| 服务管理 | procd:提供 `/etc/init.d/moshiro-agent`(`procd_set_param respawn`,前台运行,日志输出到 logd);`Fleet.Hosting.ServiceShell` 在 procd 下不需要 `sd_notify` |
|
||||
| 存储 | 闪存很小,而且需要避免频繁写入:二进制放在 `/usr/lib/moshiro/`,配置和身份放在 `/etc/moshiro/`(sysupgrade 时通过 `/lib/upgrade/keep.d/` 保留);测量数据本来就不落盘;`ConfigStore` 只在 Agent 列表变化时写入 |
|
||||
| 内存 | 预算 ≤ 32 MB,适合 ≥ 256 MB 内存的路由器;在本地配置中限制重负载测试的码率(`limits.max_test_mbps`),防止路由器 CPU 成为瓶颈,反过来影响测量结果 |
|
||||
| 测量偏差 | Probe 运行在网关上时,自己没有 NAT;一旦路由器 CPU 饱和,结果就会失真。因此 Probe 在 `moshiro.event` 中上报自身的 CPU 繁忙标记(仅进程级别),分析层据此标注置信说明 |
|
||||
| 测量偏差 | 拨号方 运行在网关上时,自己没有 NAT;一旦路由器 CPU 饱和,结果就会失真。因此 拨号方 在 `moshiro.event` 中上报自身的 CPU 繁忙标记(仅进程级别),分析层据此标注置信说明 |
|
||||
| 打包 | 提供 `tar.gz` 和 procd 脚本;包格式(ipk 或 apk)按目标 OpenWrt 版本提供 |
|
||||
| 更新 | 纯二进制节点的更新器还没有实现([路线图](../roadmap.md));实现时 `keep_versions = 1`,下载前检查剩余空间,避免写满闪存 |
|
||||
|
||||
|
||||
Reference in new issue
Block a user