From 3ea67a1b046deba6b7c3459e3763678ad0c87d56 Mon Sep 17 00:00:00 2001 From: stqfdyr <89149493+stqfdyr@users.noreply.github.com> Date: Tue, 29 Sep 2026 14:17:50 +0800 Subject: [PATCH 1/7] =?UTF-8?q?docs:=20=E5=8E=86=E5=8F=B2=E5=88=86?= =?UTF-8?q?=E4=B8=A4=E5=B1=82=E5=AD=98=E5=82=A8=E3=80=81=E4=BF=9D=E7=95=99?= =?UTF-8?q?=E5=A4=A9=E6=95=B0=E4=B8=8E=E4=B8=BB=E9=A2=98=E7=9A=84=E6=97=B6?= =?UTF-8?q?=E9=97=B4=E8=8C=83=E5=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 保留天数 1–365、默认 90,最近 7 天按分钟、更早按小时;推荐天数与占用;升级后的汇总与回收 - 回收空间需要约两倍于数据库的空闲磁盘 - 主题契约:/api/me 的 history_days、窗口上限、超过 7 天的窗口的口径 --- src/content/config/data.mdx | 18 +++++++++++++----- src/content/dev/architecture.mdx | 19 ++++++++++++++----- src/content/dev/theme.mdx | 22 ++++++++++++++++++++-- 3 files changed, 47 insertions(+), 12 deletions(-) diff --git a/src/content/config/data.mdx b/src/content/config/data.mdx index 7d7ac25..0801ffa 100644 --- a/src/content/config/data.mdx +++ b/src/content/config/data.mdx @@ -3,17 +3,25 @@ hub 的全部数据在一个 SQLite 文件里:一键脚本部署是 `/opt/moni ## 保留天数 -**设置**页的**历史数据保留天数**(1–3650,默认 7)决定每分钟一行的历史明细和延迟记录留多久,hub 每个 -整点清理超出的部分。 +**设置**页的**历史数据保留天数**(1–365,默认 90)决定图表最远能看多少天,hub 每个整点清理超出的部分。 -累计流量不受影响:总流量和月流量是独立的累计值,不是从明细算出来的,调小保留天数只会让图表变短。 +历史分两层保存:最近 7 天按分钟,更早的按小时汇总。超过一周的图表上,按分钟和按小时画出来几乎一样, +按小时存只占几十分之一的空间。100 台节点、每台 4 个每分钟一次的延迟监控,保留 90 天约 150 MiB,保留 +一年约 240 MiB。 + +推荐 90 天,月付、季付的机器都能看完一整个周期;年付的机器想回看整整一年,填 365。 + +累计流量不受影响:总流量和月流量是独立的累计值,不是从历史算出来的,调小保留天数只会让图表变短。 + +从 hub 1.3.1 及更早版本升级后,hub 启动时把 7 天以前的分钟明细汇总成小时数据再删掉,明细多时要几分钟, +期间面板照常可用。删掉的明细不会让文件自己变小,过几分钟在**数据**页点一次**回收空间**即可。 ## 回收空间 -删掉的历史只把空间还给 SQLite 自己,文件不会变小。**数据**页的**回收空间**依次清理超出保留天数的明细、 +删掉的历史只把空间还给 SQLite 自己,文件不会变小。**数据**页的**回收空间**依次清理超出保留天数的历史、 重建数据库文件(`VACUUM`)、截断预写日志,把空间还给文件系统。 -执行时需要和数据库大小相当的空闲磁盘,期间面板和 agent 上报会短暂等待。 +执行时需要约为数据库两倍的空闲磁盘,期间面板和 agent 上报会短暂等待。 ## 备份与恢复 diff --git a/src/content/dev/architecture.mdx b/src/content/dev/architecture.mdx index 2bbf524..38eebc5 100644 --- a/src/content/dev/architecture.mdx +++ b/src/content/dev/architecture.mdx @@ -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` 的读写方式完全不同:一个是偶尔修改的配置,一个是持续累加的数据。 @@ -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 决定而不是调用方,因为这个接口 匿名可访问。 diff --git a/src/content/dev/theme.mdx b/src/content/dev/theme.mdx index cd04a3d..1ec7505 100644 --- a/src/content/dev/theme.mdx +++ b/src/content/dev/theme.mdx @@ -62,7 +62,7 @@ hub 1.3.0 及更早的版本不做这项检查,所以以前装得上的包, | 接口 | 用途 | |---|---| -| `GET /api/me` | 站点名、登录状态、公开页开关 | +| `GET /api/me` | 站点名、登录状态、公开页开关、历史保留天数 | | `GET /api/nodes` | 节点列表、实时指标、累计流量 | | `GET /api/nodes/{id}/metrics` | 历史指标和延迟记录 | | `GET /api/ws` | 每 2 秒推送一次节点快照的 WebSocket | @@ -70,7 +70,7 @@ hub 1.3.0 及更早的版本不做这项检查,所以以前装得上的包, `metrics` 的三个查询参数都可以省: -- `hours=N`:窗口宽度,默认 6。匿名上限 168,登录后 2160,超出时静默收窄 +- `hours=N`:窗口宽度,默认 6,上限是 `/api/me` 的 `history_days` × 24,登录与匿名相同,超出时静默收窄 - `points=W`:图表能画下的点数,60–1440。只会让 hub 抽得更稀,不会更密 - `series=metrics|ping`:只取要画的那一类,另一类占响应的三分之一到三分之二 @@ -81,6 +81,24 @@ hub 1.3.0 及更早没有这两个 key。 延迟监控的名称在响应的 `probes` 里随数据一起返回,匿名可读,画延迟图不需要第二个请求,也不需要登录。 +### 时间范围 + +站长在面板里设的保留天数就是能画多远,`/api/me` 里的 `history_days`(1–365)给出这个数。时间范围的按钮 +按它生成,不要写死:写死的「30 天」遇上只保留 7 天的 hub,会被静默收窄成 7 天,按钮上却还写着 30 天。 + +```ts +// 默认主题的做法:小于保留期的整档位,最后加上保留期本身 +const WINDOWS = [1, 6, 24, 168, 720, 2160] +const whole = history_days * 24 +const hours = [...WINDOWS.filter((h) => h < whole), whole] +``` + +hub 1.3.1 及更早没有 `history_days`,这时按 7 天处理:那些版本匿名最多只给 168 小时。 + +7 天以内的窗口来自每分钟一行的明细,更宽的来自小时汇总,每个点至少一小时。一行的含义不变:资源仍是这段 +时间的平均值和峰值,延迟的 `loss` 和 `band` 是精确的,`latency` 在一个点跨多个小时时是各小时中位数按答上 +来的次数加权后的中位数。 + `ping` 里的记录按站长在面板上排的监控顺序逐个排列,同一个监控的记录按时间先后。按 `task_id` 第一次出现的 顺序生成曲线,图例和配色就和面板一致。hub 1.3.0 及更早按时间先后排,监控之间谁先谁后不固定。 From 3b23566a436ca688759ff8f97be37f11a0c1aea7 Mon Sep 17 00:00:00 2001 From: stqfdyr <89149493+stqfdyr@users.noreply.github.com> Date: Tue, 29 Sep 2026 14:32:26 +0800 Subject: [PATCH 2/7] =?UTF-8?q?docs:=20=E5=AF=BC=E5=85=A5=E5=A4=87?= =?UTF-8?q?=E4=BB=BD=E7=9A=84=E4=B8=8A=E9=99=90=E6=94=B9=E4=B8=BA=201=20Gi?= =?UTF-8?q?B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/content/config/data.mdx | 2 +- src/content/install/reverse-proxy.mdx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/content/config/data.mdx b/src/content/config/data.mdx index 0801ffa..71b594a 100644 --- a/src/content/config/data.mdx +++ b/src/content/config/data.mdx @@ -30,7 +30,7 @@ hub 的全部数据在一个 SQLite 文件里:一键脚本部署是 `/opt/moni **导入备份**用备份文件整体替换当前数据:节点、设置、历史、密码都换成备份里的。 -- 文件先完整上传、校验通过才替换,最大 256 MiB;校验不通过时当前数据不变 +- 文件先完整上传、校验通过才替换,最大 1 GiB;校验不通过时当前数据不变 - 旧版本 hub 导出的备份可以导入新版本,反过来不行,要先升级 - 导入后所有登录会话失效,执行导入的这个浏览器会拿到新会话;在线的 agent 自动重连 - 反代要放行 8 MiB 的请求体,见[反向代理](/install/reverse-proxy#2-请求体上限-8-mib) diff --git a/src/content/install/reverse-proxy.mdx b/src/content/install/reverse-proxy.mdx index 36241ca..9fa54f8 100644 --- a/src/content/install/reverse-proxy.mdx +++ b/src/content/install/reverse-proxy.mdx @@ -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`。 From 6b2f43ed218074c78cd555098ce994d0b28e52cb Mon Sep 17 00:00:00 2001 From: stqfdyr <89149493+stqfdyr@users.noreply.github.com> Date: Wed, 30 Sep 2026 18:35:31 +0800 Subject: [PATCH 3/7] =?UTF-8?q?docs:=20=E5=8D=87=E7=BA=A7=E5=90=8E?= =?UTF-8?q?=E6=B1=87=E6=80=BB=E6=9C=9F=E9=97=B4=E8=B6=85=E8=BF=87=207=20?= =?UTF-8?q?=E5=A4=A9=E7=9A=84=E5=9B=BE=E8=A1=A8=E7=BC=BA=E4=B8=80=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/content/config/data.mdx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/content/config/data.mdx b/src/content/config/data.mdx index 71b594a..21f249a 100644 --- a/src/content/config/data.mdx +++ b/src/content/config/data.mdx @@ -14,7 +14,8 @@ hub 的全部数据在一个 SQLite 文件里:一键脚本部署是 `/opt/moni 累计流量不受影响:总流量和月流量是独立的累计值,不是从历史算出来的,调小保留天数只会让图表变短。 从 hub 1.3.1 及更早版本升级后,hub 启动时把 7 天以前的分钟明细汇总成小时数据再删掉,明细多时要几分钟, -期间面板照常可用。删掉的明细不会让文件自己变小,过几分钟在**数据**页点一次**回收空间**即可。 +期间面板照常可用,超过 7 天的图表中间会缺一段,汇总完就补上。删掉的明细不会让文件自己变小,过几分钟在 +**数据**页点一次**回收空间**即可。 ## 回收空间 From 2c8d91b442ba92ff31ae183a1c8bd9c0345616a8 Mon Sep 17 00:00:00 2001 From: stqfdyr <89149493+stqfdyr@users.noreply.github.com> Date: Wed, 30 Sep 2026 19:05:42 +0800 Subject: [PATCH 4/7] =?UTF-8?q?docs:=20=E9=BB=98=E8=AE=A4=E4=BF=9D?= =?UTF-8?q?=E7=95=99=E5=A4=A9=E6=95=B0=E6=94=B9=E4=B8=BA=2030=20=E5=A4=A9?= =?UTF-8?q?=EF=BC=9B=E6=A1=A3=E4=BD=8D=E7=A4=BA=E4=BE=8B=E4=B8=8D=E5=8D=95?= =?UTF-8?q?=E5=88=97=E7=B4=A7=E6=8C=A8=E4=BF=9D=E7=95=99=E6=9C=9F=E7=9A=84?= =?UTF-8?q?=E6=95=B4=E6=A1=A3=E4=BD=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/content/config/data.mdx | 8 ++++---- src/content/dev/theme.mdx | 6 ++++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/content/config/data.mdx b/src/content/config/data.mdx index 21f249a..aab7cef 100644 --- a/src/content/config/data.mdx +++ b/src/content/config/data.mdx @@ -3,13 +3,13 @@ hub 的全部数据在一个 SQLite 文件里:一键脚本部署是 `/opt/moni ## 保留天数 -**设置**页的**历史数据保留天数**(1–365,默认 90)决定图表最远能看多少天,hub 每个整点清理超出的部分。 +**设置**页的**历史数据保留天数**(1–365,默认 30)决定图表最远能看多少天,hub 每个整点清理超出的部分。 历史分两层保存:最近 7 天按分钟,更早的按小时汇总。超过一周的图表上,按分钟和按小时画出来几乎一样, -按小时存只占几十分之一的空间。100 台节点、每台 4 个每分钟一次的延迟监控,保留 90 天约 150 MiB,保留 -一年约 240 MiB。 +按小时存只占几十分之一的空间。100 台节点、每台 4 个每分钟一次的延迟监控,保留 30 天约 110 MiB,90 天约 +150 MiB,一年约 240 MiB。 -推荐 90 天,月付、季付的机器都能看完一整个周期;年付的机器想回看整整一年,填 365。 +默认 30 天,能看约一个月的历史;季付的机器想看完整个周期,填 92;年付的机器想回看整整一年,填 365。 累计流量不受影响:总流量和月流量是独立的累计值,不是从历史算出来的,调小保留天数只会让图表变短。 diff --git a/src/content/dev/theme.mdx b/src/content/dev/theme.mdx index 1ec7505..6638095 100644 --- a/src/content/dev/theme.mdx +++ b/src/content/dev/theme.mdx @@ -87,10 +87,12 @@ hub 1.3.0 及更早没有这两个 key。 按它生成,不要写死:写死的「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 < whole), whole] +const hours = [...WINDOWS.filter((h) => h * 1.25 <= whole), whole] ``` hub 1.3.1 及更早没有 `history_days`,这时按 7 天处理:那些版本匿名最多只给 168 小时。 From c74aa9c3ff0228920277dd749197eeb30acd7994 Mon Sep 17 00:00:00 2001 From: stqfdyr <89149493+stqfdyr@users.noreply.github.com> Date: Wed, 30 Sep 2026 19:25:06 +0800 Subject: [PATCH 5/7] =?UTF-8?q?docs:=20=E4=BF=9D=E7=95=99=E5=A4=A9?= =?UTF-8?q?=E6=95=B0=E7=9A=84=E8=AF=B4=E6=98=8E=E6=94=B9=E4=B8=BA=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=2030=20=E5=A4=A9=E3=80=81=E4=B8=8A=E9=99=90=20365=20?= =?UTF-8?q?=E5=A4=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/content/config/data.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/config/data.mdx b/src/content/config/data.mdx index aab7cef..281da9b 100644 --- a/src/content/config/data.mdx +++ b/src/content/config/data.mdx @@ -9,7 +9,7 @@ hub 的全部数据在一个 SQLite 文件里:一键脚本部署是 `/opt/moni 按小时存只占几十分之一的空间。100 台节点、每台 4 个每分钟一次的延迟监控,保留 30 天约 110 MiB,90 天约 150 MiB,一年约 240 MiB。 -默认 30 天,能看约一个月的历史;季付的机器想看完整个周期,填 92;年付的机器想回看整整一年,填 365。 +默认 30 天,能看约一个月的历史,上限 365 天。 累计流量不受影响:总流量和月流量是独立的累计值,不是从历史算出来的,调小保留天数只会让图表变短。 From 151462a63e255848de8fe9dc54653188b1093cad Mon Sep 17 00:00:00 2001 From: stqfdyr <89149493+stqfdyr@users.noreply.github.com> Date: Wed, 30 Sep 2026 20:46:36 +0800 Subject: [PATCH 6/7] =?UTF-8?q?docs:=20=E5=8E=86=E5=8F=B2=E6=8C=87?= =?UTF-8?q?=E6=A0=87=E7=9A=84=20cpu=5Fmax=20=E4=B8=8E=20minutes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/content/dev/theme.mdx | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/content/dev/theme.mdx b/src/content/dev/theme.mdx index 6638095..e83c74c 100644 --- a/src/content/dev/theme.mdx +++ b/src/content/dev/theme.mdx @@ -74,10 +74,17 @@ hub 1.3.0 及更早的版本不做这项检查,所以以前装得上的包, - `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 每次连上的第一分钟不单独 + 记一行,所以算出的在线率会比实际略低 + +hub 1.3.0 及更早没有 `net_rx_max` / `net_tx_max`,1.3.1 及更早没有 `cpu_max` 和 `minutes`。 延迟监控的名称在响应的 `probes` 里随数据一起返回,匿名可读,画延迟图不需要第二个请求,也不需要登录。 From d5346e60930f90cae8529476be0f55bb8f17991f Mon Sep 17 00:00:00 2001 From: stqfdyr <89149493+stqfdyr@users.noreply.github.com> Date: Thu, 1 Oct 2026 11:58:17 +0800 Subject: [PATCH 7/7] =?UTF-8?q?docs:=20=E4=B8=8A=E6=8A=A5=E9=97=B4?= =?UTF-8?q?=E9=9A=94=E8=B6=85=E8=BF=87=2060=20=E7=A7=92=E6=97=B6=20minutes?= =?UTF-8?q?=20=E6=8C=89=E6=AF=94=E4=BE=8B=E5=81=8F=E5=B0=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/content/dev/theme.mdx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/content/dev/theme.mdx b/src/content/dev/theme.mdx index e83c74c..39fef38 100644 --- a/src/content/dev/theme.mdx +++ b/src/content/dev/theme.mdx @@ -83,6 +83,9 @@ hub 1.3.0 及更早的版本不做这项检查,所以以前装得上的包, 到过多高就读这几个 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`。