慢接口排查别只问结论:一次日志分析流程复盘

📅 2026/6/30 11:51:25
慢接口排查别只问结论:一次日志分析流程复盘
线上接口偶发变慢是后端开发最容易被“经验判断”带偏的问题之一。前段时间我处理过一个订单查询接口的性能问题。现象不算夸张P95 从 180ms 抬到 700ms 左右持续时间不稳定监控里没有明显错误率上升数据库 CPU 也没打满。最开始我也想当然地怀疑是慢 SQL但真正查下来问题并不只在 SQL。这次我把 AI 模型放进了排查流程里但没有让它直接“判断根因”。我的做法是把脱敏后的日志、调用链片段、SQL 执行计划、代码片段分批交给模型让它帮我做归纳、列假设、设计验证步骤最后再用实际数据验证。这篇记录一下完整过程重点不是某个模型有多强而是AI 辅助 Debug 时最好让它参与可验证的中间环节而不是直接替你下结论。问题背景接口偶发慢但没有明显报错接口简化后大概是这样httpGET /api/order/list?userIdxxxpage1pageSize20调用链路textNginx - API Gateway - order-service - user-service - coupon-service - MySQL - Redis监控里看到几个现象textorder-service /api/order/listP50: 95msP90: 410msP95: 730msP99: 1800ms 错误率无明显变化QPS比平时高约 18%MySQL CPU正常Redis 延迟偶发尖刺如果只看这些指标很容易得出几个模糊判断可能是 Redis 抖动可能是数据库慢查询可能是下游服务不稳定可能是接口里有 N1 查询可能是分页参数被滥用。这些判断都可能对但没法直接改代码。于是我先做了一件事把材料拆成几个最小输入避免一次性把一堆日志丢给模型。第一步先让 AI 整理现象不让它猜根因我用过 ChatGPT、Claude、Gemini、DeepSeek 做这类任务。个人感受是Claude 对长日志归纳比较稳ChatGPT 在排查思路上比较完整Gemini 适合快速压缩信息DeepSeek 对中文技术描述很顺。但模型不是重点输入方式更关键。第一段 Prompt 我会写得很保守text你是后端排查助手。下面是脱敏后的接口监控摘要和部分日志。 请只做三件事1. 提取明确事实2. 按时间线整理异常现象3. 列出需要继续验证的问题。 限制- 不要直接判断根因- 不要编造日志中不存在的字段- 不要给优化方案- 不确定的地方标记为“证据不足”。 输入{监控摘要和脱敏日志}这样做的好处是减少幻觉。模型输出的内容大概会变成text明确事实- P95 在 10:10 至 10:35 之间升高- QPS 较基线增长约 18%- 部分请求在 coupon-service 调用处耗时超过 400ms- Redis get 操作存在少量 100ms 以上记录- 未观察到 5xx 错误率升高。 待验证问题- 慢请求是否集中在特定 userId 或分页参数- coupon-service 慢调用是否与 Redis 延迟重合- order-service 内部是否存在循环调用下游- SQL 执行耗时是否与慢请求时间段一致。这一步的价值不是“聪明”而是把零散信息整理成排查清单。尤其是凌晨看日志时人很容易漏掉时间线细节。第二步把慢请求样本做成结构化表格原始日志通常长这样text2025-02-14 10:18:21.332 INFO traceIdabc123 userIdU1023 path/api/order/list cost812ms dbCost96ms redisCost128ms couponCost431ms page1 pageSize202025-02-14 10:18:22.019 INFO traceIdabc124 userIdU7781 path/api/order/list cost756ms dbCost88ms redisCost119ms couponCost402ms page1 pageSize202025-02-14 10:18:25.441 INFO traceIdabc125 userIdU5531 path/api/order/list cost1680ms dbCost121ms redisCost310ms couponCost980ms page1 pageSize20我不会直接让 AI 看几千行日志然后“分析一下”那样输出很容易发散。更稳的是先用脚本做一次初筛。例如用 Python 抽取慢请求pythonimport refrom statistics import mean pattern re.compile( rtraceId(\w).*?cost(\d)ms.*?dbCost(\d)ms.*? rredisCost(\d)ms.*?couponCost(\d)ms.*?page(\d).*?pageSize(\d)) rows [] with open(order.log, r, encodingutf-8) as f: for line in f: m pattern.search(line) if not m: continue trace_id, cost, db, redis, coupon, page, page_size m.groups() cost int(cost) if cost 700: rows.append({ traceId: trace_id, cost: cost, dbCost: int(db), redisCost: int(redis), couponCost: int(coupon), page: int(page), pageSize: int(page_size) }) print(slow count:, len(rows))print(avg cost:, mean([r[cost] for r in rows]) if rows else 0) for r in rows[:20]: print(r)得到结构化样本后再交给 AItext下面是慢请求样本字段含义如下- cost接口总耗时- dbCost数据库查询耗时- redisCostRedis 操作耗时- couponCost调用 coupon-service 耗时 请分析这些样本中可能的相关性。 要求1. 只基于样本分析2. 不直接判断根因3. 输出“可能相关”“证据不足”“建议补充数据”三类4. 给出下一步验证建议。这一步模型通常能帮你发现一些“肉眼看着有点像但没来得及整理”的现象。比如我这次看到慢请求里couponCost占比明显更高Redis 延迟也有抬升但数据库耗时相对稳定。这不代表 coupon-service 一定有问题只能说明它值得继续查。第三步让 AI 帮忙设计验证而不是替你验证排查性能问题最怕从一个猜测跳到另一个猜测。比较靠谱的方式是给每个假设配验证动作。我会让模型输出类似这样的表text请根据当前证据列出 5 个以内排查假设。 每个假设包含- 假设描述- 当前支持证据- 当前反证或不足- 需要补充的监控/日志- 可执行的验证命令或 SQL- 如果验证成立下一步处理建议 注意- 不要写大而全的优化建议- 优先选择低风险验证动作- 不要建议直接改线上配置。输出里有几条比较有用假设支持证据验证动作coupon-service 响应变慢拖累主接口慢请求中 couponCost 占比高查 coupon-service 同时间段 P95/P99Redis 延迟影响 coupon-serviceredisCost 与 couponCost 同时抬升对齐 Redis latency monitor 与调用链order-service 存在重复调用优惠券逻辑慢请求集中在订单列表接口检查循环内是否调用 coupon 查询数据库不是主要瓶颈dbCost 相对稳定对慢请求 traceId 关联 SQL 耗时这类表格对排查很有帮助因为它把“猜测”变成了“验证任务”。第四步代码片段 Review重点查循环调用后来我把脱敏后的核心代码片段给模型看javapublic ListOrderVO listOrders(String userId, int page, int pageSize) { ListOrder orders orderRepository.queryByUser(userId, page, pageSize); ListOrderVO result new ArrayList(); for (Order order : orders) { OrderVO vo convert(order); CouponInfo coupon couponClient.queryAvailableCoupon( userId, order.getShopId(), order.getTotalAmount() ); vo.setCouponInfo(coupon); result.add(vo); } return result;}Prompttext请检查下面代码是否存在可能导致接口耗时放大的结构性问题。 要求1. 只分析给出的代码2. 标记风险点3. 给出需要结合日志验证的点4. 不要直接重写整段代码5. 如果提出修改建议请说明可能引入的兼容性风险。 代码{代码片段}模型很快指出循环内调用couponClient.queryAvailableCoupon可能导致下游调用次数随订单数量线性增加。这个结论并不新鲜但在排查现场有用因为它和前面的慢请求样本能对上。之后我查调用链确实发现 pageSize20 时会触发 20 次 coupon-service 请求。平时 coupon-service 快的时候问题不明显一旦 Redis 延迟抬升主接口就被放大拖慢。最终根因不是单点慢 SQL而是两个因素叠加订单列表接口循环调用优惠券服务优惠券服务依赖 RedisRedis 在高峰期存在短暂延迟尖刺。第五步优化方案也要让 AI 参与“风险检查”解决方向很自然把循环内单次查询改成批量查询。改造前javafor (Order order : orders) { CouponInfo coupon couponClient.queryAvailableCoupon( userId, order.getShopId(), order.getTotalAmount() ); vo.setCouponInfo(coupon);}改造后思路javaListCouponQueryItem items orders.stream() .map(order - new CouponQueryItem( order.getId(), order.getShopId(), order.getTotalAmount() )) .toList(); MapString, CouponInfo couponMap couponClient.batchQueryAvailableCoupons(userId, items); for (Order order : orders) { OrderVO vo convert(order); vo.setCouponInfo(couponMap.get(order.getId())); result.add(vo);}这里我没有让 AI 直接生成最终代码而是让它检查风险text下面是一次接口优化方案将循环内单次 RPC 调用改为批量 RPC 调用。 请从兼容性和测试角度检查风险。 关注- 返回结果顺序- 部分订单查询失败- 空优惠券结果- 下游批量接口超时- 老逻辑与新逻辑结果一致性- 灰度和回滚策略。 请输出测试清单不要写实现代码。这一步输出的测试点比较实用text测试清单1. 单个订单有优惠券批量接口返回一致2. 单个订单无优惠券返回空对象还是 null 需确认3. 多订单返回顺序打乱时能否按 orderId 正确映射4. 部分订单查询失败时主接口是否降级5. batch 接口超时后是否影响订单列表主体展示6. pageSize1、20、50 时调用次数是否符合预期7. 新旧逻辑在灰度用户上的返回字段是否一致8. 下游接口异常时日志是否包含 traceId。其中“返回顺序打乱”这个点很容易漏。如果批量接口返回数组而调用方默认按顺序匹配就会埋坑。最后我们明确用orderId做映射不依赖返回顺序。AI 在这次排查里真正省了什么时间这次 AI 没有替我定位根因也没有替我上线代码。它省下的是这些时间从日志里整理时间线把现象归纳成假设表提醒需要补充哪些监控对代码片段做结构性风险扫描根据优化方案生成测试清单帮忙检查改造后的兼容性风险。这些工作平时都要做只是容易散在脑子里、文档里和聊天记录里。AI 的价值是把它们更快地结构化。但有几件事我不会交给 AI未脱敏生产日志完整数据库结构和客户数据线上配置修改决策根因最终裁定是否上线、是否回滚的判断。尤其是生产环境排查模型输出只能作为辅助线索不能替代监控、压测、代码 Review 和灰度验证。一个适合开发者复用的排查流程如果你也想把 AI 放进 Bug 排查或性能优化流程可以按下面这条线走text1. 收集监控摘要 ↓2. 脱敏日志和 traceId ↓3. 用脚本提取慢请求样本 ↓4. 让 AI 整理事实和时间线 ↓5. 让 AI 列假设与验证动作 ↓6. 人工执行验证命令 ↓7. 提供代码片段做风险 Review ↓8. 生成测试清单 ↓9. 压测、灰度、观察指标注意顺序先有数据再问模型。不要一开始就问“接口变慢是什么原因”这种问题上下文太少模型只能泛泛而谈。Prompt 写法里的几个细节我现在写排查类 Prompt会固定加几类约束text只基于我提供的信息不要补充不存在的系统背景。这句话能减少模型自行脑补架构。text把结论分成“明确事实”“合理假设”“证据不足”。这能避免它把猜测写得像确定结论。text每个建议都要给出验证方式。没有验证动作的建议在排查现场价值不大。text不要直接建议修改线上配置。生产环境里改配置比写代码更危险尤其是缓存、连接池、线程池这类参数。常见误区1. 把完整日志直接丢给 AI让它找根因不建议。日志太长、噪声太多模型容易忽略关键字段。更好的方式是先用脚本筛出慢请求、异常 traceId、时间窗口再让模型做归纳分析。2. AI 说 coupon-service 慢就能认定它是根因吗不能。它只能根据输入材料提出假设。是否成立要看下游监控、调用链、Redis 延迟、压测结果和代码逻辑是否能互相印证。3. AI 生成的优化代码可以直接提交吗最好不要。性能优化经常牵涉兼容性、降级策略、异常处理和灰度。AI 可以给思路但最终代码必须经过 Review、单元测试、接口测试和压测。4. 多模型对比有没有必要看任务复杂度。简单日志归纳用一个模型就够了涉及需求、代码、测试、风险判断时可以用不同模型交叉看一遍。但多模型输出不等于更正确最终还是看证据链。5. 生产日志怎么处理才安全至少去掉用户 ID、手机号、订单号、Token、内部域名、IP、数据库名、客户名称等敏感信息。公司有安全规范时优先按公司规范执行。结尾让 AI 参与排查但不要替你背锅这次慢接口排查给我的最大感受是AI 更适合做“排查助手”不适合做“线上负责人”。对开发者来说比较稳的用法是选一个高频、低风险、可验证的环节开始比如日志摘要、假设整理、测试清单生成输入材料先脱敏Prompt 里明确禁止脑补每个结论都要落到监控、日志、代码或压测结果上。真正决定问题是否修复的不是模型回答得像不像专家而是指标有没有下降、调用链有没有变短、测试有没有覆盖、灰度有没有异常。AI 能帮你少走弯路但线上问题的最终判断还是要回到工程证据。