全链路追踪
概述
一次游戏请求会穿越网关、逻辑服、DB、Redis、MQ,问题到底出在哪一环?全链路追踪把一次请求的跨服务调用串成一条链,一眼看到每一跳的耗时与状态。本文讲 OpenTelemetry 标准、SkyWalking/Jaeger 落地,以及用链路定位性能瓶颈的方法。
一、链路追踪基础
1.1 核心概念
链路追踪三要素:
TraceId:一次请求全局唯一 ID
SpanId:一次调用单元(调用 DB、调用 RPC)唯一 ID
ParentSpanId:父调用(组成调用树)
示例(充值链路):
traceId: a1b2
├─ span: gateway 入口 (5ms)
├─ span: 调逻辑服 RPC (40ms)
│ ├─ span: 查玩家 (8ms)
│ ├─ span: 调支付 (20ms)
│ └─ span: 发 MQ (2ms)
└─ span: 返回客户端1.2 TraceId 透传
透传链:
客户端 → 网关(协议头带/生成 traceId)
网关 → 逻辑服(RPC 头)
逻辑服 → DB/Redis(探针自动注入)
逻辑服 → MQ(消息头)
实现:
OpenTelemetry SDK 自动注入(HTTP/gRPC/JDBC/Redis 插件)
MQ 手动透传(消息 header 带 trace 上下文)// 手动透传 MQ 消息头
Headers traceHeaders = tracer.injectCarrier();
kafkaTemplate.send(topic, msg,
record -> record.headers().add("traceparent",
traceHeaders.toBytes()));二、OpenTelemetry 与选型
2.1 OpenTelemetry 标准
OpenTelemetry(CNCF 标准):
统一 API/SDK(多语言)
自动插桩(主流框架插件)
导出器(Exporter):可对接任意后端
对比:
自研 TraceId 日志串联(日志章节):只能日志层面串
OpenTelemetry:自动埋点 + 调用树 + 耗时统计
接入方式:
Agent 注入(Java Agent,零侵入)
SDK 手动埋点(精确控制)// Java Agent 方式(零侵入)
java -javaagent:opentelemetry-javaagent.jar \
-Dotel.service.name=game-logic \
-Dotel.exporter.otlp.endpoint=http://collector:4317 \
-jar game-logic.jar2.2 SkyWalking vs Jaeger
SkyWalking:
国产、APM 全家桶(链路 + 指标 + 拓扑)
部署简单(OAP + 前端)
适合与监控统一运维
Jaeger:
CNCF、聚焦链路(开源标准)
查询灵活(Trace 对比/查找)
与 Prometheus 生态配合好
选型:
要拓扑图/一站式 → SkyWalking
只要链路 + 已有 Prometheus → Jaeger
(本文以 SkyWalking 为主示例)// SkyWalking Agent 接入
java -javaagent:skywalking-agent.jar \
-Dskywalking.agent.service_name=game-logic \
-Dskywalking.collector.backend_service=oap:11800 \
-jar game-logic.jar三、链路可视化
3.1 拓扑图
服务拓扑:
SkyWalking 自动绘制服务间调用关系
箭头 + 耗时 + 调用量
一眼看出:调用链在哪跳最慢、哪个服务被大量调用
用法:
服务层级(网关 → 逻辑 → DB/Redis/MQ)
异常链路高亮(错误 Span 标红)3.2 Trace 查询
Trace 查询:
按 TraceId 精确查(从日志拿)
按服务/接口/时间范围筛选
慢调用 Top(按耗时排序)
错误链路(状态码/异常类型过滤)
分析方法:
逐跳耗时对比(哪一跳占大头)
出现大 Gap → 该处卡住(锁/GC/等待)
重复调用 → 循环调用问题// 链路分析步骤
1. 拿到慢请求 TraceId
2. 看整条链总耗时 vs 各 Span 耗时和
3. 定位最大耗时 Span(如 DB 查询 300ms)
4. 下钻该 Span(SQL/参数/缓存命中)
5. 优化 → 复测对比四、性能瓶颈链路分析
4.1 常见瓶颈模式
常见链路瓶颈:
DB 慢查询(索引缺失/锁等待)
Redis 大 Key / 热 Key(单点慢)
RPC 超时重试(雪崩)
MQ 积压(消费慢)
锁等待(同玩家串行链路过长)
GC 停顿(链路出现周期性大 Gap)// 瓶颈定位口诀
慢在单跳 → 该组件优化(SQL/缓存/连接池)
慢在等待 → 锁/队列/线程池
周期慢 → GC / 定时任务
全链慢 → 网络/基础资源/大请求体4.2 与监控联动
链路 + 监控联动:
链路发现"DB 耗时高"
→ 监控面板确认 DB 慢查询/连接池
→ 日志检索 SQL 详情
→ 三平台互查定位根因
告警联动:
链路错误率 → 监控告警
告警附 TraceId 样本 → 直接进链路分析// 一次真实排查示例
现象:对局偶发卡顿
链路:room 服务 span 出现 800ms Gap
监控:GC 周期与卡顿时间吻合
根因:GC 停顿
方案:JVM 参数调整(见 JVM 调优章节)五、实现要点
全链路追踪核心:
TraceId 全链路透传(客户端 → 网关 → 逻辑 → 存储)
OpenTelemetry 标准 + SkyWalking/Jaeger
拓扑图 + Trace 查询 + 慢链路分析
与监控/日志三平台联动定位根因
常见坑:
只做日志 TraceId 不采集调用树 → 看不出耗时分布
不透传 MQ/异步线程 → 链路断裂
采样率过高 → 存储成本
只搭平台无人用 → 沉淀排查 SOP
与其他系统衔接:
日志 TraceId → 日志审计章节
指标监控 → 实时监控章节
性能调优 → 性能优化章节
排查 SOP → 运维手册