Skip to main content
今日目标:Week 5 是整个 30 天计划的终局之战。我们将模拟一个真实的互联网大厂需求,从 0 开始设计并实现一个 Master-Agent 架构 的监控系统。今天不写代码,而是要像架构师一样思考。我们要彻底理解 “为什么要用 Master-Agent 架构”“Push vs Pull 模型区别” 以及 “如何设计高性能的时序数据表”

学习内容 (30 mins)

在开始写代码前,先搞懂这些核心概念,否则你的系统一上线就会崩。
为什么不直接 SSH 上去查?
  • SSH 方案: 慢,难以并行,且保存 SSH Key 有极大的安全隐患。
  • Master-Agent 方案:
    • Master (大脑): 集中管理数据,提供 API。
    • Agent (触手): 部署在每台机器上,只负责采集和上报。
  • 优势:
    1. 解耦: 业务机器不需要知道 Master 的逻辑,由于 Agent 极轻量,即便挂了也不影响业务。
    2. 安全: Agent 不需要开放端口(只出不进),利用 Outbound HTTP 连接,无需在防火墙打洞。
谁主动?
  • Pull 模型 (Prometheus): Master 主动去连 Agent 抓数据。
    • 优点:Master 控制全局,知道谁挂了。
    • 缺点:Agent 必须有公网 IP 或在同一内网,且需要开放端口。
  • Push 模型 (Our Project): Agent 主动把数据发给 Master。
    • 优点:内网穿透。Agent 在深层子网也能报数据,只要能访问公网 Master 即可。
    • 缺点:Master 不知道 Agent 是死是活(需要心跳机制补充)。
  • 结论: 对于混合云环境(阿里云+腾讯云+办公室物理机),Push 模型更合适。
监控数据的特点:
  • 写多读少: 每秒都有成千上万个点写入。
  • 时间敏感: 我们只关心“最近 1 小时”或“最近 24 小时”。
  • 索引策略: 必须在 created_at 上建索引,否则查询 Top N 时会全表扫描。

设计任务 (90 mins)

1

任务 A: 数据库建模 (MySQL)

我们需要一张能够支撑快速写入和按时间排序的表结构。
-- 1. 创建专用数据库
-- 使用 utf8mb4 字符集以支持更多字符(虽然监控数据主要是数字)
CREATE DATABASE IF NOT EXISTS monitor_system CHARACTER SET utf8mb4;

USE monitor_system;

