上一篇:00 导读与环境准备 | 目录:README | 下一篇:02 系统设计
写代码之前,先把"我要做一个监控平台"这句话翻译成一张能指导开发的清单。 这一篇不写一行代码,但它决定了后面 11 篇代码的质量——需求想不清,代码全是还债。
一、从一个具体的痛点出发
所有监控平台的起点都不是"我要做个平台",而是一个具体的、扎心的场景:
论坛页偶发卡死,CPU 打到 100%。你登上服务器 top 一看——Python 进程占满了。 是哪个接口?哪条 SQL?慢在哪?不知道。翻日志,每行都是正常输出,没有报错。 你只能重启,然后祈祷它别再犯。
这个场景里藏着四个能力缺口:
- 看不见:请求慢在哪一环(视图?SQL?渲染?)没有任何数据;
- 留不住:就算这次排查到一点线索,下一次是三天后,什么都没存下来;
- 不知道:CPU 飙了多久了?内存还剩多少?要不要今晚就得处理?没有全局水位;
- 等不起:出问题靠人肉刷页面才发现,半夜没人刷,就没有人知道。
把四个缺口反过来,就是监控平台的需求雏形:采集(看得见)→ 存储(留得住)→ 展示(知道水位)→ 告警(主动找你)。
二、可观测性:把"监控"升级成"能回答任何问题"
光采集 CPU 和接口耗时还不够。业界给这类系统起了个名字:可观测性(Observability), 它由三根支柱组成——这三个词后面会反复出现:
| 支柱 | 英文 | 回答的问题 | 在本项目里对应什么 |
|---|---|---|---|
| 指标 | Metrics | "现在/过去系统什么水位?"——聚合后的数字 | HostMetric、RequestMetric 聚合、指标注册表 |
| 追踪 | Tracing | "这一个请求慢在哪一环?"——一次请求的完整旅程 | trace_id + SQL/视图 span + 瀑布图 |
| 日志 | Logging | "当时具体发生了什么?"——逐条的原始记录 | LogEntry + 关键字检索 |
三根支柱要能互相串联才有价值:日志里看到 ERROR,能拿它的 trace_id 跳到调用链 看是哪个请求哪条 SQL 引起的——这是本项目贯穿始终的一条设计红线 (第 4 篇的 TraceID、第 7 篇的日志 trace_id 都在为它服务)。
前端还有第四路数据:RUM(Real User Monitoring,真实用户监控)—— 从访问者的浏览器里直接采集加载耗时和 JS 报错。服务端监控说"接口 50ms 返回了", RUM 能告诉你"用户看到内容用了 3 秒,因为图片没压"——两边的视角互补。
三、项目的来历:从单一工具到完整平台
Beacon Tower 的前身是一个 Django 性能监控与优化平台:一个故意埋了性能问题的论坛 (N+1 查询、无索引、全表加载),配一个 AST 静态诊断引擎,解决"论坛 CPU 100% 找不到原因" 这类单一问题。
但用起来很快发现:诊断只是"分析",完整的运维闭环缺了一大圈——
- 有接口耗时数据,但没有主机 CPU / 内存 / 磁盘水位 → 加主机监控;
- 数据只能本机采,别的服务器够不着 → 加自研 Agent + 多机接入;
- 出了异常要人盯着看 → 加告警引擎(策略 → 评估 → 事件 → 通知);
- 告警响了,是"真故障"还是"抖一下"?影响面多大?恢复没有?→ 加故障事件(故障单);
- 只有"出事才看"不够,日常体检靠什么?→ 加巡检中心 + SLO 错误预算;
- 用户端页面慢不慢,服务端根本不知道 → 加前端 RUM;
- 上面所有东西全靠盯页面?→ 加自定义大盘 + 报表中心;
- 故障处理完,那个已知的 N+1 还在论坛里躺着 → 保留并强化 AST 静态诊断 + 问题版/优化版对比压测。
把这些拼起来,就是对标腾讯云可观测平台模块形态的完整闭环。注意这个推演顺序: 每个模块都是被前一个模块的"缺口"逼出来的——你在 02 篇画架构图时,也应该按这个顺序想。
四、需求清单(功能范围)
把上面的推演落成清单。带 ★ 的是教程主线(逐篇展开),不带的是教程点到、 对照仓库补齐的部分(避免教程失焦)。
A. 数据采集层(一切的地基)
- ★ A1 请求计时中间件:每个请求记耗时/状态码/SQL 次数/慢查询,生成 TraceID,组装调用链 span;
- ★ A2 主机采集线程:psutil 每 15 秒采 CPU/内存/磁盘/网络/进程/连接数,写 HostMetric;
- ★ A3 日志自动接入:logging Handler 挂 root logger,WARNING 及以上自动入库,带 trace_id;
- ★ A4 前端 SDK rum.js:PV、页面性能(TTFB/FCP/LCP)、JS 异常、API 包装,sendBeacon 批量上报;
- ★ A5 多机 Agent:只依赖 psutil 的单文件脚本,推送
/api/ingest/host/,断网指数退避重试; - ★ A6 自定义指标 OpenAPI:
POST /api/ingest/metrics/,业务自己报数; - A7 拨测:黑盒探测 URL 可用性/延迟/证书到期(第 10 篇运维中心)。
B. 数据存储层
- ★ B1 模型设计:RequestMetric(含 spans JSON)/ HostMetric / LogEntry / RumEvent / CustomMetric / AlertPolicy / AlertEvent / DashCard / TaskLease;
- ★ B2 SQLite WAL:四条后台线程和请求线程并发读写,必须先解决写锁;
- ★ B3 数据保留策略:采集数据 7 天自动清理,分批删除避免长事务锁库。
C. 分析与展示层
- ★ C1 指标注册表:18 个内置指标的统一取数入口,总览/大盘/告警/智能分析共用;
- ★ C2 监控总览:KPI + 趋势 + 错误分布 + 服务健康表;
- ★ C3 APM 页:接口分析(量/耗时/P95/错误率/SQL)、调用链列表 + 瀑布图详情;
- ★ C4 数据库分析:按路径的 SQL 统计 + 慢查询模板归并;
- ★ C5 主机页:多主机下拉、CPU/内存/磁盘/网络曲线、Top 进程;
- ★ C6 日志查询页:关键字/级别/来源/trace_id 过滤、级别直方图;
- ★ C7 RUM 六个分析页:总览/页面性能/异常/API/资源/自定义;
- ★ C8 自定义大盘:从注册表选指标组卡片,ECharts 折线/面积/柱状;
- C9 IP 访问地图(省份热力,可插拔归属地解析);
- C10 性能诊断(AST 静态扫描 N+1/全表加载/无 limit)+ 问题版/优化版压测对比。
D. 智能分析层(全部纯标准库、可解释)
- ★ D1 滑动窗口 3σ 异常检测(输出偏离 σ 倍数);
- ★ D2 最小二乘线性趋势预测(输出斜率 + R²);
- ★ D3 皮尔逊相关性矩阵(7 个核心指标);
- ★ D4 日志模板聚类(数字/ID/IP 归一化后归并,输出错误模板 Top N)。
E. 告警闭环
- ★ E1 告警策略:任意注册表指标 + 比较符 + 阈值 + 级别(P0/P1/P2/提示);
- ★ E2 评估引擎:后台线程 30 秒一轮,取 5 分钟窗口均值;
- ★ E3 防抖与迟滞:for-duration(持续越限 N 分钟才触发)、恢复阈值(回到安全侧才恢复)、静默窗口;
- ★ E4 事件生命周期:firing → 确认 → resolved,触发与恢复各发通知;
- ★ E5 通知渠道:站内信 + 模拟 Webhook 内置,SMTP 邮件/企业微信/钉钉真实发送可配置。
F. 运维中心(教程概述 + 对照仓库)
- F1 拨测管理(probe.* 指标进告警引擎);F2 故障单:时间相近告警自动聚合 + MTTR 统计 + 复盘导出;
- F3 巡检中心:一键体检 + 磁盘/内存耗尽预测 + 每 12 小时自动巡检;F4 SLO 错误预算燃尽;
- F5 资产台账:Agent 主机自动登记;F6 自愈:白名单命令/清理临时目录/HTTP 回调 + 冷却期;
- F7 操作审计:策略变更/大盘编辑/自愈执行/登录成败全程留痕;
- F8 清理加速中心:磁盘分析、四类垃圾清理、内存整理(唯一"真删文件"的地方,安全边界单独讲)。
G. 工程化(第 11 篇)
- ★ G1 测试:125 个用例,覆盖算法/告警引擎/安全边界/缓冲/租约;
- ★ G2 ruff 静态检查;
- ★ G3 GitHub Actions CI:lint → check → migration 完整性 → 全量测试。
H. 部署(第 12 篇)
- ★ H1 一键脚本 start.sh(幂等:venv/依赖/迁移/演示数据/端口检查);
- ★ H2 Docker Compose 三角色:db(PostgreSQL)+ web(gunicorn)+ worker(后台任务,租约选主,可多副本);
- ★ H3 无 Docker 的 systemd 形态;
- ★ H4 生产安全清单:HTTPS Cookie/CSRF、可信反代 XFF、密钥不入镜像、非 root 容器。
五、非目标(明确不做什么)
需求清单里,"不做什么"和"做什么"同样重要,这是单人项目能做完的唯一办法:
- 不做分布式后端:单机线程 + SQLite 面向教学演示;生产形态就是 compose 三角色, 不引入 Kafka/ClickHouse/对象存储。数据规模(7 天保留 + 分批清理)刻意控制在单库能扛的范围;
- 不做 APM 字节码插桩:Java 系 agent 那种自动埋点工程量巨大,这里用 Django 中间件 +
force_debug_cursor拿到全量 SQL,一行配置生效,够用且可解释; - 不自研图表库:ECharts 本地托管,自研的是"数据怎么组织",不是"像素怎么画";
- 不做多租户:整站登录门禁定位是自用系统 + 一个只读演示组,不做 SaaS 的租户隔离;
- 不保证实时:采集走批量缓冲,指标可见延迟 ≤1 秒——用可量化的延迟换吞吐, 这是设计决策不是缺陷(05 篇详细算这笔账)。
六、关键成功指标(做完怎么算"成了")
| 指标 | 目标 | 教程位置 |
|---|---|---|
| 端到端闭环 | 制造故障(慢请求/错误/日志风暴/CPU 抬升)→ 30 秒内在 APM/日志/主机/告警四个模块看到联动反应 | 08、12 篇验证 |
| 采集不拖累业务 | 批量缓冲改造后业务请求 p99 从 2190ms → 251ms(16 线程闭环压测) | 05 篇 |
| 多副本安全 | worker 副本 ×3 时,同一任务全集群只有一个进程在跑;硬杀持有者 28 秒内接管 | 06、12 篇 |
| 安全底线 | 匿名写入 401、令牌只能写不能读、SQL 敏感字面量脱敏、SSRF 闸门、演示账号只读 | 06、10 篇 |
| 质量底线 | 125 个测试全绿;CI 四道闸门 | 11 篇 |
| 可复现性 | 安全设计、性能改造都有"方法 + 数据 + 复现步骤",结论可审计 | 各篇 |
七、用户与故事(用例驱动一次)
三个用户角色,每个都给两条核心用户故事,用来反推页面:
- 管理员(你): - "我打开首页 10 秒内判断出:系统整体健康吗?哪里最不健康?" → 总览页 KPI/健康表 + 触发中告警横幅; - "凌晨告警响了,我要在 3 分钟内定位根因。" → 告警事件页点 trace_id → 调用链瀑布图 → 慢 SQL 明细 → 日志上下文。
- 开发同事(只读展示): - "我想知道我的接口为什么慢,但不想碰任何配置。" → 只读账号能看到 APM/日志/分析全部查询页,但所有 POST 写操作 403(第 10 篇讲实现);
- 运维同事: - "把这两台新服务器接进来,我不想装任何复杂的东西。" → Agent 单文件 + 三个环境变量(第 6 篇); - "磁盘还剩 5%,给我个耗尽预测和处理办法。" → 巡检中心的容量耗尽预测 + 清理加速中心。
把这三组故事贴在显眼处——后面 11 篇里每一个"要不要做这个功能"的犹豫, 都拿它们来裁决。
八、技术选型的"为什么"(分析阶段的结论)
选型不是填表格,是把约束讲清楚之后的自然结果:
- Django 而不是 Flask/FastAPI:这个项目 80% 是"ORM 增删改查 + 模板渲染 + 后台线程", Django 的 auth(整站门禁)、ORM(聚合查询)、admin(数据兜底管理)、migrations(模型演进) 全部开箱即用。FastAPI 的强项是 async API 服务,本项目恰恰不是;
- SQLite 起步、PostgreSQL 一键切换:演示零配置是"小白能跑起来"的生死线;
同时在 settings 里留了
OBS_DATABASE_URL,生产切 PostgreSQL 不改一行代码。 SQLite 的单写者锁是真实约束,项目为此做了 WAL + 批量缓冲 + 分批删除三件事—— 这反过来成了最好的教学内容; - psutil 是唯一"硬依赖":采集端未安装自动降级为模拟指标,保证任何环境都能先把平台跑起来;
- 前端不上框架:页面 = 模板 + ECharts + 原生 JS。引入 Vue/React 意味着构建链、 node_modules 和前后端联调,对单人教学的性价比为负;
- 算法手写:3σ/最小二乘/皮尔逊/模板聚类都是 20~50 行的标准库函数, 手写让"每个结论可回溯"成为可能,也是面试时最出细节的部分。
本篇检查点
- [ ] 能不看资料说出可观测性三支柱各自回答什么问题;
- [ ] 能按"缺口逼出模块"的顺序讲出平台 8 个模块的来历;
- [ ] 能说清三条"非目标"和背后的理由;
- [ ] 手上有 A~H 八组需求清单(建议抄进你的项目笔记);
- [ ] 能说出三个用户角色各自最关键的 1 条用户故事。
下一站的准备
下一篇我们把这张需求清单变成设计:一张数据流架构图、9 个 Django app 的职责边界、 核心数据模型,以及 5 个决定项目成败的设计决策(含被否掉的备选方案)—— 02 · 系统设计。