Skip to content
21 changes: 15 additions & 6 deletions src/content/config/data.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,26 @@ hub 的全部数据在一个 SQLite 文件里:一键脚本部署是 `/opt/moni

## 保留天数

**设置**页的**历史数据保留天数**(1–3650,默认 7)决定每分钟一行的历史明细和延迟记录留多久,hub 每个
整点清理超出的部分。
**设置**页的**历史数据保留天数**(1–365,默认 30)决定图表最远能看多少天,hub 每个整点清理超出的部分。

累计流量不受影响:总流量和月流量是独立的累计值,不是从明细算出来的,调小保留天数只会让图表变短。
历史分两层保存:最近 7 天按分钟,更早的按小时汇总。超过一周的图表上,按分钟和按小时画出来几乎一样,
按小时存只占几十分之一的空间。100 台节点、每台 4 个每分钟一次的延迟监控,保留 30 天约 110 MiB,90 天约
150 MiB,一年约 240 MiB。

默认 30 天,能看约一个月的历史,上限 365 天。

累计流量不受影响:总流量和月流量是独立的累计值,不是从历史算出来的,调小保留天数只会让图表变短。

从 hub 1.3.1 及更早版本升级后,hub 启动时把 7 天以前的分钟明细汇总成小时数据再删掉,明细多时要几分钟,
期间面板照常可用,超过 7 天的图表中间会缺一段,汇总完就补上。删掉的明细不会让文件自己变小,过几分钟在
**数据**页点一次**回收空间**即可。

## 回收空间

删掉的历史只把空间还给 SQLite 自己,文件不会变小。**数据**页的**回收空间**依次清理超出保留天数的明细、
删掉的历史只把空间还给 SQLite 自己,文件不会变小。**数据**页的**回收空间**依次清理超出保留天数的历史、
重建数据库文件(`VACUUM`)、截断预写日志,把空间还给文件系统。

执行时需要和数据库大小相当的空闲磁盘,期间面板和 agent 上报会短暂等待。
执行时需要约为数据库两倍的空闲磁盘,期间面板和 agent 上报会短暂等待。

## 备份与恢复

Expand All @@ -22,7 +31,7 @@ hub 的全部数据在一个 SQLite 文件里:一键脚本部署是 `/opt/moni

**导入备份**用备份文件整体替换当前数据:节点、设置、历史、密码都换成备份里的。

