Files
mfd-monitor-agent/docs/ARCHITECTURE.md
codex de3fd88948 ✨ feat(agent): 添加 token 鉴权和流程文档
* 默认监听调整为 0.0.0.0:8080,并要求查询参数 token
* 支持首次 run 自动生成含随机 token 的配置文件
* 补充 HTTP 鉴权、配置校验和相关测试
* 完善代码注释,覆盖缓存、上报、服务和平台采集路径
* 新增架构与开发流程文档,补充一键构建脚本
2026-05-22 06:46:21 +00:00

173 lines
6.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# MFD Monitor Agent 架构与工作流程
本文档汇总当前代码中的实际运行流程,供开发、排障和评审时快速理解 agent 如何从配置加载到采集、缓存、查询、上报和服务化运行。
## 进程职责
MFD Monitor Agent 采用单进程一体化架构。一个 agent 进程同时负责:
- 周期采集主机状态
- 保存最近一次 `HostStatus` 内存缓存
- 提供本地 HTTP API
- 可选地向中心端主动 POST 上报
- 执行 Linux/Windows 服务安装、启动、停止和卸载命令
HTTP 查询与主动上报读取同一份缓存,不在请求路径上触发实时系统扫描。
## 包职责
| 包 | 职责 |
|----|------|
| `cmd/agent` | CLI 分发、配置加载、进程生命周期、HTTP server 启停 |
| `internal/config` | 默认配置、JSON 读取、首次配置生成、环境变量覆盖、配置校验 |
| `internal/status` | `/status` 与主动上报共用的 `HostStatus` JSON 数据模型 |
| `internal/collector` | 平台相关主机、网络、资源、进程、TCP 监听采集 |
| `internal/snapshot` | 子采集器聚合、partial 错误记录、并发安全缓存 |
| `internal/httpapi` | `GET /health` 与 `GET /status`,查询参数 token 鉴权 |
| `internal/reporter` | 周期性 POST 缓存快照,失败重试与日志记录 |
| `internal/service` | Linux systemd 与 Windows SCM 服务生命周期封装 |
## 启动与生命周期
`agent` 无参数时等价于 `agent run`。
`agent run [-config config.json]` 流程:
1. 解析 `-config`,未指定时使用当前工作目录 `config.json`。
2. 调用 `config.LoadOrCreate`。配置不存在时创建默认 JSON 并生成随机 `http.token`。
3. 创建 `snapshot.Cache`,启动后台采集循环。
4. 若 `report.enabled=true`,启动主动上报循环。
5. 启动 HTTP server,默认监听 `0.0.0.0:8080`。
6. 收到 `SIGINT` 或 `SIGTERM` 后优雅关闭 HTTP server。
服务命令 `install`、`uninstall`、`start`、`stop` 使用 `config.Load` 读取已有配置,不会自动创建配置文件。
## 配置加载流程
配置来源按以下顺序生效:
1. `config.Default()` 提供默认值。
2. JSON 文件覆盖默认值。
3. `MFD_AGENT_*` 环境变量覆盖 JSON。
4. `validate` 校验安全和必填项。
关键规则:
- `http.token` 必填;`agent run` 首次生成配置时会自动写入随机 token。
- `report.enabled=true` 时 `report.endpoint` 必填。
- 自动生成的配置文件权限为 `0600`,因为其中包含 API token。
- 非法布尔或时长环境变量会被忽略,保留文件中的原值。
## 采集与缓存流程
`snapshot.Cache.Run` 启动后立即采集一次,随后按 `collect.interval` 周期刷新。
每轮采集流程:
1. 用 `collect.timeout` 创建整体超时 context。
2. 构造新的 `HostStatus`,默认 `agent.snapshot_status=ok`。
3. 依次执行 `system`、`network`、`resource`、`process`、`socket` 采集器。
4. 子采集器失败时记录到 `errors[]`,整份快照降级为 `partial`,其他字段继续保留。
5. 用锁一次性发布最新快照,供 HTTP 与 reporter 并发读取。
`processes.status` 与 `tcp_listeners.status` 支持 `ok`、`partial`、`error`。例如 Linux 读取 `/proc/<pid>/fd` 权限不足时,TCP 端口仍会返回,但进程映射可能不完整并标记为 `partial`。
## HTTP 查询流程
所有 API 都要求查询参数 token:
```text
GET /health?token=<http.token>
GET /status?token=<http.token>
```
处理流程:
1. `withQueryTokenAuth` 使用恒定时间比较校验 token。
2. token 缺失、错误或配置 token 为空时返回 `401`。
3. 非 `GET` 方法返回 `405`。
4. `/health` 读取缓存元数据。首次快照未就绪时返回 `503` 和 `{"status":"starting"}`。
5. `/status` 返回完整缓存 `HostStatus`。首次快照未就绪时返回 `503`。
HTTP 请求不会触发采集,避免高并发查询放大系统扫描成本。
## 主动上报流程
启用条件:
```json
{
"report": {
"enabled": true,
"endpoint": "http://center.example.internal/agent/status"
}
}
```
运行流程:
1. `reporter.Run` 按 `report.interval` 定时执行。
2. 从 `snapshot.Cache` 读取最新 `HostStatus`。
3. 首次快照未就绪时跳过本轮。
4. 以 `application/json` POST 到 `report.endpoint`。
5. 非 2xx、网络错误或超时视为失败。
6. 失败后等待短暂退避并重试一次。
7. 最终失败只记录日志,不影响采集循环或本地 HTTP 服务。
上报载荷与 `/status` 响应结构完全一致。
## 服务生命周期流程
### Linux systemd
`agent install -config /path/config.json -exe /path/agent`:
1. 检查当前用户必须为 root。
2. 生成 `/etc/systemd/system/<service.name>.service`。
3. `ExecStart` 写入 `<exe> run -config <path>`。
4. 执行 `systemctl daemon-reload`。
5. 执行 `systemctl enable <service.name>`。
`start`、`stop` 调用 `systemctl start/stop`。`uninstall` 尽力 `disable --now`,删除 unit 文件后再次 `daemon-reload`。
### Windows SCM
Windows 通过 `sc.exe` 管理服务,不依赖 NSSM。
`install` 使用 `sc.exe create` 注册自动启动服务,`binPath` 为:
```text
"<exe>" run -config "<config>"
```
`start`、`stop`、`uninstall` 分别调用 `sc.exe start`、`sc.exe stop`、`sc.exe delete`。安装、删除和启停通常需要管理员权限。
## HostStatus 数据模型
`HostStatus` 是唯一对外状态模型,同时用于:
- `GET /status` 响应体
- 主动上报 POST body
- 测试中的快照断言
顶层字段包括:
- `agent`:版本、启动时间、快照时间、快照状态
- `host`:机器标识、主机名、平台、架构、运行时长
- `network`:网卡明细、IPv4/IPv6、MAC
- `cpu`:逻辑核心、物理核心、使用率、负载、型号
- `memory`:内存容量与使用率
- `disks`:文件系统容量与使用率
- `processes`:采集状态与完整进程列表
- `tcp_listeners`:采集状态与 TCP 监听端口到进程映射
- `errors`:子采集器失败原因
## 平台差异
Linux 采集主要读取 `/proc`、`/etc/os-release`、`net.Interfaces` 和 `statfs`。进程与 socket 映射受 `/proc/<pid>` 权限和进程生命周期竞争影响。
Windows 采集使用 Win32 API、Toolhelp、注册表、PSAPI、iphlpapi 和一次尽力 WMIC 命令。部分字段需要高权限读取进程句柄或令牌,失败时降级为空字段或 `partial`。
非 Linux/Windows 平台保留基础主机和网络采集,进程与 TCP 监听采集明确返回不支持并标记 `partial`。