-- 2. 创建指标表
-- 这是一个典型的“时序数据”表 design
CREATE TABLE IF NOT EXISTS server_metrics (
    -- 主键:自增 ID,大数据量下建议使用 BIGINT
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    
    -- 维度字段:用于定位是谁报的数据
    hostname VARCHAR(64) NOT NULL COMMENT '主机名',
    ip_address VARCHAR(15) NOT NULL COMMENT '内网IP',
    
    -- 指标字段:核心监控数值
    -- 使用 FLOAT 存储百分比 (0.0 - 100.0)
    -- 为什么不用 DECIMAL?监控数据允许轻微精度损失,FLOAT 更省空间
    cpu_usage FLOAT NOT NULL COMMENT 'CPU使用率%',
    mem_usage FLOAT NOT NULL COMMENT '内存使用率%',
    disk_usage FLOAT NOT NULL COMMENT '磁盘使用率%',
    
    -- 时间字段:数据的生命线
    -- DEFAULT CURRENT_TIMESTAMP 让数据库自动打标
    reported_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    
    -- 复合索引:加速查询
    -- 场景:查询 hostname='web-01' 在 '2023-10-01' 之后的数据
    INDEX idx_host_time (hostname, reported_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='服务器监控指标流水表';
代码解释
  • BIGINT UNSIGNED:大数据量下使用 BIGINT,避免 INT 溢出
  • FLOAT vs DECIMAL:监控数据允许精度损失,FLOAT 更省空间
  • INDEX idx_host_time:复合索引,加速按主机和时间查询
  • DEFAULT CURRENT_TIMESTAMP:数据库自动打时间戳
时序数据库的设计哲学
  • 写多读少:优化写入性能,索引只建在查询字段上
  • 时间分区:大数据量下按月分表,或定期清理旧数据
  • 维度+指标:hostname 是维度,cpu/mem/disk 是指标
设计思考
  • 为什么不把 hostname 设为主键? -> 因为每个主机每分钟都会上报多次,hostname 是重复的。它是”维度”,不是”主键”。
  • 数据会爆炸吗? -> 会。100 台机器,每 5 秒一条,一天就是 100 * 12 * 60 * 24 = 1,728,000 条。生产环境通常会按月分表,或使用定期清理脚本。
验证步骤:
  1. 进入 MySQL 容器:docker exec -it mysql-learn mysql -uroot -proot
  2. 粘贴 SQL 执行。
  3. DESCRIBE monitor_system.server_metrics; 确认结构无误。
2

任务 B: API 契约定义 (JSON)

Master 和 Agent 必须由统一的语言。即使还没写代码,先把 JSON 格式定死,前后端(以及 Go/Python)就能并行开发了。
// POST /api/v1/report 的请求体 (Request Body)
{
  "hostname": "prod-api-01",
  "ip": "10.0.1.5",
  "cpu": 45.2,   // 约定:必须是 0-100 之间的浮点数
  "mem": 60.8,
  "disk": 80.1
}
常见错误
  • 字段类型歧义: Agent 传了字符串 "45.2%",而 Master 期待的是数字 45.2。这会导致解析失败。
  • 空指针风险: 如果 disk 采集失败了,是传 0 还是 null?这里我们约定:必须传数字,如果采集失败,Agent 需自行处理(如填 -1 或 上次的值)。
3

任务 C: 工程目录规划

一个好的目录结构是成功的开始。我们将创建标准的“多语言混合项目”结构。
~/final-project/
├── README.md           # 项目总说明
├── docker-compose.yaml # 整体编排
├── master/             # Python 控制面
   ├── main.py
   ├── models.py
   ├── schemas.py
   ├── requirements.txt
   └── Dockerfile
├── agent/              # Go 数据面
   ├── main.go
   ├── go.mod
   └── go.sum
└── scripts/            # 辅助脚本
    └── init_db.sql
验证步骤:
  1. 执行 mkdir -p ~/final-project/{master,agent,scripts}
  2. touch ~/final-project/docker-compose.yaml
  3. 把刚才的 SQL 保存为 scripts/init_db.sql

拓展任务 (30 mins)

鉴权挑战

思考:现在 API 是公网裸奔的。任何知道 URL 的人都可以伪造数据 POST 给你。任务:设计一个简单的 Authorization 机制。
  • 方案:Master 在环境变量设置 AGENT_SECRET=xyz。Agent 发送请求时在 Header 带上 X-Token: xyz。Master 校验不通过则返回 403。

高可用思考

思考:如果 Master 挂了,Agent 应该怎么办?任务:设计 Agent 的重试策略。
  • 方案:Agent 应该有一个内存 Buffer(比如存最近 10 条)。如果发送失败,先存 Buffer,等 Master 恢复了一次性发过去。

今日产出物

  • scripts/init_db.sql - 数据库初始化脚本
  • README.md (Draft) - 包含 API 格式说明
  • 完整的项目骨架目录

参考资源

OpenAPI 规范

了解为什么我们要先定义 JSON 格式

Google SRE Book

Google 对分布式监控系统的经典论述

实际应用场景

Zabbix vs Prometheus

  • Zabbix: 传统老牌,擅长 Push 模式,适合物理机、网络设备监控。我们做的这个项目更像 Zabbix 的简化版。
  • Prometheus: 云原生标配,擅长 Pull 模式,适合 K8s 动态环境。
Next Step: 设计图纸已画好。明天(Day 30 Pt.1)我们将戴上安全帽,先把 Master (大脑) 搭建起来。请确保你的 Python 环境就绪。

回到目录

查看完整进度

下一阶段: Master 开发

Day 30 Pt.1 | Master 服务开发