- 文件先完整上传、校验通过才替换,最大 256 MiB;校验不通过时当前数据不变
- 文件先完整上传、校验通过才替换,最大 1 GiB;校验不通过时当前数据不变
- 旧版本 hub 导出的备份可以导入新版本,反过来不行,要先升级
- 导入后所有登录会话失效,执行导入的这个浏览器会拿到新会话;在线的 agent 自动重连
- 反代要放行 8 MiB 的请求体,见[反向代理](/install/reverse-proxy#2-请求体上限-8-mib)
Expand Down
19 changes: 14 additions & 5 deletions src/content/dev/architecture.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,10 @@ POST /api/db/restore POST /api/db/vacuum
| `setting` | key/value 配置,替代配置文件 |
| `node` | 节点配置 + agent 上报的静态信息,含分组、离线通知的开关与状态 |
| `traffic` | **单调递增的流量累计**。1:1 于 node,约每分钟写一次 |
| `metric` | 历史明细,每节点每分钟一行,按保留天数删 |
| `metric` | 历史明细,每节点每分钟一行,最多留 7 天 |
| `ping_task` / `ping_node` | 探测任务及其节点分配 |
| `ping_record` | 探测结果,同样按保留天数删 |
| `ping_record` | 探测结果,同样最多留 7 天 |
| `metric_hour` / `ping_hour` | 小时汇总,由上面两张表每小时折叠而来,按保留天数删 |
| `session` | 登录会话,存 sha256,14 天过期 |

`traffic` 单独一张表,因为它和 `node` 的读写方式完全不同:一个是偶尔修改的配置,一个是持续累加的数据。
Expand All @@ -159,15 +160,23 @@ POST /api/db/restore POST /api/db/vacuum
平均值。同一行另存这一分钟里 agent 报过的最高网速,聚合成宽窗口时取桶内的最大值,所以 7 天窗口里的一次
测速仍是它当时的速率。

小时汇总的一行是这一小时里全部分钟行的平均值,另存参与平均的分钟数;延迟存答上来的次数、超时次数、中位数
和最低最高值。一小时结束后再等一小时才汇总:agent 最慢一小时上报一次,探测结果要等下一帧才落库。分钟明细
在所在的小时汇总之后才删。

## 历史查询的两个上限

```text
hours 窗口宽度 登录 1–2160,匿名 1–168
hours 窗口宽度 1 到保留天数 × 24,登录与匿名相同
points 返回点数 60–1440,默认 1440;调用方报上自己能画多少点,hub 只会调低
```

两个上限管两件事:`points` 限制返回多少行,`hours` 限制扫描多少行。`hours=2160` 最多只返回 1440 行,
却要读完这个节点在窗口内保留的全部记录。主题画的最宽窗口是 7 天,所以匿名请求限制在 168 小时。
两个上限管两件事:`points` 限制返回多少行,`hours` 限制扫描多少行。7 天以内的窗口读分钟明细,最多读
一周的行;更宽的窗口读小时汇总,一年也只有 8760 行,再加上最近还没汇总的那一两个小时的分钟明细。所以
无论窗口多宽,一次请求读的行数都不超过一周的分钟明细,匿名请求不必另设更低的上限。

更宽的窗口每个点至少一小时。资源的平均值按分钟数加权合并,和直接用分钟明细算的一致;延迟的丢包率和最低
最高值是精确的,中位数在一个点跨多个小时时,取各小时中位数按答上来的次数加权后的中位数。

分辨率由屏幕决定:样本放得下就一个不抽稀,放不下才聚合。上限由 hub 决定而不是调用方,因为这个接口
匿名可访问。
Expand Down
42 changes: 36 additions & 6 deletions src/content/dev/theme.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -63,25 +63,55 @@ hub 1.3.0 及更早的版本不做这项检查,所以以前装得上的包,

| 接口 | 用途 |
|---|---|
| `GET /api/me` | 站点名、登录状态、公开页开关 |
| `GET /api/me` | 站点名、登录状态、公开页开关、历史保留天数 |
| `GET /api/nodes` | 节点列表、实时指标、累计流量 |
| `GET /api/nodes/{id}/metrics` | 历史指标和延迟记录 |
| `GET /api/ws` | 每 2 秒推送一次节点快照的 WebSocket |
| `GET /api/themes/{short}/config` | 站长在面板里保存的主题设置,见下文[主题设置](#主题设置) |

`metrics` 的三个查询参数都可以省:

- `hours=N`:窗口宽度,默认 6。匿名上限 168,登录后 2160,超出时静默收窄
- `hours=N`:窗口宽度,默认 6,上限是 `/api/me` 的 `history_days` × 24,登录与匿名相同,超出时静默收窄
- `points=W`:图表能画下的点数,60–1440。只会让 hub 抽得更稀,不会更密
- `series=metrics|ping`:只取要画的那一类,另一类占响应的三分之一到三分之二

`metrics` 的每一行描述一段时间:`net_rx` / `net_tx` 是这段时间的平均网速,画成线时积分等于累计流量;
`net_rx_max` / `net_tx_max` 是其中最高的网速,按 agent 的一个上报间隔(默认 1 秒)测得,不小于平均值。
一次 15 秒的测速在一分钟的平均值里只剩四分之一,在 7 天窗口里更低,要画它跑到过多高就读这两个 key。
hub 1.3.0 及更早没有这两个 key。
`metrics` 的每一行描述一段时间,`minutes` 是其中有数据的分钟数,满额是点距除以 60:

- `cpu`、`mem_used`、`disk_used`、`net_rx` / `net_tx` 是这些分钟的平均值。网速乘以 `minutes` × 60 秒
就是这段时间的流量
- `cpu_max`、`net_rx_max` / `net_tx_max` 是其中的最高值,按 agent 的一个上报间隔(默认 1 秒)测得,
不小于平均值。一次 15 秒的测速或 CPU 占满在一分钟的平均值里只剩四分之一,在 7 天窗口里更低,要画它
到过多高就读这几个 key
- `minutes` 不满额,说明节点这段时间有一部分不在线,可以用来画在线率。agent 每次连上的第一分钟不单独
记一行,所以算出的在线率会比实际略低
- 以上按 agent 每分钟至少上报一次而言(默认每秒一次)。`--interval` 超过 60 秒时,hub 只在收到上报的那一
分钟记一行,`minutes` 按比例偏小,300 秒时只有满额的五分之一,积分出的流量和在线率都会偏低。累计流量
以 `/api/nodes` 返回的为准

hub 1.3.0 及更早没有 `net_rx_max` / `net_tx_max`,1.3.1 及更早没有 `cpu_max` 和 `minutes`。

延迟监控的名称在响应的 `probes` 里随数据一起返回,匿名可读,画延迟图不需要第二个请求,也不需要登录。

### 时间范围

站长在面板里设的保留天数就是能画多远,`/api/me` 里的 `history_days`(1–365)给出这个数。时间范围的按钮
按它生成,不要写死:写死的「30 天」遇上只保留 7 天的 hub,会被静默收窄成 7 天,按钮上却还写着 30 天。

```ts
// 默认主题的做法:小于保留期的整档位,最后加上保留期本身。
// 保留期比某个整档位多不到四分之一时去掉那一档,
// 免得「90 天」「92 天」两个按钮并列
const WINDOWS = [1, 6, 24, 168, 720, 2160]
const whole = history_days * 24
const hours = [...WINDOWS.filter((h) => h * 1.25 <= whole), whole]
```

hub 1.3.1 及更早没有 `history_days`,这时按 7 天处理:那些版本匿名最多只给 168 小时。

7 天以内的窗口来自每分钟一行的明细,更宽的来自小时汇总,每个点至少一小时。一行的含义不变:资源仍是这段
时间的平均值和峰值,延迟的 `loss` 和 `band` 是精确的,`latency` 在一个点跨多个小时时是各小时中位数按答上
来的次数加权后的中位数。

`ping` 里的记录按站长在面板上排的监控顺序逐个排列,同一个监控的记录按时间先后。按 `task_id` 第一次出现的
顺序生成曲线,图例和配色就和面板一致。hub 1.3.0 及更早按时间先后排,监控之间谁先谁后不固定。

Expand Down
4 changes: 2 additions & 2 deletions src/content/install/reverse-proxy.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ cloudflared service install

### 2. 请求体上限 8 MiB

导入备份和上传主题按 4 MiB 分片上传,hub 对单个请求的上限是 8 MiB。这个数不随数据库变大:256 MiB 的
备份也只是 64 个 4 MiB 的请求,Cloudflare 免费版每个请求 100 MB 的上限同样够用。
导入备份和上传主题按 4 MiB 分片上传,hub 对单个请求的上限是 8 MiB。这个数不随数据库变大:1 GiB 的
备份也只是 256 个 4 MiB 的请求,Cloudflare 免费版每个请求 100 MB 的上限同样够用。

nginx 默认的 `client_max_body_size 1m` 连一片都放不过。这时 413 来自反代,hub 没有日志,面板收到 413
会直接提示调大 `client_max_body_size`。
Expand Down
Loading