5.4 KiB
Backend 存储
实现位于 MoShiro.Backend.Storage.Sqlite,负责实现 Backend.Application 中定义的端口接口,只做读写,不含业务逻辑。降采样和分析由 Application 调用 Analysis 完成。
1. 目录布局
data/
├─ moshiro.db # SQLite:配置、身份、原始块索引、指标、测试结果
├─ backups/ # Backend 更新前的数据库备份
└─ raw/
└─ 2026-09-27/ # 按 UTC 日期分目录,保留期满整目录删除
├─ agt_01J…/ # 每个 Agent 一个目录
│ ├─ udp_echo.seg # 段文件:同一天、同一 Kind 的块依次追加
│ ├─ tcp_echo.seg
│ └─ tsk_…_icmp_echo.seg # 目标任务
└─ tests/tst_01J…/phase0.seg …
- 段文件:把收到的 RawChunk 原样追加写入(块本身已经带 crc,并且自描述),SQLite 只记录
(segment, offset, length)。每 10 秒一块也不会产生海量小文件。 - 写入顺序:追加写入 →
fsync(每批合并执行一次)→ 插入索引 → 由收件箱确认(Fleet 回复fleet.outbox.ack)。启动时截断没有索引记录的段文件尾部。 - 去重:
chunk_id已存在时,直接回复 ACK。
2. SQLite 配置
journal_mode=WAL、synchronous=NORMAL、foreign_keys=ON、busy_timeout=5000。- 单写入者:所有写操作经过一个有界
Channel,由一个后台循环执行;读操作使用独立的只读连接池。 - 时间统一存储为 Unix 毫秒
INTEGER(UTC);表结构版本记录在PRAGMA user_version,迁移脚本为内置 SQL。
3. 表结构
完整定义以 Schema.cs 为准(当前版本 16,迁移为按版本号追加的内置 SQL)。agents、join_tokens 及公钥、状态版本字段同时作为 Fleet 的 IFleetStore 实现,与其他数据放在同一个 moshiro.db,由同一个单写入者写入。CI 签名的发布清单存在 settings 表中(release.<组件>.manifest、release.<组件>.signature),面板原样保存和转发。
| 类别 | 表 | 说明 |
|---|---|---|
| 身份与注册 | agents、probes、join_tokens、node_meta |
节点公钥、状态、地址(含手填标记)、IPv6 诊断、task_version / applied_task_version、row_version(ETag);node_meta 保存系统、构建信息与国家 / 运营商;agents.name 仅在非 pending 节点间唯一 |
| 账户与信任 | users、sessions、api_tokens、passkeys、operator_sets、audit_log、settings |
会话与 CSRF、能力化 API 令牌、passkey、操作员集合链、审计日志、键值设置 |
| 任务 | tasks、tests、test_results |
tasks.scope 为 line 或 target,agent_id 为空表示全局模板,base_task_id 指向被覆盖的模板;tests 记录按需测试及其阶段、地址族、线路;test_results 保存指标与曲线 |
| 原始数据索引 | raw_segments、raw_chunks |
raw_chunks 记录 (segment, offset, length)、series(line:<probe_id>[:ipv6] 或 target:<task_id>)、Kind、任务、测试、起止时间 |
| 指标 | metric_10s、metric_1m、metric_5m、metric_1h、metric_versions |
每个桶一行,metrics 为 AccumulatorCodec 编码的 {metric_id: 累加器状态};主键 (agent_id, series, window_start);metric_versions 保存指标指纹与重算进度 |
| 分析调度 | analysis_queue、rollup_dirty |
待计算窗口(seq 递增,完成时只删除序号未变的项,处理期间到达的迟到块不丢更新);待降采样的桶(先低层 5 分钟,再高层 1 小时) |
| 观测 | events、host_samples |
节点事件;每个节点每分钟一行的主机资源汇总 |
新增 Kind 或指标不需要改表结构:指标是 metric_*.metrics 中的一个键,Kind 只是 raw_chunks.kind 的一个取值。1 秒精度的热层在内存中,不落盘,见 query.md 第 3 节。
4. 保留
| 数据 | 默认保留 |
|---|---|
| 持续任务的原始段文件 | 30 天 |
| 按需测试的原始段文件 | 90 天 |
| 热层(1s,内存) | 最近 1 小时 |
metric_10s |
48 小时 |
metric_1m |
30 天 |
metric_5m |
365 天 |
metric_1h、tests、test_results |
永久 |
events |
365 天 |
保留期在管理端设置中修改,键为 retention.raw_days、retention.test_raw_days、retention.metric_10s_hours、retention.metric_1m_days、retention.metric_5m_days、retention.events_days、retention.host_days(主机样本,默认 7 天)。
降采样由 Application 的 AnalysisScheduler 驱动:读取下一级的累加器状态,合并后写回上一层,待处理的桶记录在 rollup_dirty。
5. 容量估算
以 15 个 Agent、默认模板(udp_echo 10 Hz + tcp_echo 20 Hz)为例:
| 数据 | 估算 |
|---|---|
| 原始数据 | 每条线路约 7 MB/天(udp_echo)+ 14 MB/天(tcp_echo 及内核采样)≈ 21 MB/天;15 条线路约 0.3 GB/天,30 天约 9.5 GB |
| 按需测试 | 一次 hy2_ladder 约 1.5 MB;每条线路每天 4 次,90 天约 8 GB |
| SQLite | 指标窗口和降采样约 1~2 GB/年 |
写入量约每秒 3 块,单写入者可以承载。以上为估算值。
6. 查询
时间段、自动步长、数据源选择、现场合并和降级规则见 query.md。