故障诊断闭环 — 从发现问题到修复验证,一条链路走通
以前排障 = 查日志 → 猜 → 加日志 → 重跑 → 再猜 → 再加日志……
现在排障 = 看故事 → 点一下 → 到代码 → 修复 → 验证。
传统排障有多痛
场景:线上报错了,用户投诉
没有 dlz-lens 的时候
第 1 步:接到告警 / 用户反馈
↓
第 2 步:查日志系统
→ 搜索 error 关键字
→ 找到异常堆栈
→ 看到 SQL 错误,但不知道是哪个接口触发的
→ 也不知道传入的参数是什么
↓
第 3 步:猜
→ 根据异常里的类名,大概猜到是哪个接口
→ 但这个类可能被好几个地方调用,不确定是哪条路径
↓
第 4 步:加日志
→ 在怀疑的地方加 log.info() 打印参数
→ 加 log.info() 打印 traceId
→ 改代码 → 提交 → 发布到测试环境
↓
第 5 步:重现
→ 测一下,看看能不能重现
→ 不能重现?再猜,再加日志
→ 能重现?看新加的日志输出
↓
第 6 步:定位根因
→ 哦,原来是这个参数传错了
→ 哦,原来是这里 N+1 了
→ 哦,原来是事务里调了 HTTP
↓
第 7 步:修复 → 发布 → 验证
总耗时:30 分钟 ~ 半天,取决于问题好不好猜
核心痛点:信息不全 → 靠猜 → 反复加日志 → 反复重跑。低效、痛苦、依赖经验。
有 dlz-lens 的时候
第 1 步:接到告警 / 用户反馈
↓
第 2 步:打开 dlz-lens → 故事回放
→ 筛选 500 错误的请求
→ 找到出错的那个故事
↓
第 3 步:看故事时间线
→ 一眼看到:第 4 条 SQL 执行失败了
→ 错误信息:Duplicate entry 'xxx' for key 'uk_order_no'
→ 参数是什么、调用者是谁、在不在事务里——清清楚楚
↓
第 4 步:点一下调用者 → 直接跳到代码行
→ IDEA 自动打开,光标定位到出问题的那行
→ 上下文一目了然
↓
第 5 步:修复 → 发布 → 重跑接口 → 看故事验证
总耗时:3 ~ 5 分钟
区别:不是"猜 → 验证 → 再猜",是"看 → 定位 → 修复"。
完整的诊断闭环
dlz-lens 提供的不是一个"看 SQL 的面板",是一条完整的故障诊断链路。
第一步:发现问题
怎么发现?
| 入口 | 你会看到 |
|---|---|
| 实时监控 Tab | 新出现的红色错误调用、橙色慢调用 |
| 故事回放 Tab | 红色 500 错误的请求、橙色慢请求、紫色 N+1 标签 |
| 顶部状态栏 | 错误数突然飙升、慢 SQL 数突然增加 |
不用盯着控制台等——你可以正常开发、正常测试,有问题的时候过来一看就知道。
第二步:定位根因
从外到内,三层定位:
第一层:哪个请求有问题?
在故事列表里,有问题的请求会用颜色标记出来——红色错误、橙色慢、紫色 N+1。一眼就能挑出来。
第二层:这个请求里哪一步有问题?
点进故事,看时间线。哪步报错了、哪步最慢、哪步看起来不正常——都在时间线上清清楚楚。
第三层:这步是哪行代码触发的?
点一下调用者,直接跳 IDE。到了代码行,上下文就在眼前——为什么会执行到这里、参数怎么传过来的、逻辑是什么——一目了然。
三层定位,层层递进。从"哪个接口有问题"到"哪行代码有问题",不超过 10 秒。
第三步:修复验证
改完代码,重新跑一下接口,再看故事回放:
- 错误还在吗?→ 验证修复有效性
- 耗时降下来了吗?→ 验证性能优化效果
- N+1 消除了吗?→ 验证重构效果
- 事务范围对了吗?→ 验证事务调整
修复前的故事 vs 修复后的故事,对比一下就知道有没有修好。
常见故障的诊断路径
🔴 场景 1:接口 500 报错
诊断路径:
- 故事回放 → 筛选 500 → 找到报错请求
- 看时间线 → 找到红色错误的那步调用
- 看错误信息 → 知道了是什么异常
- 看参数 → 知道了传的是什么值
- 点调用者 → 跳代码 → 分析为什么会出错
- 修复 → 重跑 → 验证
耗时:3 分钟。
🐢 场景 2:接口很慢
诊断路径:
- 故事回放 → 找到慢请求
- 看时间线 → 看耗时分布
- 是某一条 SQL 特别慢?→ 去优化那条 SQL
- 是 N 条小 SQL 加起来慢?→ 看是不是 N+1
- 是 Redis 慢?→ 查 Redis
- 是下游 HTTP 慢?→ 找下游 / 加缓存
- 点调用者 → 跳代码 → 看上下文
- 优化 → 重跑 → 对比优化前后的故事
耗时:5 分钟。
🔄 场景 3:N+1 问题
怎么发现的:
- 故事列表里有紫色 N+1 标签
- 时间线上出现一组长得很像的调用(比如循环查同一个表)
- 统计里 SQL 数量明显偏多
诊断路径:
- 故事回放 → 找到 N+1 标记的请求
- 看时间线 → 确认是哪里在循环查
- 点调用者 → 跳代码 → 找到循环位置
- 改成批量查询 / 预加载
- 重跑 → 验证 SQL 数量是不是降下来了
耗时:5 分钟。
以前找 N+1 全靠经验和眼力——看日志里一堆相似的 SQL,猜是哪里循环查的。
现在?dlz-lens 直接帮你标出来,紫色标签明明白白。
⚠️ 场景 4:事务问题
怎么发现的:
- 故事列表里有黄色"事务风险"标签
- 时间线上事务竖线特别长(事务过大)
- 事务里出现了 HTTP / Redis 等不该有的调用
常见事务问题:
| 问题 | 表现 | 风险等级 |
|---|---|---|
| 事务里调 HTTP | 事务竖线里有 HTTP 调用 | 🔴 高 |
| 事务过大 | 事务里有 10+ 条调用,持续时间长 | 🟠 中 |
| 事务里有 N+1 | 事务里循环查数据 | 🟠 中 |
| 不必要的事务 | 只读查询也开了事务 | 🟡 低 |
| 事务外发 MQ | MQ 在 COMMIT 之前发 | 🟠 中(可能发了消息但事务回滚) |
诊断路径:
- 故事回放 → 找到事务风险标记的请求
- 看时间线 → 看事务范围里有什么
- 点 BEGIN 的调用者 → 跳代码 → 看事务声明在哪
- 调整事务范围 / 去掉不必要的事务
- 重跑 → 验证事务范围是不是合理了
为什么这是"闭环"
传统排障是开环的——你永远不知道信息够不够,总在猜,总在加日志,反复验证。
dlz-lens 的排障是闭环的:
发现问题 → 定位根因 → 修复代码 → 验证效果
↑ ↓
└────────────────────────────┘
(验证后再发现新问题,继续循环)
每一步都有足够的信息,不需要猜,不需要额外加日志。发现了问题就能定位,定位了就能修复,修复了就能验证。一条链路走通。
真实案例对比
案例:生产环境订单创建偶尔失败
没有 dlz-lens 的排查过程
Day 1: 用户反馈偶尔下单失败
↓
查日志 → 看到 DuplicateKeyException
↓
猜:是不是订单号重复了?
↓
加日志 → 打印订单号生成逻辑
↓
发测试环境 → 没重现出来
Day 2: 继续猜
↓
会不会是并发问题?
↓
加更多日志 → 打印事务状态、打印线程号
↓
压测 → 还是没重现
Day 3: 终于在生产抓到一次
↓
分析日志 → 发现是两个请求生成了同一个订单号
↓
哦,订单号生成器在并发场景下有问题
↓
修复 → 发布
总耗时:3 天
有 dlz-lens 的排查过程
用户反馈偶尔下单失败
↓
打开 dlz-lens → 故事回放 → 筛选 500 错误
↓
找到失败的请求 → 看时间线
↓
第 3 条 INSERT 报错:Duplicate entry 'ORD2026081100123'
↓
点调用者 → 跳到 OrderNoGenerator.java:25
↓
看代码:哦,这个生成器没有考虑并发
↓
修复(加分布式锁 / 用号段模式)
↓
重跑并发测试 → 看故事 → 没有重复了
总耗时:15 分钟
这不是夸张。这是每一个后端开发者都经历过的痛点——信息不够的时候,排障全靠猜,而猜是最浪费时间的。
dlz-lens 给你的,就是足够的信息,让你不用猜。
不只是排障工具
故障诊断闭环是 dlz-lens 最直观的价值,但它的用处不止于此:
| 场景 | 怎么用 | 节省的时间 |
|---|---|---|
| 开发调试 | 写代码时实时看 IO 调用对不对 | 每次调试省 5-10 分钟 |
| 性能优化 | 看故事找瓶颈,不瞎优化 | 每次优化省 30 分钟 |
| Code Review | 跑一遍接口看故事,找隐藏问题 | 每次 CR 省 15 分钟 |
| 新人上手 | 跑核心接口看故事,懂业务流程 | 新人上手时间缩短 50% |
| 技术分享 | 用故事时间线讲解系统架构 | 一听就懂,不用脑补 |
把这些加起来,一个开发者每周至少能省出 2-3 小时。
而这一切,只需要加一个依赖,加一行配置。