Linux 监控告警 + AI 智能监控

楠风测开 · 测试工程师复习日记 Day14

📊 Prometheus + Grafana 实践:指标口径、告警链路与 AI 异常检测

前言

朋友们好,我是楠风。

Day 11---13,我们复习了 Linux 命令、AI 辅助写 Shell 和性能瓶颈排查。今天把这些观察能力接入一套持续工作的监控体系。

先看一个教学场景:创建订单接口持续返回 500,CPU 却只有 20%。看板能看到错误,告警群里没有消息。

如果规则写成"CPU 超过 80%,并且错误率超过 5%",这个结果就不奇怪。资源没有打满,接口故障仍然可能发生。

这篇围绕已有 Prometheus、Grafana 和 Alertmanager 环境,讨论指标怎么定义、规则怎么写、通知怎么验收,以及 AI 检测任务接在哪里。配置中的阈值用于演示,需要按业务调整。

一、先把监控链路画清楚

text 复制代码
Linux node_exporter ─┐
                    ├→ Prometheus ─→ Grafana 看板
应用 /metrics ──────┘       │
                          规则评估
                            ↓
                       Alertmanager
                            ↓
                      接收渠道 / 适配服务
                            ↓
                      负责人排查与恢复

node_exporter 提供主机资源指标,应用另行暴露请求量、耗时和结果。Prometheus 抓取、存储并评估规则;Grafana 查询这些数据;Alertmanager 负责告警分组、去重和路由。这里的通知不依赖 Grafana 转发。Prometheus 架构

Grafana 的数据源地址必须能从 Grafana 所在环境访问。容器内的 localhost 指容器自身,不能直接照搬宿主机访问地址。数据源配置

看板至少摆上请求速率、错误比例、P95 延迟和资源使用情况。面板共用服务筛选与时间范围,异常发生时才能对照。日志里的服务名、时间和请求 ID 则用于继续定位原因。

二、动手前先约定指标口径

以 POST /orders 为例,约定在请求结束时递增一次计数器:

text 复制代码
http_requests_total{
  service="order-demo",
  route="/orders",
  method="POST",
  status="500"
}

本文假设抓取任务为 order-demo,同一实例不会被重复采集。多个实例可以汇总,但不能混入其他环境的数据。

这里有三个细节:

  • 路由使用模板。 例如 /orders/{id},别把每个订单 ID 都放进标签;请求 ID 留在日志里。
  • 失败和总量保持同一口径。 同一服务、路由、方法和时间窗口,才有可比较的错误率。
  • 初始化已知状态序列。 应用启动时把已知的 200、500 等状态计数初始化为 0 并持续暴露;否则"没有错误序列"与"错误数为零"不同。官方埋点建议

接口返回 200 但订单没创建,属于另一类业务失败。HTTP 指标之外,还需要业务结果埋点或探测,不能让状态码替业务下结论。

汇总多个实例时,还要避免"平均错误率"。假设实例 A 收到 100 次请求、失败 20 次,实例 B 收到 900 次请求、全部成功,整体错误率是 20 ÷ 1000,也就是 2%;把两个实例的比例直接平均,会得到 10%。

整体比例回答的是服务总体情况。它也可能掩盖单个实例的问题,因此保留实例级看板,必要时另设实例规则,才能从服务现象继续定位。

三、写一条能够解释的告警

目标先用自然语言表达:订单创建接口最近 5 分钟的 5xx 比例超过 5%,平均流量至少为每秒 1 次,且条件连续成立 1 分钟。

规则文件 order-alerts.yml:

yaml 复制代码
groups:
  - name: order-api
    rules:
      - alert: OrderApiHigh5xxRate
        expr: |
          (
            sum by (service, route, method) (
              rate(http_requests_total{
                job="order-demo", service="order-demo",
                route="/orders", method="POST", status=~"5.."
              }[5m])
            )
            /
            sum by (service, route, method) (
              rate(http_requests_total{
                job="order-demo", service="order-demo",
                route="/orders", method="POST"
              }[5m])
            )
            > 0.05
          )
          and on (service, route, method)
          (
            sum by (service, route, method) (
              rate(http_requests_total{
                job="order-demo", service="order-demo",
                route="/orders", method="POST"
              }[5m])
            ) >= 1
          )
        for: 1m
        labels:
          severity: warning
        annotations:
          summary: "订单创建接口5xx比例持续偏高"
          description: "检查请求指标、应用日志和依赖服务"

Prometheus 的 rule_files 需要加载这个文件,主配置还要指向 Alertmanager;Alertmanager 再按接收器配置通知渠道。

这里先对每条计数器序列求 rate,再汇总到相同标签维度,既统一分子分母,也保留对计数器重置的处理。不能拿每个状态码的原始速率直接相除。rate 用法

两处设计取舍要写进测试用例:

第一,流量门槛减少小样本波动,也会排除低流量故障。支付等低频关键操作,需要额外的业务失败规则或主动探测。

第二,[5m] 是计算窗口,for: 1m 是表达式持续成立的时间。它既不是"第一次 500 后一分钟发消息",也不能机械地算成六分钟;还涉及采集、评估与通知调度。告警规则说明

CPU 异常单独设规则。是否响应接口故障,不以 CPU 同时升高为前提。

四、通知与恢复需要分别验收

建议在可控测试环境按"正常请求 → 注入故障 → 撤掉故障"运行,记录开始报错、条件成立、告警触发、消息送达四个时间点。

看到 firing 只说明规则已触发。还要检查 Alertmanager 的路由、静默状态、接收器与下游服务。通用 webhook 的请求格式不一定匹配群机器人,必要时需要适配服务;恢复通知也应在接收器中明确配置。Alertmanager 配置

