docs: rewrite README and AGENTS.md etc..
ci/woodpecker/push/web-build Pipeline was successful
ci/woodpecker/push/verify Pipeline was successful
ci/woodpecker/push/e2e Pipeline was successful

This commit is contained in:
justme committed 2026-10-21 06:28:19 +08:00
1 parent cc64df3e70
commit a9bf849697
22 files changed
+514 -665

No files matched your search

+11 -11
View File
@@ -2,10 +2,10 @@
MoShiro 的两条控制链路都建立在 Fleet 之上:
- **Agent ↔ Backend**:Fleet 连接服务端(wss),见 [../backend/fleet/README.md](../../backend/fleet/README.md);
- **Probe ↔ Agent**:Fleet 节点间点对点会话(TLS),见 [../backend/fleet/README.md](../../backend/fleet/README.md) 的「点对点会话」一节。
- Agent ↔ Backend:Fleet 连接服务端(wss),见 [Fleet 文档](../../backend/fleet/README.md);
- Probe ↔ Agent:Fleet 节点间点对点会话(TLS),见 [Fleet 文档](../../backend/fleet/README.md) 的「点对点会话」一节。
认证、心跳、重连、能力协商、可靠发件箱、期望状态同步、JSON-RPC 信封都由 Fleet 负责。本文只定义 **MoShiro 自己的内容**:`moshiro.*` 方法、状态文档、二进制通道,以及 Fleet 之外的数据面(QUIC Datagram 和 TCP 数据连接)。所有类型都放在 `MoShiro.Protocol` 中。
认证、心跳、重连、能力协商、可靠发件箱、期望状态同步、JSON-RPC 信封都由 Fleet 负责。本文只定义 MoShiro 自己的内容:`moshiro.*` 方法、状态文档、二进制通道,以及 Fleet 之外的数据面(QUIC Datagram 和 TCP 数据连接)。所有类型都放在 `MoShiro.Protocol` 中。
## 1. Fleet 能力的映射
@@ -15,8 +15,8 @@ MoShiro 的两条控制链路都建立在 Fleet 之上:
| 下发 Agent 列表给 Probe | 期望状态 `fleet.state.sync`(Probe 直连面板) | 文档类型 `probe_agents`:`version`、`agents[]`(`agent_id`、`host`、`tcp_port`、`quic_ports`、`public_key`),`public_key` 是 Agent 面向 Probe 的 TLS 证书公钥(SPKI,base64):Probe 用它固定证书并派生敲门密钥;没有上报公钥的 Agent 不会下发。已按线路开关过滤;Agent 集合或线路开关变化时重新推送 |
| 定时重启 | 通知 `moshiro.schedule`(B→A、B→P) | `{restart_at}`,形如 `04:30+08:00`,空表示关闭;连上时补发、管理端改了设置就群发。节点本地写了 `restart_at` 或 `MOSHIRO_RESTART_AT` 时以本地为准;节点只是到点自己有序退出,由服务管理器拉起 |
| 更新 | 通知 `moshiro.update.offer` / `moshiro.update.apply`(B→A、B→P),心跳附加字段 `update` | `offer` 带 CI 签名的发布清单原文和签名,节点只写进数据目录;`apply` 请求更新;`update` 是宿主机更新器的状态(`state`、`current`、`available`、`error`、`at`),见 [deployment.md](../ops/deployment.md) |
| 上报原始块 | 发件箱,二进制通道 **16** | `RawChunk`(自描述,见 [measurement.md](measurement.md) 第 4 节),`msg_id = chunk_id` |
| Probe 交付列块 | 点对点会话的发件箱,二进制通道 **17** | 列块:`u32 stream_id \| u32 first_seq \| u32 count \| 列数据(Brotli)` |
| 上报原始块 | 发件箱,二进制通道 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 包括 `moshiro.kinds:<列表>`、`moshiro.blocks:<列表>`;Agent 附加 `platform`(系统、架构、版本、tag、提交、构建时间)、`tls_pubkey`(面向 Probe 的证书公钥,面板自己算指纹)、`addresses`(本机公网地址)、`probe_ports`、`local_limits` 摘要;Probe 附加 `platform` |
@@ -53,7 +53,7 @@ MoShiro 的两条控制链路都建立在 Fleet 之上:
### 列块(Probe → Agent,通道 17)
Probe 只记录自己一侧的列,Agent 在数据面记录另一侧,由 Agent 合并、盖章、上传(见 `measurement.md` 第 5 节)。合并**由 Kind 的流声明驱动**(`StreamSpec`:`Driver`、`Key`,每一列的归属由它的时钟决定),没有按 Kind 手写的模式:
Probe 只记录自己一侧的列,Agent 在数据面记录另一侧,由 Agent 合并、盖章、上传(见 `measurement.md` 第 5 节)。合并由 Kind 的流声明驱动(`StreamSpec`:`Driver`、`Key`,每一列的归属由它的时钟决定),没有按 Kind 手写的模式:
| 流声明 | 例子 | Probe 的列块 | Agent 补充 |
| --- | --- | --- | --- |
@@ -63,7 +63,7 @@ Probe 只记录自己一侧的列,Agent 在数据面记录另一侧,由 Agen
单块最多 `MaxRecordsPerChunk`(50 000)条记录:Probe 必须把大的阶段按序号范围切成多个列块(例如 100 Mbit/s、1000 B 的 10 秒阶段是 125 000 个包 → 4 个列块),`phase_end` 的应答报告总块数。块头里 Probe 必须带上 `agent_id`(它知道自己在和哪个 Agent 通信)。
新增方法只需要在 `MoShiro.Protocol/Rpc` 中定义,并在节点组装处加一行 `.On(...)`。旧节点会通过 capabilities 协商自动避开不支持的方法。
新增方法在 `MoShiro.Protocol/Rpc` 中定义,并在节点组装处加一行 `.On(...)`。旧节点通过 capabilities 协商避开不支持的方法。
## 3. 数据面(不属于 Fleet)
@@ -82,7 +82,7 @@ Probe 只记录自己一侧的列,Agent 在数据面记录另一侧,由 Agen
28+N 16 mac HMAC-SHA256(session_key, 前面全部字节),截断至 16 字节
```
**接收方处理规则**(任一步失败即静默丢弃并计数,**不回复**):
接收方处理规则(任一步失败即静默丢弃并计数,不回复):
1. 长度、magic、version、type 合法;
2. `session_id` 和 `stream_id` 都处于活跃状态;
@@ -90,7 +90,7 @@ Probe 只记录自己一侧的列,Agent 在数据面记录另一侧,由 Agen
4. `seq` 不在重放窗口中;
5. 速率不超过声明速率的 1.2 倍,也不超过本地硬上限。
通过后先**记录原始列**。收到 `EchoRequest` 时,立即回复一个长度**完全相同**的包,发往请求的**实际源地址**(这样可以跟随 NAT 映射变化),并记录回复时刻。
通过后先记录原始列。收到 `EchoRequest` 时,立即回复一个长度相同的包,发往请求的实际源地址(这样可以跟随 NAT 映射变化),并记录回复时刻。
### 3.2 TCP/TLS 数据连接
@@ -107,11 +107,11 @@ Probe 只记录自己一侧的列,Agent 在数据面记录另一侧,由 Agen
- Agent 和 Probe 会在 hello 与心跳中上报 IPv6 套接字、监听、全局地址、默认路由及网络命名空间状态。Podman/Docker 宿主网络部署里,采样反映宿主接口;桥接网络容器会分别报告容器网络和能读取到的宿主 IPv6。诊断只有布尔值和粗粒度状态,不包含地址和接口名称。
- `ConnectedProbe`、`TestRunParams` 和 RawChunk 块头新增 `ip_version`,取值 `ipv4` / `ipv6`,缺省 `ipv4`。Agent 合并列块时以认证过的控制会话地址族为准,覆盖 Probe 上报的值。
- IPv4 的线路 id `agent~probe`、序列 `line:probe` 保持不变;IPv6 使用 `agent~probe~ipv6`、`line:probe:ipv6`。指标、重算、SSE 和测试结果按路径隔离。
- 本次是 JSON 字段扩展,二进制包、列编码和容器布局没有变化,协议与 `container_version` 保持原版本。双栈采集需要升级 Agent 和 Probe;旧节点继续提供 IPv4。
- 双栈是 JSON 字段扩展,二进制包、列编码和容器布局不变,`protocol_version` 与 `container_version` 不升级。双栈采集需要升级 Agent 和 Probe,旧节点继续提供 IPv4。
### 通用规则
- Fleet 层的兼容规则见 [../backend/fleet/README.md](../../backend/fleet/README.md)。
- Fleet 层的兼容规则见 [Fleet 文档](../../backend/fleet/README.md)。
- `moshiro.*` 方法:新增方法或可选字段不需要升级版本,接收方忽略未知字段。
- RawChunk:块头自描述,新增列或新增 Kind 不需要升级 `container_version`;只有容器格式变化时才升级。
- QUIC Datagram 和 TCP 数据连接首帧的布局变化时,必须升级 `protocol_version`,并更新黄金字节测试。