NodeGet 的 agent 也是常驻进程(Rust 二进制,12.5 MB RSS),不是真正的 cron 模式。
NodeGet agent 真实工作方式
NodeGet Server (cron 调度) ──WebSocket──► nodeget-agent (常驻) ──fork──► bash (执行 ping)
| 层级 | 角色 | 常驻/瞬时 |
|---|---|---|
| Server (容器) | cron 调度器,每 10 分钟派发任务 | 常驻 36 MB |
| agent (各 VPS) | WebSocket 常驻连接,接收任务 | 常驻 12.5 MB |
| bash (子进程) | 执行 ping/tcp_ping 命令 | 瞬时 8 MB, 7% CPU |
瞬时压力对比 (执行任务时)
| 指标 | monitor-probe agent | NodeGet agent | Beszel agent | Komari agent |
|---|---|---|---|---|
| 常驻 RSS | 1.7 MB | 12.5 MB | \~15 MB | \~12 MB |
| 常驻 CPU | 0.1% | 1.1% | \~0.1% | \~0.1% |
| 执行任务时额外 RSS | 0 (自身执行) | +8 MB (fork bash) | 0 (自身执行) | 0 (自身执行) |
| 执行任务时 CPU | <1% | 5-10% (bash + ping) | <1% | <1% |
| 任务执行方式 | 原生 Rust,直接 connect() | fork bash 执行 ping 命令 | Go 原生,直接系统调用 | Go 原生,直接系统调用 |
NodeGet 瞬时压力大的原因
monitor-probe: agent ──tcp_connect()──► 目标:80 (一次系统调用, <1ms)
NodeGet: agent ──fork()──► bash ──exec ping──► 目标
│ │
▼ ▼
8 MB 额外 5-10% CPU
内存分配 进程创建 + 命令解释
- fork bash:每个任务派发时,agent fork 一个 bash 子进程(8 MB RSS, 7% CPU)
- 执行 ping 命令:bash 再 exec
ping/curl/tcptraceroute,又是额外开销 - WebSocket 长连接:agent 与 server 保持 WebSocket,空闲时也有 1.1% CPU(心跳/重连逻辑)
- 无连接复用:每次任务独立 fork,不像 monitor-probe 可以复用 TCP 连接
20 节点任务执行时的总压力
| 场景 | monitor-probe | NodeGet |
|---|---|---|
| 空闲时 | 20 × 0.1% = 2% CPU | 20 × 1.1% = 22% CPU |
| 执行任务时(每 10 分钟) | 20 × 1% = 20% CPU | 20 × (1.1% + 7%) = 162% CPU 峰值 |
| 执行频率 | 每 60 秒一次 | 每 10 分钟一次(但集中爆发) |
| 单次执行耗时 | <1 ms | 5-30 ms(fork + bash + ping) |
NodeGet 的真正问题不是常驻内存(12.5 MB 可接受),而是:
- fork 模式:每次任务 fork bash,进程创建开销大
- 集中爆发:36 个 cron 任务分散在不同秒数,但每个任务会同时派发给 11 个 agent,瞬间产生 11 个 bash 子进程
- WebSocket 长连接开销:agent 侧 1.1% CPU 偏高(monitor-probe 仅 0.1%),可能是重连/心跳逻辑不够高效
monitor-probe 的优势:原生 Rust 直接执行 TCP connect,无 fork,无子进程,单次探测 <1ms,常驻 CPU 0.1%。
实测数据齐了。以下是完整对比:
综合对比表
| 维度 | monitor-probe | NodeGet | Beszel | Komari | Prometheus |
|---|---|---|---|---|---|
| Agent 语言 | Rust | Python (cron) | Go | Go | Go (node_exporter) |
| Agent RSS | 0.6 MB | — (cron 瞬时) | \~15 MB | \~12 MB | \~20 MB |
| Agent CPU | 0.1% | 0 (cron 模式) | \~0.1% | \~0.1% | \~0% (pull 模式) |
| Hub/Server 语言 | Rust (axum) | PHP-FPM | Go | Go | Go |
| Hub RSS | 8.8 MB | 36 MB (容器) | \~30 MB | \~25 MB | 200-1000 MB |
| Hub CPU | 0.1% | 1.1% | \~0.2% | \~0.2% | 5-20% |
| 数据库 | SQLite | SQLite | SQLite / PG | SQLite / PG | TSDB (自定义) |
| DB 大小 (实测) | 304 KB (3节点×2h) | 556 MB (11节点) | — | — | — |
| DB 大小 (20节点×90天) | \~3 GB | \~10 GB¹ | \~2-4 GB | \~2-4 GB | \~1-2 GB² |
| 探测间隔 | 60 秒 | 600 秒 | 60 秒 | 60 秒 | 15-60 秒 (scrape) |
| 数据模型 | 行存 (SQL) | 行存 (SQL) | 行存 (SQL) | 行存 (SQL) | 列存 (TSDB) |
| 保留策略 | 自动 prune | 手动清理 | 自动 | 自动 | 自动 (retention) |
| 告警 | Telegram/Webhook | Telegram | Discord/Telegram | 内置 | Alertmanager |
| 公开页 | ✅ 主题可换 | ❌ 无 | ✅ | ✅ | ❌ (Grafana 外接) |
¹ NodeGet 10 分钟间隔但 DB 仍大,因为历史数据积累多 + 表结构未优化
² Prometheus TSDB 压缩率高,相同数据量约为 SQLite 的 1/3
关键差异
1. 资源开销 (从小到大)
monitor-probe < Beszel ≈ Komari < NodeGet << Prometheus
- monitor-probe 最小:Rust 编译的原生二进制,agent 仅 0.6 MB RSS,hub 8.8 MB
- Beszel/Komari 接近:Go 二进制,agent \~15 MB,hub \~30 MB
- NodeGet 中等:PHP-FPM 容器 36 MB,但 cron 模式 agent 不占常驻内存
- Prometheus 最大:server 端 RAM 可达数百 MB 到 GB 级别(取决于指标基数),且需要 Grafana 做可视化
2. 存储效率
Prometheus TSDB > monitor-probe SQLite > Beszel/Komari SQLite > NodeGet SQLite
- Prometheus TSDB 列式压缩,效率最高,但查询语言 (PromQL) 学习曲线陡
- monitor-probe SQLite 行存但 WITHOUT ROWID 优化,30 天 3 GB 可接受
NodeGet SQLite 556 MB 已膨胀,因为:
- 无自动 prune(用户没配置清理)
- 表结构含冗余字段
- 10 分钟间隔 × 11 节点 × 多目标,长期积累
3. 数据库区别
| 特性 | SQLite (monitor-probe/Beszel/Komari) | TSDB (Prometheus) |
|---|---|---|
| 类型 | 嵌入式关系库 | 自定义时序引擎 |
| 查询 | SQL (灵活) | PromQL (专精时序) |
| 压缩 | 无(页级) | 有( Gorilla 压缩,\~1.3 bytes/sample) |
| 高可用 | 单机 | 单机(HA 需 Thanos/Cortex) |
| 运维 | 零配置,单文件备份 | 需管理 WAL、块、压缩 |
| 适合 | < 100 节点,< 10 GB | 大规模集群,高基数指标 |
结论
monitor-probe 在中小规模 (20-50 节点) 是最优选择:
- 资源开销最低(agent 0.6 MB, hub 8.8 MB)
- SQLite 零运维,单文件备份/迁移
- 公开页 + 主题系统开箱即用
- 90 天保留仅 3 GB
Prometheus 更适合:大规模集群(100+ 节点)、需要复杂告警路由、已有 Grafana 生态。
NodeGet 已落后:DB 膨胀到 556 MB、无自动 prune、10 分钟间隔精度不足。