接收人拿到消息后,应该知道哪个环境、哪个服务、哪个接口出问题,以及先看哪里。可以在通知模板中带上标签、触发值、看板地址和排查入口。只有"服务异常"四个字,即使送达,也会把定位工作重新推给接收人。

撤掉故障后继续发送成功请求,等待历史失败样本逐步离开窗口,再观察解除与恢复消息。

告警消失不能单独证明业务恢复。 零请求、采集失败和目标被移除也要区分:up == 0 能检查已有抓取目标的失败,目标缺失则需结合预期目标与 absent_over_time 等方法另设规则。缺失序列检测

五、🤖 AI 异常检测接在哪里

固定阈值先覆盖明确故障,再让模型发现偏离历史表现的时间段。例如 P95 从平时的 100ms 升到 250ms,尚未到 500ms 阈值,是否值得关注要结合流量和历史变化判断。

可以先用简单动态基线做对照,再试验 Isolation Forest。AI 帮忙写出均值、标准差计算代码,并不会让统计规则自动变成机器学习模型。

为每个服务建立同一时间窗口的样本,特征可以是请求速率、5xx 比例、P95 延迟与关联主机 CPU 使用率。单位、采样时间和聚合口径必须固定;服务到主机的映射不明确时,先去掉 CPU 特征。

下面是已准备好数据后的核心流程:

python 复制代码
from sklearn.ensemble import IsolationForest

# 两个数组均为 [样本数, 特征数],列顺序和单位完全一致。
# normal_train 来自较早、已核对正常的时间段。
# later_eval 来自后续独立时间段,包含标注的正常与故障样本。
model = IsolationForest(random_state=42)
model.fit(normal_train)
flags = model.predict(later_eval)

predict 的 -1 表示模型判为异常,1 表示模型判为正常。这个判断不是故障根因,也不是已经校准的故障概率。Isolation Forest 说明

接入时需要实现数据整理、定时推断和指标暴露:

text 复制代码
Prometheus 查询 → 时间对齐与数据校验 → 定时推断
→ 暴露异常标记、最近成功评分时间 → Prometheus 采集
→ 规则评估 → Alertmanager → 人工复核

查询返回多条序列时,按标签匹配,不能直接取第一个结果。缺失和无穷值应单独处理,不能补零后当作正常样本;没有有效请求时,P95 也可能无法计算。

模型服务还要暴露"最近一次成功评分的时间戳"。只看进程心跳,可能漏掉"程序活着但评分卡住";只看异常标记,又可能把残留的旧结果当成当前状态。评分超时、采集失败、指标缺失都需要覆盖。

上线前按时间切分数据,别把同一故障前后相邻样本随机混进训练集与验证集。用正常高峰、发布变更、故障演练、采集缺失和恢复过程评估,并与现有阈值规则对照:

  • 同一观察周期内,产生多少次需要人工查看的误报?
  • 已标注的故障事件,有多少漏掉?
  • 从故障开始到首次有效告警,延迟多少?

比较误报时,还要先统一计数方式:连续十分钟判为异常,是一次异常事件,还是十个采样点?把相邻异常合并为事件后再统计通知数量,才更接近人的处理负担。漏报则对照独立标注的故障事件,不能让模型自己定义"哪些是真故障"。

业务上线新功能或流量结构变化后,旧训练数据可能不再代表当前正常状态。保留特征定义、模型版本和训练时间段,定期复核;夜间与白天的差异也需要显式设计,模型不会自动理解业务日历。

先让模型结果进入观察看板,人工复核后再决定是否参与通知。多指标同时变化能提供排查线索,仍需要日志或实验来确认原因。

六、📋 留一份验收清单

场景 核对重点
正常流量 指标持续更新,规则不误触发
CPU 正常但接口持续报错 达到规则条件后,通知送到正确接收人
短暂错误与低流量 验证持续时间及流量门槛的实际影响
撤掉故障 错误比例回落,告警解除,另验恢复通知
采集失败与目标移除 分别触发对应检查,不当成恢复
AI 评分卡住 成功评分时间停止更新,任务异常被发现

每次演练保存规则版本、故障时间和通知记录。后续调整阈值或模型,再用相同场景比较,才能知道改动补上了什么、又引入了什么遗漏。

下期预告

Day15 · MySQL 基础 + AI SQL 优化

继续沿着订单接口往下查:返回 200,数据库里却没有新增订单,该怎样写 SQL 校验?再让 AI 辅助改写查询,用结果与执行计划验证改动。

🌱 楠风测开 · 把测试方法用到具体问题里。

相关推荐
Solara2 小时前
库连续 35 天只写自己的日记:第 36 天的外采,进得了索引,进不了版本库
人工智能·程序员·ai编程
阿里嘎多学长2 小时前
2026-10-14 GitHub 热点项目精选
开发语言·程序员·github·代码托管
合尘猫2 小时前
给客服系统加一道闸:把「该转人工」从模糊判断变成可测拦截
人工智能·后端·程序员
阿里嘎多学长3 小时前
2026-10-13 GitHub 热点项目精选
开发语言·程序员·github·代码托管
程序员cxuan1 天前
Gemini 4 Argon 正式发布!
人工智能·后端·程序员
高晶1 天前
ARM 嵌入式 Linux 开发:从体系结构到 LED 点亮实战
设计模式·程序员
Hilaku1 天前
ERP选型时不问MCP,等于默认三年后再付一次集成费!
前端·javascript·程序员
小贺儿开发1 天前
DeepSeek + Codex + MCP:Unity 游戏开发实测
科技·游戏·unity·ai·程序员·编程·deepseek