refactor!: rename the project from Monitor to MoShiro [CI]
ci/woodpecker/push/main-amd64-build Pipeline was successful

Namespaces, assemblies, solution, binaries, images, systemd units, config paths, environment variables, protocol methods and the Linux user are all renamed. Breaking: existing databases, node identities and installed units must be recreated.
This commit is contained in:
justme committed 2026-10-07 02:03:25 +08:00
1 parent 27ac7fb787
commit 2e146d4da7
309 files changed
+1565 -1572

No files matched your search

+17 -17
View File
@@ -1,35 +1,35 @@
# 线协议
Monitor 的两条控制链路都建立在 Fleet 之上:
MoShiro 的两条控制链路都建立在 Fleet 之上:
- **Agent ↔ Backend**:Fleet 连接服务端(wss),见 [fleet/link.md](fleet/link.md);
- **Probe ↔ Agent**:Fleet 节点间点对点会话(TLS),见 [fleet/link.md](fleet/link.md) 第 8 节。
认证、心跳、重连、能力协商、可靠发件箱、期望状态同步、JSON-RPC 信封都由 Fleet 负责。本文只定义 **Monitor 自己的内容**:`monitor.*` 方法、状态文档、二进制通道,以及 Fleet 之外的数据面(UDP 包和数据连接)。所有类型都放在 `Monitor.Protocol` 中。
认证、心跳、重连、能力协商、可靠发件箱、期望状态同步、JSON-RPC 信封都由 Fleet 负责。本文只定义 **MoShiro 自己的内容**:`moshiro.*` 方法、状态文档、二进制通道,以及 Fleet 之外的数据面(UDP 包和数据连接)。所有类型都放在 `MoShiro.Protocol` 中。
## 1. Fleet 能力的映射
| Monitor 需要的能力 | 使用的 Fleet 机制 | Monitor 提供的内容 |
| MoShiro 需要的能力 | 使用的 Fleet 机制 | MoShiro 提供的内容 |
| --- | --- | --- |
| 下发任务 | 期望状态 `fleet.state.sync` | 文档类型 `TaskSet`,包括 `tasks[]`、`peers`(允许连这个 Agent 的 Probe 公钥,已按线路开关过滤) |
| 下发 Agent 列表给 Probe | 期望状态 `fleet.state.sync`(Probe 直连面板) | 文档类型 `probe_agents`:`version`、`agents[]`(`agent_id`、`host`、`tcp_port`、`udp_ports`、`spki`),已按线路开关过滤;Agent 集合或线路开关变化时重新推送 |
| 更新 | 通知 `monitor.update.offer` / `monitor.update.apply`(B→A、B→P),心跳附加字段 `update` | `offer` 带 CI 签名的发布清单原文和签名,节点只写进数据目录;`apply` 请求更新;`update` 是宿主机更新器的状态(`state`、`current`、`available`、`error`、`at`),见 [deployment.md](deployment.md) |
| 更新 | 通知 `moshiro.update.offer` / `moshiro.update.apply`(B→A、B→P),心跳附加字段 `update` | `offer` 带 CI 签名的发布清单原文和签名,节点只写进数据目录;`apply` 请求更新;`update` 是宿主机更新器的状态(`state`、`current`、`available`、`error`、`at`),见 [deployment.md](deployment.md) |
| 上报原始块 | 发件箱,二进制通道 **16** | `RawChunk`(自描述,见 [measurement.md](measurement.md) 第 4 节),`msg_id = chunk_id` |
| Probe 交付列块 | 点对点会话的发件箱,二进制通道 **17** | 列块:`u32 stream_id \| u32 first_seq \| u32 count \| 列数据(Brotli)` |
| 节点自身状态 | `fleet.heartbeat` 的附加字段 | Agent:`sessions`、`probes[]`、`pps_in/out`、`dropped_invalid`、`dropped_rate_limited`、`queue_bytes`、`update`;Probe:只有 `update` |
| 版本与能力 | `fleet.hello` | capabilities 包括 `monitor.kinds:<列表>`、`monitor.blocks:<列表>`;Agent 附加 `platform`(系统、架构、版本、tag、提交、构建时间)、`tls_spki`、`probe_ports`、`local_limits` 摘要;Probe 附加 `platform` |
| 版本与能力 | `fleet.hello` | capabilities 包括 `moshiro.kinds:<列表>`、`moshiro.blocks:<列表>`;Agent 附加 `platform`(系统、架构、版本、tag、提交、构建时间)、`tls_spki`、`probe_ports`、`local_limits` 摘要;Probe 附加 `platform` |
## 2. `monitor.*` 方法
## 2. `moshiro.*` 方法
### Agent ↔ Backend
| 方法 | 方向 | 类型 | 参数与结果 |
| --- | --- | --- | --- |
| `monitor.test.run` | B→A | 请求 | `test_id`、`probe_id`(在哪个 Probe 上跑)、`plan`、`phases[]` → `accepted`,或错误 `test_busy`、`probe_offline` |
| `monitor.probe.disconnect` | B→A | 请求 | `probe_id` → `accepted`(Agent 是否真的有这个会话);Agent 关闭该 Probe 的会话 |
| `monitor.test.cancel` | B→A | 请求 | `test_id` |
| `monitor.test.status` | A→B | 通知 | `test_id`、`status`(`running`、`phase_done`、`succeeded`、`failed`、`aborted`)、`phase?`、`error_code?` |
| `monitor.event` | A→B | 通知 | `kind`(`probe_connected`(`detail` 是 `probe_id`,`probe` 里带版本、远端地址和连接时间)、`probe_disconnected`、`endpoint_changed`、`session_rejected`、`clock_step`、`gap`、`cpu_saturated`(节点进程 CPU 饱和,可能影响测量,由 Probe 或 Agent 上报))、`at_utc`、`detail` |
| `moshiro.test.run` | B→A | 请求 | `test_id`、`probe_id`(在哪个 Probe 上跑)、`plan`、`phases[]` → `accepted`,或错误 `test_busy`、`probe_offline` |
| `moshiro.probe.disconnect` | B→A | 请求 | `probe_id` → `accepted`(Agent 是否真的有这个会话);Agent 关闭该 Probe 的会话 |
| `moshiro.test.cancel` | B→A | 请求 | `test_id` |
| `moshiro.test.status` | A→B | 通知 | `test_id`、`status`(`running`、`phase_done`、`succeeded`、`failed`、`aborted`)、`phase?`、`error_code?` |
| `moshiro.event` | A→B | 通知 | `kind`(`probe_connected`(`detail` 是 `probe_id`,`probe` 里带版本、远端地址和连接时间)、`probe_disconnected`、`endpoint_changed`、`session_rejected`、`clock_step`、`gap`、`cpu_saturated`(节点进程 CPU 饱和,可能影响测量,由 Probe 或 Agent 上报))、`at_utc`、`detail` |
心跳的附加字段里有 `probes[]`:Agent 当前连着的每个 Probe(`id`、`version`、`remote`、`since_utc_ms`),每次都是完整快照,Backend 靠它纠正错过的连接事件。点对点握手的认证消息里可以带 Probe 的 `version`(只用于展示)。块头里的 `probe_id` 以 Agent 认证过的会话为准,Probe 自报的值会被覆盖。
@@ -38,10 +38,10 @@ Monitor 的两条控制链路都建立在 Fleet 之上:
| 方法 | 方向 | 类型 | 参数与结果 |
| --- | --- | --- | --- |
| `fleet.state.sync`(文档类型 `line_task_set`) | A→P | 请求 | 这条线路的任务(`id`、`kind`、`params`、`stream_id`、`port`)和 Agent 的数据面端口 |
| `monitor.clock` | P→A | 请求 | `probe_mono_us` → `agent_mono_us`;Probe 按往返中点估计两端单调时钟的偏移(取最小往返的一次),记入块头 `probe_offset_us` |
| `monitor.test.phase` | A→P | 请求 | 测试的一个阶段:`test_id`、`phase`、`kind`、`params`、`stream_id`、`duration_s`、`port` → `accepted`;Probe 在回复之前准备好自己一侧的角色(单向数据流:先发几个探活包让 Agent 学到源地址) |
| `monitor.test.phase_end` | A→P | 请求 | `sent_count`(Agent 发出的包数)→ `fragments`:Probe 收尾,把列块交给 Agent,回复交出的个数;Agent 等全部列块合并上传之后才进入下一阶段 |
| `monitor.test.abort` | A→P | 通知 | `test_id` |
| `moshiro.clock` | P→A | 请求 | `probe_mono_us` → `agent_mono_us`;Probe 按往返中点估计两端单调时钟的偏移(取最小往返的一次),记入块头 `probe_offset_us` |
| `moshiro.test.phase` | A→P | 请求 | 测试的一个阶段:`test_id`、`phase`、`kind`、`params`、`stream_id`、`duration_s`、`port` → `accepted`;Probe 在回复之前准备好自己一侧的角色(单向数据流:先发几个探活包让 Agent 学到源地址) |
| `moshiro.test.phase_end` | A→P | 请求 | `sent_count`(Agent 发出的包数)→ `fragments`:Probe 收尾,把列块交给 Agent,回复交出的个数;Agent 等全部列块合并上传之后才进入下一阶段 |
| `moshiro.test.abort` | A→P | 通知 | `test_id` |
| `fleet.outbox.ack` | 双向 | 通知 | Probe 的列块(通道 17)是至少一次投递,Agent 每收到一个就确认,重复到达的只处理一次 |
会话密钥不需要单独的方法:点对点握手(TLS 固定证书 → `peer.challenge` → Probe 用身份私钥签 `(peer_id, nonce, client_pub, server_pub)` → 两端各自 ECDH + HKDF)直接得到 `session_id` 和 `session_key`,`peer.auth` 的应答只回显 `session_id` 用来互相确认。
@@ -58,7 +58,7 @@ Probe 只记录自己一侧的列,Agent 在数据面记录另一侧,由 Agen
单块最多 `MaxRecordsPerChunk`(50 000)条记录:Probe 必须把大的阶段按序号范围切成多个列块(例如 100 Mbit/s、1000 B 的 10 秒阶段是 125 000 个包 → 4 个列块),`phase_end` 的应答报告总块数。块头里 Probe 必须带上 `agent_id`(它知道自己在和哪个 Agent 通信)。
新增方法只需要在 `Monitor.Protocol/Rpc` 中定义,并在节点组装处加一行 `.On(...)`。旧节点会通过 capabilities 协商自动避开不支持的方法。
新增方法只需要在 `MoShiro.Protocol/Rpc` 中定义,并在节点组装处加一行 `.On(...)`。旧节点会通过 capabilities 协商自动避开不支持的方法。
## 3. 数据面(不属于 Fleet)
@@ -95,7 +95,7 @@ Probe 只记录自己一侧的列,Agent 在数据面记录另一侧,由 Agen
## 4. 版本演进
- Fleet 层的兼容规则见 [fleet/link.md](fleet/link.md)。
- `monitor.*` 方法:新增方法或可选字段不需要升级版本,接收方忽略未知字段。
- `moshiro.*` 方法:新增方法或可选字段不需要升级版本,接收方忽略未知字段。
- RawChunk:块头自描述,新增列或新增 Kind 不需要升级 `container_version`;只有容器格式变化时才升级。
- UDP 包和数据连接首帧的布局变化时,必须升级 `protocol_version`,并更新黄金字节测试。
- Agent 同时支持当前版本和上一个版本的 Probe;Backend 能解码保留期内所有的 `container_version`。