AI 赋能的业务监控:从被动告警到基于 LLM 的主动异常检测
AI 赋能的业务监控从被动告警到基于 LLM 的主动异常检测一、传统监控的告警疲劳困境如果用一个词形容我们团队 2024 年的监控状态那一定是告警疲劳。Prometheus Grafana Alertmanager 这套经典组合每天产生的告警数量在 200~400 条之间波动。值班同事的工作模式逐渐变成了收到告警 → 看一眼 Grafana 面板 → 如果看起来没什么大问题就关闭。统计数据显示2024 年 Q3 的告警中真正需要人工介入处理的有效告警仅占 7.3%。其余 92.7% 的告或是阈值设置过于敏感产生的噪音如 CPU 瞬时飙升至 85% 又立即回落或是关联告警的重复通知同一磁盘故障触发了 12 条不同维度的告警或是已知的周期性波动每天凌晨 2 点的批处理任务导致数据库连接数峰值。告警系统的核心问题不是告得不够多而是告得不够聪明——它只能做简单的阈值比较完全不具备对系统行为的理解能力。二、分层异常检测的架构设计我们设计了一套分层异常检测架构从下到上分为三层。第一层统计异常检测。保留传统的阈值和同比/环比检测但将阈值从固定值升级为动态基线。通过统计过去 30 天的指标分布计算 P5/P95 分位数仅在指标突破分位数范围时触发。这消除了由于固定阈值设置不合理导致的大多数误报。第二层向量化异常检测。这是引入 AI 的核心创新点。我们将系统的正常状态编码为高维向量。具体做法是以每分钟为粒度采集当前系统的 Top-50 指标CPU、内存、GC 频率、接口 P99 延迟、QPS、错误率、数据库连接池使用率、MQ 积压数量等组成一个 50 维的特征向量。通过 Isolation Forest 算法训练无监督异常检测模型发现偏离正常状态簇的异常时刻。异常检测不是简单地告诉你某个指标超了而是告诉你当前系统的整体状态与过去 30 天同一时段有显著差异。这一层的告警质量远高于单纯的阈值告警。第三层LLM 根因分析。当异常被检测到时系统自动收集异常发生前后 5 分钟的指标快照、日志关键信息、调用链异常节点等上下文数据格式化为结构化的 Prompt 提交给 LLM 进行分析。/** * 分层异常检测引擎 */ Service public class AnomalyDetectionEngine { Resource private MetricCollector metricCollector; Resource private IsolationForestModel anomalyModel; Resource private RootCauseAnalyzer rootCauseAnalyzer; /** * 每分钟触发一次的异常检测主流程 */ public void detect() { // 采集当前时刻的系统多维指标 double[] currentVector metricCollector.collectCurrentVector(); if (currentVector null || currentVector.length 0) { log.warn(指标采集为空跳过异常检测); return; } // 动态基线检测第一层 ListString thresholdAlerts checkDynamicThresholds(currentVector); // 向量异常检测第二层 AnomalyScore score; try { score anomalyModel.predict(currentVector); } catch (ModelException e) { log.error(异常检测模型预测失败, e); score AnomalyScore.normal(); // 降级为正常 } if (!score.isAnomalous() thresholdAlerts.isEmpty()) { return; // 系统正常无需处理 } // 异常确认收集上下文信息 AnomalyContext context AnomalyContext.builder() .timestamp(LocalDateTime.now()) .anomalyScore(score) .thresholdAlerts(thresholdAlerts) .metricSnapshot(metricCollector.snapshot(5)) // 前后5分钟快照 .recentLogs(logCollector.collect(5)) .traceAnomalies(traceCollector.detectAnomalies(5)) .build(); // LLM根因分析第三层 try { RootCauseReport report rootCauseAnalyzer.analyze(context); // 根据严重程度决定告警策略 if (report.getSeverity() Severity.CRITICAL) { alertService.sendUrgent(report); } else { alertService.sendWarning(report); } log.info(异常检测完成: severity{}, summary{}, report.getSeverity(), report.getSummary()); } catch (AnalyzerException e) { log.error(LLM根因分析失败降级为传统告警, e); alertService.sendFallbackAlert(thresholdAlerts); } } private ListString checkDynamicThresholds(double[] vector) { ListString alerts new ArrayList(); DynamicBaseline baseline baselineService.getBaseline(); for (int i 0; i vector.length; i) { double value vector[i]; BaselineStats stats baseline.getStats(i); if (stats null) continue; if (value stats.getP95() * 1.2 || value stats.getP5() * 0.8) { alerts.add(String.format(指标[%d]异常: 当前值%.2f, 基线P5-P95[%.2f, %.2f], i, value, stats.getP5(), stats.getP95())); } } return alerts; } }三、LLM 根因分析的 Prompt 工程根因分析是整个系统中 Prompt 设计要求最高的环节。输入信息包含多种格式的结构化数据时序指标、日志片段、调用链图谱。如何让 LLM 从这些异构数据中推理出正确的根因我们的 Prompt 设计分为三个区块。上下文简报用不超过 200 字的自然语言概括当前异常的整体情况哪些维度异常、异常严重程度、是否有已知的关联事件。结构化数据以 Markdown 表格形式呈现关键指标的当前值与基线对比值偏高用 ↑ 标记偏低用 ↓ 标记以列表形式呈现最近的异常日志仅保留 ERROR 和 WARN 级别去重后不超过 10 条以文本形式描述调用链中的异常节点和对应的下游服务。历史关联检索过去 90 天内相似异常的工单和处理记录作为参考。最后通过一个严格的输出格式约束要求 LLM 按最可能的根因 → 置信度 → 关联证据 → 建议操作 → 是否需要立即处理五段式输出。/** * LLM根因分析服务 */ Service public class RootCauseAnalyzer { Resource private LLMClient llmClient; Resource private HistoricalTicketSearcher ticketSearcher; /** * 分析异常上下文生成根因报告 */ public RootCauseReport analyze(AnomalyContext context) throws AnalyzerException { // 检索历史相似异常工单 ListTicket similarTickets ticketSearcher.searchSimilar( context.getMetricSnapshot(), 5); String prompt buildAnalysisPrompt(context, similarTickets); String response; try { response llmClient.chat(prompt); } catch (LLMException e) { throw new AnalyzerException(LLM调用失败, e); } try { return parseRootCauseReport(response); } catch (ParseException e) { log.error(根因报告解析失败: {}, response); // 解析失败时构建一个基础的降级报告 return buildDegradedReport(context); } } private String buildAnalysisPrompt(AnomalyContext context, ListTicket similarTickets) { StringBuilder prompt new StringBuilder(); prompt.append(你是一个资深的系统运维专家。请分析以下异常检测结果找出根因。\n\n); // 异常概况 prompt.append(## 异常概况\n); prompt.append(String.format(检测时间: %s\n, context.getTimestamp())); prompt.append(String.format(异常评分: %.2f (阈值0.7)\n, context.getAnomalyScore().getValue())); prompt.append(String.format(触发阈值告警数: %d\n\n, context.getThresholdAlerts().size())); // 关键指标对比表格形式 prompt.append(## 关键指标对比\n); prompt.append(| 指标 | 当前值 | 基线均值 | 偏差 |\n); prompt.append(|------|--------|----------|------|\n); for (MetricSnapshot metric : context.getMetricSnapshot().getMetrics()) { String deviation metric.getDeviationPercent() 0 ? ↑ String.format(%.0f%%, metric.getDeviationPercent()) : ↓ String.format(%.0f%%, Math.abs(metric.getDeviationPercent())); prompt.append(String.format(| %s | %.2f | %.2f | %s |\n, metric.getName(), metric.getCurrentValue(), metric.getBaselineMean(), deviation)); } // 异常日志 prompt.append(\n## 异常日志\n); for (String logLine : context.getRecentLogs()) { prompt.append(- ).append(logLine).append(\n); } // 历史相似工单 if (!similarTickets.isEmpty()) { prompt.append(\n## 历史相似工单\n); for (Ticket ticket : similarTickets) { prompt.append(String.format(- [%s] %s (处理方案: %s)\n, ticket.getResolvedTime(), ticket.getTitle(), ticket.getResolution())); } } // 输出格式要求 prompt.append(\n请严格按以下格式输出分析结果\n); prompt.append(根因: 最可能的根因描述\n); prompt.append(置信度: 0~100的数值\n); prompt.append(关联证据: 支持该结论的具体证据\n); prompt.append(建议操作: 具体的处理步骤\n); prompt.append(紧急度: critical/high/medium/low\n); return prompt.toString(); } private RootCauseReport parseRootCauseReport(String response) { // 解析LLM返回的五段式结构化报告 RootCauseReport report new RootCauseReport(); String[] lines response.split(\n); for (String line : lines) { if (line.startsWith(根因:)) { report.setRootCause(line.substring(3).trim()); } else if (line.startsWith(置信度:)) { String value line.substring(4).trim().replace(%, ); report.setConfidence(Integer.parseInt(value)); } else if (line.startsWith(建议操作:)) { report.setSuggestedAction(line.substring(5).trim()); } else if (line.startsWith(紧急度:)) { report.setSeverity(Severity.fromString(line.substring(4).trim())); } } return report; } private RootCauseReport buildDegradedReport(AnomalyContext context) { RootCauseReport report new RootCauseReport(); report.setRootCause(LLM分析结果解析失败请人工排查); report.setConfidence(0); report.setSuggestedAction(请查看原始监控数据和日志进行人工分析); report.setSeverity(Severity.MEDIUM); return report; } }四、告警聚合与降噪引入异常检测和根因分析后单条告警的质量大幅提升。但随之而来的新问题是根因分析的报告数量仍然不少高峰时每小时仍有 15~20 条报告。值班同事反馈信息质量提高了但信息量还是太大。我们引入了一个轻量级的告警聚合引擎从两个维度聚合一是时间维度将 5 分钟窗口内的多条根因报告合并取置信度最高的一条作为代表其余的作为补充细节二是拓扑维度通过服务依赖关系图基于调用链数据自动生成将有关联的服务告警聚合成一条影响链报告明确展示异常传播路径如Redis 连接超时 → 订单服务降级 → 支付服务队列堆积。五、效果评估与下一步方向系统上线 4 个月后的对比如下有效告警占比从 7.3% 提升至 62%平均故障发现时间MTTD从 23 分钟降至 3.2 分钟平均故障修复时间MTTR从 87 分钟降至 41 分钟值班同事反馈的告警疲劳感从 8.5 分降至 3.2 分10 分满分制。下一步的优化方向包括一是引入预测性异常检测在故障发生前 5~10 分钟预警已在小规模实验中取得 72% 的提前预警率二是构建自动化修复决策对于置信度超过 90% 且修复方案明确的告警如重启 Pod、扩容 HPA自动触发修复操作三是将异常检测场景从后端监控拓展到业务指标如订单量异常下降、支付成功率异常波动实现从技术监控到业务监控的全面覆盖。AI 赋能监控的核心价值不是替代运维工程师而是让机器处理那些确定性的、重复性的、低价值的判断工作将人的精力集中在真正需要经验和创造力的疑难问题上。作者李然程序员鸭梨Java 架构师专注可观测性与智能运维体系建设。

相关新闻

Qwen、Kimi、GLM三大开源大模型实战部署与场景选择指南

Qwen、Kimi、GLM三大开源大模型实战部署与场景选择指南

如果你最近在关注AI大模型的发展,可能会发现一个明显的趋势:开源模型正在以惊人的速度追赶甚至超越闭源模型。从Qwen、Kimi到GLM,这些开源项目不仅在通用能力上表现出色,更在编程、推理等专业领域展现出独特优势。但问题来了&…

2026/10/10 7:57:33 阅读更多 →
小程序毕设项目:基于 SpringBoot 的运动健身日志记录与计划规划 APP 智能健身指导与个性化训练系统设计 (源码+文档,讲解、调试运行,定制等)

小程序毕设项目:基于 SpringBoot 的运动健身日志记录与计划规划 APP 智能健身指导与个性化训练系统设计 (源码+文档,讲解、调试运行,定制等)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/10/4 0:04:26 阅读更多 →
AU-60双波束DSP:I2S主从配置与延迟对齐的硬件实现细节

AU-60双波束DSP:I2S主从配置与延迟对齐的硬件实现细节

一、内置 Codec 的系统集成价值在传统的语音处理系统中,音频信号链路通常由分立器件组成:麦克风 MEMS 传感器 → 模拟前置放大器 → ADC(模数转换器)→ DSP(数字信号处理器)→ DAC(数模转换器&a…

2026/10/4 11:09:59 阅读更多 →

最新新闻

Docker 新手入门:搞懂镜像与容器关系,避开五大常见坑

Docker 新手入门:搞懂镜像与容器关系,避开五大常见坑

简介:面向零基础开发者与运维人员的 Docker 入门手册,系统讲解容器化技术相对于传统虚拟机在启动速度、资源占用、隔离性等方面的优势,以及镜像、容器、仓库三个核心概念的关联。内容覆盖 Ubuntu 环境下安装 Docker Engine 与配置用户组的完整…

2026/10/12 17:02:21 阅读更多 →
零成本玩转AI:TaoToken 统一 Key 接入免费模型全攻略

零成本玩转AI:TaoToken 统一 Key 接入免费模型全攻略

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 17:02:21 阅读更多 →
数据分析进阶:从业务语义到因果归因的实战跃迁

数据分析进阶:从业务语义到因果归因的实战跃迁

1. 项目概述:这不是“续集”,而是数据分析实战的临界点突破“2.3数据分析Data_Analysis_part2”这个标题乍看像课程目录里的一个普通编号,但在我带过二十多期数据分析实训、亲手陪跑过上百个真实业务分析项目的经历里,它几乎总出现…

2026/10/12 17:02:21 阅读更多 →
Milvus 2.5.4 离线部署实战:压缩包解决内网向量数据库依赖难题

Milvus 2.5.4 离线部署实战:压缩包解决内网向量数据库依赖难题

简介:本资源为 Milvus 2.5.4 单节点版离线安装包,面向需要在无外网环境下快速搭建向量数据库的开发者与数据科学家,尤其适合开发测试与小规模应用场景。压缩包共 10 个文件,约 779.13MB,以 gz 镜像与二进制包为主&…

2026/10/12 17:02:21 阅读更多 →
参考模型设计指南:从问题域出发构建可复用架构框架

参考模型设计指南:从问题域出发构建可复用架构框架

1. 参考模型到底在解决什么问题第一次接触“参考模型”这个词,很多人会下意识觉得它离自己很远,像是只有写论文或者做系统架构评审时才会用到的概念。但如果你做过任何稍微复杂一点的项目,不管是软件系统、数据分析流程、硬件选型方案&#x…

2026/10/12 17:02:21 阅读更多 →
Claude Code 50+命令全解析:从斜杠命令到快捷键的CLI效率手册

Claude Code 50+命令全解析:从斜杠命令到快捷键的CLI效率手册

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 17:01:19 阅读更多 →

日新闻

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

在数码相机、高清显示屏与现代矢量图形技术高度发达的今天,画面可以做到绝对的锐利、平滑与无瑕。然而,当一张秋日手账插画或拍立得照片过于“平整无瑕”时,往往会散发出一种冰冷生硬的“数码塑料感(Digital Plasticity&#xff0…

2026/10/12 0:00:59 阅读更多 →
活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

在现代网页与移动端设计中,横排(Horizontal Layout)早已经成为了绝对的主流。然而,当我们翻开泛黄的线装古籍、宋版木刻诗集,或是欣赏一张茶道雅集的手写便签时,那种**自上而下纵向书写、自右向左逐列铺展&…

2026/10/12 0:00:59 阅读更多 →
周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

每到周日的晚上八点到十点,很多人心里都会悄悄亮起一盏警示灯。 在心理学上,这种现象有一个专门的称谓——“周日夜晚焦虑症(Sunday Scaries)”。明天又是周一,闹钟又要重新在七点响彻卧房;脑海里仿佛有一个…

2026/10/12 0:00:59 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/12 0:16:30 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/12 0:16:43 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:54 阅读更多 →