上一篇【第18篇】用SkyWalking观察微服务的各个维度从宏观到微观的侦察术下一篇【第20篇】用SkyWalking查找失败服务——从告警到根因的完整追踪术上一篇我们学会了从宏观到微观的侦察术。但侦察只是第一步——找到敌人后你得判断哪个敌人最危险、最值得优先消灭。在微服务战场上最危险的敌人就是关键路径——那条拖慢全军的瓶颈链路。今天我们就来学习如何从SkyWalking中提取关键路径。1. 什么是关键路径1.1 关键路径的定义关键路径Critical Path是系统中对用户体验影响最大的请求链路——就像战场上最关键的运输线一旦这条线慢了整个战局都受影响。更准确地说关键路径有这些特征┌──────────────────────────────────────────────────────────────────┐ │ 关键路径的特征 │ │ │ │ 1. 业务重要性高 │ │ ──→ 下单/支付等核心业务路径 │ │ ──→ 不是后台统计/日志收集等辅助路径 │ │ │ │ 2. 调用链路深 │ │ ──→ 经过3个微服务的链路 │ │ ──→ 链路越深延迟累积越严重 │ │ │ │ 3. 流量占比大 │ │ ──→ 占总请求量的20%以上 │ │ ──→ 影面广优化收益大 │ │ │ │ 4. 延迟瓶颈明显 │ │ ──→ P99延迟远高于P50 │ │ ──→ 存在明显的尾部延迟 │ │ │ │ 5. 有下游依赖瓶颈 │ │ ──→ 链路中某个Span是延迟瓶颈 │ │ ──→ 优化这个Span就能改善整条路径 │ │ │ │ 示例 │ │ 关键路径 下单链路 │ │ gateway → user → order → inventory → payment → MySQL │ │ ──→ 这条链路涉及5个服务1个数据库 │ │ ──→ 任何一环变慢整个下单体验都变差 │ │ ──→ 这就是关键路径 │ └──────────────────────────────────────────────────────────────────┘1.2 关键路径 vs 非关键路径┌──────────────────────────────────────────────────────────────────┐ │ 关键路径 vs 非关键路径对比 │ │ │ │ 关键路径下单链路 │ │ gateway → user → order → inventory → payment → MySQL │ │ ──→ P99: 5s │ │ ──→ CPM: 200 (占总请求30%) │ │ ──→ 业务核心用户直接感知 │ │ ──→ 优化优先级最高 │ │ │ │ 非关键路径后台统计 │ │ gateway → admin → stats-service → MySQL │ │ ──→ P99: 2s │ │ ──→ CPM: 5 (占总请求1%) │ │ ──→ 业务辅助用户间接感知 │ │ ──→ 优化优先级低 │ │ │ │ 优化关键路径的收益 │ │ ──→ 下单体验改善 → 转化率提升 → 收入增加 │ │ ──→ 影响面大30%的请求 │ │ │ │ 优化非关键路径的收益 │ │ ──→ 后台统计变快 → 用户体验改善不明显 │ │ ──→ 影面小1%的请求 │ │ │ │ 结论优先优化关键路径 │ └──────────────────────────────────────────────────────────────────┘2. 从SkyWalking中识别关键业务路径2.1 识别关键路径的三步法┌──────────────────────────────────────────────────────────────────┐ │ 关键路径识别三步法 │ │ │ │ 步骤一列出所有业务链路 │ │ ──→ 在拓扑图中找到所有从User到终点的路径 │ │ ──→ 每条路径就是一个业务链路 │ │ │ │ 步骤二计算每条路径的影响力分数 │ │ ──→ 影响力 业务权重 × 流量占比 × P99延迟 │ │ ──→ 业务权重核心业务10, 辅助业务3, 后台1 │ │ ──→ 流量占比该路径CPM/总CPM │ │ ──→ P99延迟该路径的P99值 │ │ │ │ 步骤三影响力最高的路径就是关键路径 │ │ ──→ 对影响力最高的路径进行深度分析 │ │ ──→ 找到瓶颈Span制定优化方案 │ │ │ │ 示例计算 │ │ 下单路径: 10 × 30% × 5000ms 15000 (影响力最高) │ │ 查询路径: 8 × 40% × 500ms 1600 │ │ 统计路径: 1 × 1% × 2000ms 20 │ │ ──→ 下单路径是关键路径 │ └──────────────────────────────────────────────────────────────────┘2.2 从拓扑图找关键路径拓扑图是识别关键路径最直观的工具# 在UI中查看拓扑图# 1. 打开UI → General → Service# 2. 选择服务层级的拓扑图# 3. 观察从User节点出发的所有路径# 关键路径的特征在拓扑图中# - 调用链路深经过多个节点# - 链路CPM高线条粗# - 链路P99高线条颜色偏红/黄# - 链路Error高线条红色2.3 从Trace列表确认关键路径# 确认关键路径的Trace特征# 1. 在Trace列表中筛选关键业务的Trace# 2. 查看这些Trace的平均Span数# 3. 查看这些Trace的P99分布# 4. 确认瓶颈Span的位置# 示例下单Trace的平均结构# Span0: gateway (路由层)# Span1: user-service (身份验证)# Span2: order-service (创建订单)# Span3: inventory-service (扣减库存)# Span4: payment-service (发起支付)# Span5: MySQL (写入支付记录)# ──→ 6个Span链路深度足够长3. P50/P75/P99延迟分析3.1 百分位数的基础概念百分位数是理解延迟分布的核心工具。就像战场上统计伤亡——你不能只看平均伤亡率得看最惨的那1%部队的情况┌──────────────────────────────────────────────────────────────────┐ │ 百分位数的含义与类比 │ │ │ │ 假设1000个请求的响应时间分布 │ │ │ │ ┌──────────────────────────────────────────────┐ │ │ │ │ │ │ │ 500个请求 → 50ms (快) │ │ │ │ 250个请求 → 200ms (中等) │ │ │ │ 150个请求 → 500ms (慢) │ │ │ │ 90个请求 → 1000ms (很慢) │ │ │ │ 10个请求 → 5000ms (极慢) │ │ │ │ │ │ │ │ P50 50ms → 50%的请求在50ms内完成 │ │ │ │ P75 200ms → 75%的请求在200ms内完成 │ │ │ │ P90 500ms → 90%的请求在500ms内完成 │ │ │ │ P99 1000ms → 99%的请求在1秒内完成 │ │ │ │ P99.9 5000ms → 99.9%的请求在5秒内完成 │ │ │ │ │ │ │ │ 平均值 285ms → 被10个极慢请求拉偏 │ │ │ │ ──→ 平均值掩盖了尾部延迟问题 │ │ │ │ ──→ P99才能揭示真实的慢请求 │ │ │ └──────────────────────────────────────────────┘ │ │ │ │ 伤亡类比 │ │ P50 → 50%的部队伤亡1% → 大部分部队安全 │ │ P99 → 1%的部队伤亡10% → 少数部队惨烈 │ │ 平均 → 所有部队平均伤亡3% → 看似可控但掩盖极端 │ │ ──→ 你应该关注那1%伤亡10%的部队P99 │ └──────────────────────────────────────────────────────────────────┘3.2 P99与P50的差距分析P99和P50的差距越大说明尾部延迟越严重——这是识别瓶颈的关键指标# 在SkyWalking UI中查看百分位数# Service Dashboard → 响应时间面板# 健康服务的百分位数分布# P5050ms, P7580ms, P90120ms, P99200ms# ──→ P99/P50 4倍 → 分布紧凑尾部延迟可控# 有问题的百分位数分布# P5050ms, P7580ms, P90200ms, P995000ms# ──→ P99/P50 100倍 → 尾部延迟极严重# ──→ 1%的请求比正常请求慢100倍 → 需要重点排查差距分析表P99/P50倍数健度行动1-3倍健康正常监控3-10倍轻微尾部延迟关注趋势10-50倍明显尾部延迟排查慢请求50倍严重尾部延迟紧急排查3.3 百分位数的时间趋势# 观察百分位数的时间趋势# 在Dashboard中选择7天的时间范围# 正常趋势P50和P99曲线同步平稳# P50 ────────────────# P99 ──────────────── (与P50差距稳定)# 异常趋势P99曲线突然飙升# P50 ────────────────# P99 ────────/\/\/\/\ (与P50差距突然增大)# 退化趋势P99缓慢上升# P50 ────────────────# P99 ───────/──────── (差距缓慢增大)4. 慢Endpoint的识别与分析4.1 Endpoint排行——找最慢的APISkyWalking UI提供了Endpoint级别的排行功能——就像战场上的伤亡排行榜一眼看出哪个阵地最危险# 在UI中查看Endpoint排行# Service Dashboard → Endpoint响应时间排行# 排行示例payment-service# ┌─── Endpoint ─────── P99 ──── CPM ──── Error% ──┐# │ /api/pay 5000ms 200 8.2% │ ← 最慢最多错# │ /api/query 500ms 50 0.1% │# │ /api/refund 200ms 20 0% │# │ /health 10ms 200 0% │ ← 健康检查# └────────────────────────────────────────────────┘# /api/pay是慢Endpoint 错误Endpoint → 重点分析4.2 慢Endpoint分析步骤┌──────────────────────────────────────────────────────────────────┐ │ 慢Endpoint分析四步法 │ │ │ │ 第一步确认Endpoint的P99趋势 │ │ ──→ 是突然飙升还是缓慢退化 │ │ ──→ 突然飙升 → 可能是代码变更或配置变更 │ │ ──→ 缓慢退化 → 可能是数据量增长或资源消耗 │ │ │ │ 第二步看Endpoint的Trace样本 │ │ ──→ 篩选该Endpoint的慢TraceP99级别 │ │ ──→ 找到最慢的几个Trace │ │ ──→ 对比正常Trace和慢Trace的差异 │ │ │ │ 第三步找瓶颈Span │ │ ──→ 慢Trace中哪个Span最耗时 │ │ ──→ 是服务自身逻辑慢还是下游依赖慢 │ │ ──→ 如果是下游依赖 → 继续追踪到下游服务 │ │ │ │ 第四步定位根因 │ │ ──→ 看瓶颈Span的标签信息 │ │ │ 如果是数据库Span → 查SQL和执行计划 │ │ │ 如果是HTTP Span → 查下游服务的性能 │ │ │ 如果是MQ Span → 查消息队列的延迟 │ │ ──→ 制定优化方案 │ │ │ │ 示例 │ │ /api/pay慢 → 慢Trace → MySQL INSERT慢 → 锁等待超时 │ │ ──→ 根因支付表并发写入导致锁冲突 │ │ ──→ 优化分表/异步写入/减少锁范围 │ └──────────────────────────────────────────────────────────────────┘4.3 Endpoint慢的常见根因根因类型Trace中的体现优化方向数据库慢查询MySQL Span耗时高加索引/优化SQL/分库分表连接池耗尽等待Span耗时高增大连接池/减少单次占用时间内存不足GC Span耗时高增大堆内存/优化对象创建下游服务慢HTTP Span耗时高优化下游服务/加超时熔断锁竞争MySQL Lock wait Span减小锁范围/避免长事务N1查询多个短MySQL Span批量查询/JOIN替代5. 数据库慢查询在Trace中的体现5.1 数据库Span的标签信息SkyWalking的数据库插件会自动记录SQL语句和执行时间——就像战场上的弹药消耗记录每一发子弹都追踪到# 数据库Span的典型标签# component: mysql ← 数据库类型# db.type: mysql ← 数据库类型冗余但兼容旧版# db.instance: payment_db ← 数据库名# db.statement: INSERT INTO... ← SQL语句# db.bind_vars: id123,... ← 绑定参数部分版本支持5.2 慢查询的Trace识别┌──────────────────────────────────────────────────────────────────┐ │ 数据库慢查询在Trace中的识别 │ │ │ │ 慢查询类型一单条SQL耗时极长 │ │ ┌─ payment-service ──────────────────── 5000ms ──┐ │ │ │ ┌─ MySQL INSERT ──────────────── 4500ms ──┐ │ │ │ │ │ SQL: INSERT INTO payments (...) │ │ │ │ │ │ ──→ 一条SQL占了90%时间 │ │ │ │ │ │ ──→ 锁等待或索引缺失 │ │ │ │ │ └────────────────────────────────────────┘ │ │ │ └───────────────────────────────────────────────┘ │ │ │ │ 慢查询类型二N1问题多条小SQL │ │ ┌─ order-service ──────────────────── 3000ms ──┐ │ │ │ ┌─ MySQL SELECT ── 10ms ──┐ │ │ │ │ │ SQL: SELECT * FROM orders WHERE id1 │ │ │ │ └─────────────────────────┘ │ │ │ │ ┌─ MySQL SELECT ── 10ms ──┐ │ │ │ │ │ SQL: SELECT * FROM orders WHERE id2 │ │ │ │ └─────────────────────────┘ │ │ │ │ ┌─ MySQL SELECT ── 10ms ──┐ │ │ │ │ │ ...重复200次 │ │ │ │ └─────────────────────────┘ │ │ │ │ ──→ 每条SQL很快(10ms)但总量极大(200×102s) │ │ │ │ ──→ N1问题应该用一条批量查询替代 │ │ │ └───────────────────────────────────────────────┘ │ │ │ │ 慢查询类型三连接等待 │ │ ┌─ order-service ──────────────────── 5000ms ──┐ │ │ │ ┌─ MySQL (等待) ────── 3000ms ──┐ │ │ │ │ │ ──→ 不是SQL慢而是获取连接慢 │ │ │ │ │ ──→ 连接池耗尽或网络延迟 │ │ │ │ └───────────────────────────────┘ │ │ │ │ ┌─ MySQL SELECT ──── 200ms ──┐ │ │ │ │ │ ──→ 获取连接后SQL执行其实很快 │ │ │ │ └───────────────────────────────┘ │ │ │ └───────────────────────────────────────────────┘ │ └──────────────────────────────────────────────────────────────────┘5.3 慢查询的优化策略# 根据Trace中慢查询的类型选择优化策略# 类型一单条SQL慢 → 优化SQL本身# 方法加索引、优化JOIN、减少子查询、使用EXPLAIN分析# 类型二N1问题 → 批量查询# 方法一条JOIN/IN查询替代循环单条查询# 优化前for(Order order:orders){db.query(SELECT * FROM items WHERE order_id order.getId());}# 优化后db.query(SELECT * FROM items WHERE order_id IN ( ids ));# 类型三连接等待 → 增大连接池或减少占用# 方法增大maxPoolSize、减少查询时间、使用异步连接5.4 数据库Span的配置为了看到完整的SQL信息需要确保MySQL插件被正确激活# MySQL插件默认在plugins/目录中默认激活 # 如果没有看到SQL信息检查 # 1. 插件是否存在 ls plugins/ | grep mysql # 2. Agent日志中是否有MySQL拦截信息 grep mysql logs/skywalking-api.log # 3. 连接池追踪是否需要额外插件 mv optional-plugins/apm-dbcp2-plugin.jar plugins/ # DBCP2连接池 mv optional-plugins/apm-hikaricp-plugin.jar plugins/ # HikariCP连接池6. 关键路径优化实践6.1 优化ROI计算不是所有慢路径都需要优化——优化投入和收益需要计算ROI┌──────────────────────────────────────────────────────────────────┐ │ 关键路径优化ROI计算 │ │ │ │ 优化ROI 影面 × 改善幅度 / 优化成本 │ │ │ │ 路径A下单 │ │ 影面30%请求受影响 │ │ 改善P99从5s降到1s4秒改善 │ │ 成本2人×2周 4人周 │ │ ROI 30% × 4s / 4人周 0.3s/人周 │ │ │ │ 路径B统计 │ │ 影面1%请求受影响 │ │ 改善P99从2s降到500ms1.5秒改善 │ │ 成本1人×1周 1人周 │ │ ROI 1% × 1.5s / 1人周 0.015s/人周 │ │ │ │ ──→ 路径A的ROI是路径B的20倍 │ │ ──→ 优先优化路径A │ └──────────────────────────────────────────────────────────────────┘6.2 优化后验证优化完成后用SkyWalking验证效果# 优化前记录基准数据# P99: 5000ms, Error: 8.2%, Apdex: 0.6# 优化后对比改善数据# P99: 800ms (↓84%), Error: 0.5% (↓94%), Apdex: 0.92 (↑53%)# 验证步骤# 1. 在Dashboard中选择7天范围# 2. 对比优化前后的P99趋势# 3. 对比优化前后的Error率趋势# 4. 对比优化前后的Apdex趋势# 5. 如果改善显著 → 优化成功# 6. 如果改善不明显 → 继续排查7. 小结关键路径提取是性能优化的瞄准镜——找到最值得优化的目标关键路径定义业务重要性高、调用链路深、流量占比大、延迟瓶颈明显的链路识别三步法列出链路 → 计算影响力分数 → 找最高分的路径P99延迟分析P99/P50差距越大尾部延迟越严重慢Endpoint分析四步法确认趋势 → 看Trace → 找瓶颈Span → 定位根因数据库慢查询单条慢SQL、N1问题、连接等待三种类型优化ROI影响面×改善幅度/优化成本ROI最高的优先优化下一篇文章我们将从性能优化转向故障排查——用SkyWalking查找失败服务。上一篇【第18篇】用SkyWalking观察微服务的各个维度从宏观到微观的侦察术下一篇【第20篇】用SkyWalking查找失败服务——从告警到根因的完整追踪术
【SkyWalking从入门到精通】第19篇:用SkyWalking提取关键路径:找到拖慢全军的瓶颈链路
发布时间:2026/7/8 14:37:19
上一篇【第18篇】用SkyWalking观察微服务的各个维度从宏观到微观的侦察术下一篇【第20篇】用SkyWalking查找失败服务——从告警到根因的完整追踪术上一篇我们学会了从宏观到微观的侦察术。但侦察只是第一步——找到敌人后你得判断哪个敌人最危险、最值得优先消灭。在微服务战场上最危险的敌人就是关键路径——那条拖慢全军的瓶颈链路。今天我们就来学习如何从SkyWalking中提取关键路径。1. 什么是关键路径1.1 关键路径的定义关键路径Critical Path是系统中对用户体验影响最大的请求链路——就像战场上最关键的运输线一旦这条线慢了整个战局都受影响。更准确地说关键路径有这些特征┌──────────────────────────────────────────────────────────────────┐ │ 关键路径的特征 │ │ │ │ 1. 业务重要性高 │ │ ──→ 下单/支付等核心业务路径 │ │ ──→ 不是后台统计/日志收集等辅助路径 │ │ │ │ 2. 调用链路深 │ │ ──→ 经过3个微服务的链路 │ │ ──→ 链路越深延迟累积越严重 │ │ │ │ 3. 流量占比大 │ │ ──→ 占总请求量的20%以上 │ │ ──→ 影面广优化收益大 │ │ │ │ 4. 延迟瓶颈明显 │ │ ──→ P99延迟远高于P50 │ │ ──→ 存在明显的尾部延迟 │ │ │ │ 5. 有下游依赖瓶颈 │ │ ──→ 链路中某个Span是延迟瓶颈 │ │ ──→ 优化这个Span就能改善整条路径 │ │ │ │ 示例 │ │ 关键路径 下单链路 │ │ gateway → user → order → inventory → payment → MySQL │ │ ──→ 这条链路涉及5个服务1个数据库 │ │ ──→ 任何一环变慢整个下单体验都变差 │ │ ──→ 这就是关键路径 │ └──────────────────────────────────────────────────────────────────┘1.2 关键路径 vs 非关键路径┌──────────────────────────────────────────────────────────────────┐ │ 关键路径 vs 非关键路径对比 │ │ │ │ 关键路径下单链路 │ │ gateway → user → order → inventory → payment → MySQL │ │ ──→ P99: 5s │ │ ──→ CPM: 200 (占总请求30%) │ │ ──→ 业务核心用户直接感知 │ │ ──→ 优化优先级最高 │ │ │ │ 非关键路径后台统计 │ │ gateway → admin → stats-service → MySQL │ │ ──→ P99: 2s │ │ ──→ CPM: 5 (占总请求1%) │ │ ──→ 业务辅助用户间接感知 │ │ ──→ 优化优先级低 │ │ │ │ 优化关键路径的收益 │ │ ──→ 下单体验改善 → 转化率提升 → 收入增加 │ │ ──→ 影响面大30%的请求 │ │ │ │ 优化非关键路径的收益 │ │ ──→ 后台统计变快 → 用户体验改善不明显 │ │ ──→ 影面小1%的请求 │ │ │ │ 结论优先优化关键路径 │ └──────────────────────────────────────────────────────────────────┘2. 从SkyWalking中识别关键业务路径2.1 识别关键路径的三步法┌──────────────────────────────────────────────────────────────────┐ │ 关键路径识别三步法 │ │ │ │ 步骤一列出所有业务链路 │ │ ──→ 在拓扑图中找到所有从User到终点的路径 │ │ ──→ 每条路径就是一个业务链路 │ │ │ │ 步骤二计算每条路径的影响力分数 │ │ ──→ 影响力 业务权重 × 流量占比 × P99延迟 │ │ ──→ 业务权重核心业务10, 辅助业务3, 后台1 │ │ ──→ 流量占比该路径CPM/总CPM │ │ ──→ P99延迟该路径的P99值 │ │ │ │ 步骤三影响力最高的路径就是关键路径 │ │ ──→ 对影响力最高的路径进行深度分析 │ │ ──→ 找到瓶颈Span制定优化方案 │ │ │ │ 示例计算 │ │ 下单路径: 10 × 30% × 5000ms 15000 (影响力最高) │ │ 查询路径: 8 × 40% × 500ms 1600 │ │ 统计路径: 1 × 1% × 2000ms 20 │ │ ──→ 下单路径是关键路径 │ └──────────────────────────────────────────────────────────────────┘2.2 从拓扑图找关键路径拓扑图是识别关键路径最直观的工具# 在UI中查看拓扑图# 1. 打开UI → General → Service# 2. 选择服务层级的拓扑图# 3. 观察从User节点出发的所有路径# 关键路径的特征在拓扑图中# - 调用链路深经过多个节点# - 链路CPM高线条粗# - 链路P99高线条颜色偏红/黄# - 链路Error高线条红色2.3 从Trace列表确认关键路径# 确认关键路径的Trace特征# 1. 在Trace列表中筛选关键业务的Trace# 2. 查看这些Trace的平均Span数# 3. 查看这些Trace的P99分布# 4. 确认瓶颈Span的位置# 示例下单Trace的平均结构# Span0: gateway (路由层)# Span1: user-service (身份验证)# Span2: order-service (创建订单)# Span3: inventory-service (扣减库存)# Span4: payment-service (发起支付)# Span5: MySQL (写入支付记录)# ──→ 6个Span链路深度足够长3. P50/P75/P99延迟分析3.1 百分位数的基础概念百分位数是理解延迟分布的核心工具。就像战场上统计伤亡——你不能只看平均伤亡率得看最惨的那1%部队的情况┌──────────────────────────────────────────────────────────────────┐ │ 百分位数的含义与类比 │ │ │ │ 假设1000个请求的响应时间分布 │ │ │ │ ┌──────────────────────────────────────────────┐ │ │ │ │ │ │ │ 500个请求 → 50ms (快) │ │ │ │ 250个请求 → 200ms (中等) │ │ │ │ 150个请求 → 500ms (慢) │ │ │ │ 90个请求 → 1000ms (很慢) │ │ │ │ 10个请求 → 5000ms (极慢) │ │ │ │ │ │ │ │ P50 50ms → 50%的请求在50ms内完成 │ │ │ │ P75 200ms → 75%的请求在200ms内完成 │ │ │ │ P90 500ms → 90%的请求在500ms内完成 │ │ │ │ P99 1000ms → 99%的请求在1秒内完成 │ │ │ │ P99.9 5000ms → 99.9%的请求在5秒内完成 │ │ │ │ │ │ │ │ 平均值 285ms → 被10个极慢请求拉偏 │ │ │ │ ──→ 平均值掩盖了尾部延迟问题 │ │ │ │ ──→ P99才能揭示真实的慢请求 │ │ │ └──────────────────────────────────────────────┘ │ │ │ │ 伤亡类比 │ │ P50 → 50%的部队伤亡1% → 大部分部队安全 │ │ P99 → 1%的部队伤亡10% → 少数部队惨烈 │ │ 平均 → 所有部队平均伤亡3% → 看似可控但掩盖极端 │ │ ──→ 你应该关注那1%伤亡10%的部队P99 │ └──────────────────────────────────────────────────────────────────┘3.2 P99与P50的差距分析P99和P50的差距越大说明尾部延迟越严重——这是识别瓶颈的关键指标# 在SkyWalking UI中查看百分位数# Service Dashboard → 响应时间面板# 健康服务的百分位数分布# P5050ms, P7580ms, P90120ms, P99200ms# ──→ P99/P50 4倍 → 分布紧凑尾部延迟可控# 有问题的百分位数分布# P5050ms, P7580ms, P90200ms, P995000ms# ──→ P99/P50 100倍 → 尾部延迟极严重# ──→ 1%的请求比正常请求慢100倍 → 需要重点排查差距分析表P99/P50倍数健度行动1-3倍健康正常监控3-10倍轻微尾部延迟关注趋势10-50倍明显尾部延迟排查慢请求50倍严重尾部延迟紧急排查3.3 百分位数的时间趋势# 观察百分位数的时间趋势# 在Dashboard中选择7天的时间范围# 正常趋势P50和P99曲线同步平稳# P50 ────────────────# P99 ──────────────── (与P50差距稳定)# 异常趋势P99曲线突然飙升# P50 ────────────────# P99 ────────/\/\/\/\ (与P50差距突然增大)# 退化趋势P99缓慢上升# P50 ────────────────# P99 ───────/──────── (差距缓慢增大)4. 慢Endpoint的识别与分析4.1 Endpoint排行——找最慢的APISkyWalking UI提供了Endpoint级别的排行功能——就像战场上的伤亡排行榜一眼看出哪个阵地最危险# 在UI中查看Endpoint排行# Service Dashboard → Endpoint响应时间排行# 排行示例payment-service# ┌─── Endpoint ─────── P99 ──── CPM ──── Error% ──┐# │ /api/pay 5000ms 200 8.2% │ ← 最慢最多错# │ /api/query 500ms 50 0.1% │# │ /api/refund 200ms 20 0% │# │ /health 10ms 200 0% │ ← 健康检查# └────────────────────────────────────────────────┘# /api/pay是慢Endpoint 错误Endpoint → 重点分析4.2 慢Endpoint分析步骤┌──────────────────────────────────────────────────────────────────┐ │ 慢Endpoint分析四步法 │ │ │ │ 第一步确认Endpoint的P99趋势 │ │ ──→ 是突然飙升还是缓慢退化 │ │ ──→ 突然飙升 → 可能是代码变更或配置变更 │ │ ──→ 缓慢退化 → 可能是数据量增长或资源消耗 │ │ │ │ 第二步看Endpoint的Trace样本 │ │ ──→ 篩选该Endpoint的慢TraceP99级别 │ │ ──→ 找到最慢的几个Trace │ │ ──→ 对比正常Trace和慢Trace的差异 │ │ │ │ 第三步找瓶颈Span │ │ ──→ 慢Trace中哪个Span最耗时 │ │ ──→ 是服务自身逻辑慢还是下游依赖慢 │ │ ──→ 如果是下游依赖 → 继续追踪到下游服务 │ │ │ │ 第四步定位根因 │ │ ──→ 看瓶颈Span的标签信息 │ │ │ 如果是数据库Span → 查SQL和执行计划 │ │ │ 如果是HTTP Span → 查下游服务的性能 │ │ │ 如果是MQ Span → 查消息队列的延迟 │ │ ──→ 制定优化方案 │ │ │ │ 示例 │ │ /api/pay慢 → 慢Trace → MySQL INSERT慢 → 锁等待超时 │ │ ──→ 根因支付表并发写入导致锁冲突 │ │ ──→ 优化分表/异步写入/减少锁范围 │ └──────────────────────────────────────────────────────────────────┘4.3 Endpoint慢的常见根因根因类型Trace中的体现优化方向数据库慢查询MySQL Span耗时高加索引/优化SQL/分库分表连接池耗尽等待Span耗时高增大连接池/减少单次占用时间内存不足GC Span耗时高增大堆内存/优化对象创建下游服务慢HTTP Span耗时高优化下游服务/加超时熔断锁竞争MySQL Lock wait Span减小锁范围/避免长事务N1查询多个短MySQL Span批量查询/JOIN替代5. 数据库慢查询在Trace中的体现5.1 数据库Span的标签信息SkyWalking的数据库插件会自动记录SQL语句和执行时间——就像战场上的弹药消耗记录每一发子弹都追踪到# 数据库Span的典型标签# component: mysql ← 数据库类型# db.type: mysql ← 数据库类型冗余但兼容旧版# db.instance: payment_db ← 数据库名# db.statement: INSERT INTO... ← SQL语句# db.bind_vars: id123,... ← 绑定参数部分版本支持5.2 慢查询的Trace识别┌──────────────────────────────────────────────────────────────────┐ │ 数据库慢查询在Trace中的识别 │ │ │ │ 慢查询类型一单条SQL耗时极长 │ │ ┌─ payment-service ──────────────────── 5000ms ──┐ │ │ │ ┌─ MySQL INSERT ──────────────── 4500ms ──┐ │ │ │ │ │ SQL: INSERT INTO payments (...) │ │ │ │ │ │ ──→ 一条SQL占了90%时间 │ │ │ │ │ │ ──→ 锁等待或索引缺失 │ │ │ │ │ └────────────────────────────────────────┘ │ │ │ └───────────────────────────────────────────────┘ │ │ │ │ 慢查询类型二N1问题多条小SQL │ │ ┌─ order-service ──────────────────── 3000ms ──┐ │ │ │ ┌─ MySQL SELECT ── 10ms ──┐ │ │ │ │ │ SQL: SELECT * FROM orders WHERE id1 │ │ │ │ └─────────────────────────┘ │ │ │ │ ┌─ MySQL SELECT ── 10ms ──┐ │ │ │ │ │ SQL: SELECT * FROM orders WHERE id2 │ │ │ │ └─────────────────────────┘ │ │ │ │ ┌─ MySQL SELECT ── 10ms ──┐ │ │ │ │ │ ...重复200次 │ │ │ │ └─────────────────────────┘ │ │ │ │ ──→ 每条SQL很快(10ms)但总量极大(200×102s) │ │ │ │ ──→ N1问题应该用一条批量查询替代 │ │ │ └───────────────────────────────────────────────┘ │ │ │ │ 慢查询类型三连接等待 │ │ ┌─ order-service ──────────────────── 5000ms ──┐ │ │ │ ┌─ MySQL (等待) ────── 3000ms ──┐ │ │ │ │ │ ──→ 不是SQL慢而是获取连接慢 │ │ │ │ │ ──→ 连接池耗尽或网络延迟 │ │ │ │ └───────────────────────────────┘ │ │ │ │ ┌─ MySQL SELECT ──── 200ms ──┐ │ │ │ │ │ ──→ 获取连接后SQL执行其实很快 │ │ │ │ └───────────────────────────────┘ │ │ │ └───────────────────────────────────────────────┘ │ └──────────────────────────────────────────────────────────────────┘5.3 慢查询的优化策略# 根据Trace中慢查询的类型选择优化策略# 类型一单条SQL慢 → 优化SQL本身# 方法加索引、优化JOIN、减少子查询、使用EXPLAIN分析# 类型二N1问题 → 批量查询# 方法一条JOIN/IN查询替代循环单条查询# 优化前for(Order order:orders){db.query(SELECT * FROM items WHERE order_id order.getId());}# 优化后db.query(SELECT * FROM items WHERE order_id IN ( ids ));# 类型三连接等待 → 增大连接池或减少占用# 方法增大maxPoolSize、减少查询时间、使用异步连接5.4 数据库Span的配置为了看到完整的SQL信息需要确保MySQL插件被正确激活# MySQL插件默认在plugins/目录中默认激活 # 如果没有看到SQL信息检查 # 1. 插件是否存在 ls plugins/ | grep mysql # 2. Agent日志中是否有MySQL拦截信息 grep mysql logs/skywalking-api.log # 3. 连接池追踪是否需要额外插件 mv optional-plugins/apm-dbcp2-plugin.jar plugins/ # DBCP2连接池 mv optional-plugins/apm-hikaricp-plugin.jar plugins/ # HikariCP连接池6. 关键路径优化实践6.1 优化ROI计算不是所有慢路径都需要优化——优化投入和收益需要计算ROI┌──────────────────────────────────────────────────────────────────┐ │ 关键路径优化ROI计算 │ │ │ │ 优化ROI 影面 × 改善幅度 / 优化成本 │ │ │ │ 路径A下单 │ │ 影面30%请求受影响 │ │ 改善P99从5s降到1s4秒改善 │ │ 成本2人×2周 4人周 │ │ ROI 30% × 4s / 4人周 0.3s/人周 │ │ │ │ 路径B统计 │ │ 影面1%请求受影响 │ │ 改善P99从2s降到500ms1.5秒改善 │ │ 成本1人×1周 1人周 │ │ ROI 1% × 1.5s / 1人周 0.015s/人周 │ │ │ │ ──→ 路径A的ROI是路径B的20倍 │ │ ──→ 优先优化路径A │ └──────────────────────────────────────────────────────────────────┘6.2 优化后验证优化完成后用SkyWalking验证效果# 优化前记录基准数据# P99: 5000ms, Error: 8.2%, Apdex: 0.6# 优化后对比改善数据# P99: 800ms (↓84%), Error: 0.5% (↓94%), Apdex: 0.92 (↑53%)# 验证步骤# 1. 在Dashboard中选择7天范围# 2. 对比优化前后的P99趋势# 3. 对比优化前后的Error率趋势# 4. 对比优化前后的Apdex趋势# 5. 如果改善显著 → 优化成功# 6. 如果改善不明显 → 继续排查7. 小结关键路径提取是性能优化的瞄准镜——找到最值得优化的目标关键路径定义业务重要性高、调用链路深、流量占比大、延迟瓶颈明显的链路识别三步法列出链路 → 计算影响力分数 → 找最高分的路径P99延迟分析P99/P50差距越大尾部延迟越严重慢Endpoint分析四步法确认趋势 → 看Trace → 找瓶颈Span → 定位根因数据库慢查询单条慢SQL、N1问题、连接等待三种类型优化ROI影响面×改善幅度/优化成本ROI最高的优先优化下一篇文章我们将从性能优化转向故障排查——用SkyWalking查找失败服务。上一篇【第18篇】用SkyWalking观察微服务的各个维度从宏观到微观的侦察术下一篇【第20篇】用SkyWalking查找失败服务——从告警到根因的完整追踪术