
AI 辅助排查生产问题先给日志再给架构图最后给错误信息标签AI、AI学习、故障排查、DevOps一、凌晨三点服务器挂了凌晨三点监控告警炸了几个关键接口的超时率飙到 40%。我被电话叫醒迷迷糊糊打开电脑看到屏幕上满屏红色告警脑子里一片空白。因为经验不足我本能地开始猜问题是不是数据库连接池不够是不是有人在刷接口是不是上线的代码有 bug然后就开始乱试重启服务、扩数据库连接数、回滚代码……每一步都是凭直觉毫无章法。后来一个资深同事接手五分钟定位到问题一个定时任务忘了加锁三个 Pod 同时跑打满了数据库查询。他问我你刚才查了啥日志看了吗架构图熟悉吗最近改动是什么时候这三个问题让我意识到不是我没能力排查问题是我没有排查问题的框架。从那以后我开始摸索一套 AI 辅助的排查流程。不是说 AI 能自动解决问题而是 AI 作为一个知识库 推理助手可以帮我在信息不完整的情况下更快地缩小问题范围。这篇文章就分享一下这个流程希望对和我一样经验不足的朋友有帮助。二、AI 排查的三段式框架经过几十次线上问题有大有小的磨练我总结了一套三段式的排查流程。每一步不是孤立执行的而是逐步递进每一步的结论都缩小下一步的搜索范围。flowchart TD Start[ 生产告警触发] -- Step1[ 第一段喂日志] Step1 -- Step1A[整理最近 15 分钟的\n关键错误日志] Step1A -- Step1B[扔给 AI总结异常模式\n标注高频错误\n时间线排序] Step1B -- Step1C{日志能定位到原因} Step1C --|能| Fix[ 修复并验证] Step1C --|不能| Step2[️ 第二段喂架构图] Step2 -- Step2A[画出涉及的\n服务拓扑图] Step2A -- Step2B[标记错误在哪个节点\n标记调用链路] Step2B -- Step2C[让 AI 分析可能瓶颈:\n数据库缓存\n消息队列网络] Step2C -- Step2D{架构分析能定位} Step2D --|能| Fix Step2D --|不能| Step3[ 第三段喂指标 变更记录] Step3 -- Step3A[喂入CPU/内存/QPS/\n连接数/慢查询] Step3A -- Step3B[喂入最近的部署\n变更记录] Step3B -- Step3C[让 AI 做时间关联分析:\n变更时间 vs 指标突变\n请求量 vs 资源消耗] Step3C -- Step3D{找到根本原因} Step3D --|能| Fix Step3D --|不能| Escalate[⚠️ 升给更资深的同事] Fix -- Verify[✅ 监控恢复确认] style Start fill:#ffcdd2 style Step1 fill:#e3f2fd style Step2 fill:#fff3e0 style Step3 fill:#f3e5f5 style Fix fill:#c8e6c9 style Verify fill:#c8e6c9 style Escalate fill:#ffcdd2注意这个框架不是死的。有时候我看日志就直接定位了不需要走到第三段。但关键是要按顺序来。跳过日志看架构图、跳过架构看变更记录很容易被无关信息误导。三、第一段喂日志——用 AI 做模式识别生产日志最大的问题是太多。一个中等规模的微服务15 分钟的日志可能就有几万行。人工一行行看不可能但让 AI 做初见分析非常合适。我一般会用以下结构化提示词你是生产环境的故障排查助手。下面是我服务最近 15 分钟的日志片段。 请帮我分析 1. 统计错误类型和频率按出现次数排序。 2. 标记同一时间点集中爆发的异常可能有因果关系。 3. 忽略已知的噪声错误如 health check 404、连接重置等非关键错误。 4. 如果有明显的根因迹象直接指出。 以下是日志已脱敏 [粘贴日志内容]这样喂给 AI 之后它通常能给出一个异常摘要比如ConnectionPoolTimeoutException出现了 234 次从 03:14:22 开始集中爆发NullPointerException出现了 12 次分布在多个时间点以上两条可能有关联连接池超时导致某步操作未正确初始化这比我自己一行行翻日志快了不知道多少倍。实际的日志喂入示例假设我有一个 Rust 服务的日志报错信息大概是这样// 这是一个模拟的生产日志输出 // 在实际排查中你需要根据日志格式先做预处理 use tracing::{info, warn, error}; // 假设这是出问题的代码忘记了连接池的 borrow 需要等待可用连接 async fn handle_request(pool: Pool) - ResultResponse, AppError { // 问题点pool.get() 在并发高时可能超时 // 连接池大小只有 5但有 50 个并发请求导致排队超时 let conn pool.get().await?; // 获取连接超时后会吐出 PoolTimeout 错误 let result db::query(conn, SELECT * FROM users).await?; Ok(result) }对应的日志可能是2024-07-11T03:14:22.123Z ERROR pool::internal: failed to get connection, errorConnectionPoolTimeout { pool_size: 5, waiting: 48, timeout_ms: 30000 }扔给 AI 后它能告诉我连接池大小只有 5但有 48 个请求在排队等连接这大概率是连接池配置太小或者有慢查询占着连接不释放。这一步就让排查方向从一个模糊的服务慢了缩小到了连接池这个具体组件。四、第二段喂架构图——让 AI 理解上下文如果日志看不出问题比如错误很分散没有明显的共同点就需要做拓扑分析。我通常会把相关的服务架构画成文字描述或 Mermaid 图喂给 AIgraph LR subgraph 前端 Nginx[Nginx 网关\n端口 443] end subgraph 应用层 API1[API 服务 Pod A\n端口 8080] API2[API 服务 Pod B\n端口 8080] API3[API 服务 Pod C\n端口 8080] end subgraph 中间件 Redis[Redis 缓存\n端口 6379] RabbitMQ[RabbitMQ 队列\n端口 5672] end subgraph 数据层 DB[PostgreSQL 主库] end subgraph 外部依赖 OSS[对象存储] SMS[短信服务] end Nginx -- API1 Nginx -- API2 Nginx -- API3 API1 -- Redis API1 -- RabbitMQ API1 -- DB API2 -- Redis API2 -- RabbitMQ API2 -- DB API3 -- Redis API3 -- RabbitMQ API3 -- DB API3 -- OSS API1 -- SMS然后对 AI 说我的服务架构如上。现在的问题是API 响应时间从 50ms 飙升到 5s三个 Pod 都慢。数据库 CPU 正常Redis 延迟正常RabbitMQ 消息堆积正常。请帮我分析可能的原因。AI 看了图之后可能会说如果 DB、Redis、MQ 都正常但 API 都慢很可能问题在外部依赖OSS 或 SMS 服务超时。特别是 SMS 服务如果响应慢会阻塞主线程。这个推理逻辑是三个 Pod 同时慢不会是单个 Pod 的问题DB/Redis/MQ 正常排除了数据层瓶颈剩下的最可疑的就是外部依赖。果然真实情况就是短信服务供应商出了故障每次调用超时 10 秒导致线程池被占满。如果日志和架构都看不出问题那大概率和时间维度有关。把变和坏的时间点对上问题就浮出来了。我实践中的一个小脚本用来把部署时间和告警时间做关联# 变更-告警关联分析脚本 # 用法将部署记录和告警时间扔进去自动找出部署后 N 分钟出问题的所有事件 # 注意这是一个辅助分析脚本不是排查问题的银弹 import json from datetime import datetime, timedelta # 部署记录从 CI/CD 系统导出 deployments [ {time: 2024-07-11 02:30:00, service: api-server, version: v2.3.1, description: 优化了数据库连接池配置}, {time: 2024-07-11 03:10:00, service: cron-scheduler, version: v1.8.0, description: 新增用户统计定时任务}, ] # 告警记录从监控系统导出 alerts [ {time: 2024-07-11 03:14:22, service: api-server, metric: p99_latency, value: 5200ms, threshold: 1000ms}, {time: 2024-07-11 03:14:25, service: api-server, metric: error_rate, value: 15%, threshold: 5%}, ] # 分析找出每次部署后第一次告警的时间差 print( * 60) print(变更-告警时间关联分析) print( * 60) for deploy in deployments: deploy_time datetime.strptime(deploy[time], %Y-%m-%d %H:%M:%S) print(f\n 变更: {deploy[service]} {deploy[version]}) print(f 时间: {deploy[time]}) print(f 描述: {deploy[description]}) # 查找该服务在部署后的第一次告警 first_alert None for alert in alerts: alert_time datetime.strptime(alert[time], %Y-%m-%d %H:%M:%S) if alert[service] deploy[service] and alert_time deploy_time: if first_alert is None or alert_time first_alert[time]: first_alert { time: alert_time, metric: alert[metric], value: alert[value], } if first_alert: delta first_alert[time] - deploy_time print(f ⚠️ 首次告警: {delta.total_seconds() / 60:.1f} 分钟后) print(f 指标: {first_alert[metric]} {first_alert[value]}) # 如果部署后 5 分钟就告警几乎可以确定是这次部署引入的 if delta.total_seconds() 300: # 5分钟 print(f 高度可疑告警在部署后 {delta.total_seconds() / 60:.1f} 分钟出现) else: print(f ✅ 部署后无相关告警) print(\n * 60) print(结论: cron-scheduler 的部署时间 (03:10) 距首次告警 (03:14) 仅 4 分钟) print( 且新增了定时任务高度怀疑是该变更导致的问题。) print( * 60)把这个分析结果和指标数据CPU、QPS、连接数一起喂给 AI它就能做更精准的时间关联推理。五、总结经过这么长时间的交学费我现在排查问题有了一套固定的节奏先给日志让 AI 做信息压缩和模式识别。从几万行日志里提取关键模式这是 AI 最擅长的。再给架构图让 AI 做拓扑分析。架构图提供全局视野AI 能帮你在多个依赖之间推理因果关系。最后给变更记录和指标做时间关联分析。什么时间变了什么和什么时间坏了什么对上了问题就浮出水面。AI 是辅助不是替代。它能帮你快速缩小范围、提供排查方向但最终的判断和决策需要你来做。代码是你写的业务是你了解的这些东西 AI 替代不了。每次排查完做复盘。把排查过程记录下来下次类似的场景就能大大加速。作为一个只有几年经验的程序员我深知自己在生产问题面前还很嫩。上面的流程也只是我现阶段能想到的最优解肯定还有很多改进空间。如果你有更好的排查思路欢迎在评论区告诉我。