文章目录
-
- 一、开篇:第26课留下的"盲区"
- 二、分布式追踪理论基础
-
- [2.1 Dapper论文的核心思想](#2.1 Dapper论文的核心思想)
- [2.2 三大核心概念:Trace、Segment、Span](#2.2 三大核心概念:Trace、Segment、Span)
- [2.3 上下文传播:跨服务追踪的核心](#2.3 上下文传播:跨服务追踪的核心)
- 三、SkyWalking架构深度剖析
-
- [3.1 四层架构:Probe → OAP → Storage → UI](#3.1 四层架构:Probe → OAP → Storage → UI)
- [3.2 核心数据模型](#3.2 核心数据模型)
- [3.3 Java Agent的字节码增强原理](#3.3 Java Agent的字节码增强原理)
- 四、SkyWalking部署实战
-
- [4.1 Docker Quick Start部署](#4.1 Docker Quick Start部署)
- [4.2 验证部署](#4.2 验证部署)
- [五、Java Agent探针配置](#五、Java Agent探针配置)
-
- [5.1 下载Agent](#5.1 下载Agent)
- [5.2 核心配置项](#5.2 核心配置项)
- [5.3 配置覆盖优先级](#5.3 配置覆盖优先级)
- [5.4 Spring Boot应用的启动配置](#5.4 Spring Boot应用的启动配置)
- [5.5 Gateway与OpenFeign的链路透传](#5.5 Gateway与OpenFeign的链路透传)
- [5.6 日志中注入TraceID](#5.6 日志中注入TraceID)
- 六、调用链路分析与拓扑图实战
-
- [6.1 验证链路数据](#6.1 验证链路数据)
- [6.2 拓扑图解读](#6.2 拓扑图解读)
- [6.3 链路详情分析](#6.3 链路详情分析)
- [6.4 性能瓶颈排查实战](#6.4 性能瓶颈排查实战)
- [6.5 日志与链路的联动](#6.5 日志与链路的联动)
- 七、生产采样策略与性能优化
-
- [7.1 采样率配置](#7.1 采样率配置)
- [7.2 OAP Server性能调优](#7.2 OAP Server性能调优)
- [7.3 Agent性能优化](#7.3 Agent性能优化)
- [7.4 SkyWalking与Micrometer Tracing的协同](#7.4 SkyWalking与Micrometer Tracing的协同)
- 八、踩坑指南
-
- 坑一:Agent版本与OAP版本不匹配
- 坑二:Gateway自定义过滤器覆盖了sw8头
- 坑三:异步线程中链路断裂
- 坑四:采样率为0导致无数据
- 坑五:Elasticsearch存储空间快速增长
- [坑六:JDK 21下Agent兼容性问题](#坑六:JDK 21下Agent兼容性问题)
- 九、课后作业
- 十、下节预告
- [🔗《最新版 SpringCloud 2025 从入门到实战》系列课程导航](#🔗《最新版 SpringCloud 2025 从入门到实战》系列课程导航)

适配版本 :Apache SkyWalking 10.4.0(OAP + UI + Java Agent)、Spring Boot 4.0.8、Spring Cloud 2025.1.3(Oakwood)、JDK 21
课程定位:监控追踪阶段进阶篇,从分布式追踪理论到SkyWalking架构,从探针配置到链路分析,构建全链路可观测性能力
一、开篇:第26课留下的"盲区"
第26课我们完成了Prometheus+Grafana的指标监控体系。通过http_server_requests_seconds指标,我们能看到service-order的P95延迟从50ms飙升到了3秒。但指标只告诉了你"慢了 ",没有告诉你"为什么慢"。
是service-user的数据库查询慢了?还是service-product的Feign调用超时了?还是service-order自己的业务逻辑阻塞了?Prometheus的指标是按服务聚合 的------它知道每个服务各自的状态,但不知道一个请求在服务之间的流转路径。
链路追踪(Distributed Tracing) 正是为解决这个问题而设计的。它为每个请求生成全局唯一的TraceId,记录请求经过的每一个服务、每一次数据库查询、每一次RPC调用,以及每一段的精确耗时。当请求变慢时,通过链路追踪可以精确定位到是哪个服务、哪个方法、哪条SQL拖慢了整个请求。
SkyWalking 是目前国内微服务生态中应用最广泛的开源APM(Application Performance Management)工具。与Zipkin、Jaeger等纯链路追踪工具不同,SkyWalking在同一个平台内覆盖Tracing、Metrics、Logging、Profiling、Event 五类遥测数据,并提供零代码侵入的Java Agent探针,非常适合Spring Cloud微服务架构的快速接入。
本课将从分布式追踪的理论基础(Dapper论文)讲起,深入SkyWalking的四层架构和字节码增强原理,完成OAP+UI部署和Java Agent探针配置,实战微服务调用链路分析和拓扑图生成,最后给出生产环境的采样策略和性能优化建议。
二、分布式追踪理论基础
2.1 Dapper论文的核心思想
2010年,Google发表了《Dapper, a Large-Scale Distributed Systems Tracing Infrastructure》论文,奠定了分布式追踪的理论基础。今天所有的链路追踪系统------无论是SkyWalking、Zipkin还是Jaeger------其核心设计理念都可以追溯到这篇论文。
Dapper论文开篇描述了一个典型的场景:Google的一个搜索请求可能涉及数百个微服务、数千台机器。当用户说"搜索好慢"时,你该从哪查起?没有追踪系统,你可能需要查几十台机器的日志。Dapper的目标非常明确:性能分析和故障定位。
论文提出了两个基本要求:广泛的覆盖面 ------监控组件应作为基础组件提供,对应用开发者尽可能透明;低开销------监控系统本身对业务服务的性能影响必须降至最低。
2.2 三大核心概念:Trace、Segment、Span
Dapper将一次请求划分为三个层次,这一模型已成为所有链路追踪系统的基础:
Trace(追踪) :表示一整条完整的调用链,包含跨进程、跨线程的所有操作。全局唯一标识为TraceID,贯穿请求的全链路。通过TraceID可以串联起跨服务、跨进程的所有操作,还原完整的调用路径。
Segment(分段) :表示单个进程(如一个JVM实例)或线程内的所有操作集合,包含若干个Span。Segment是SkyWalking的特有概念,它比Zipkin/Jaeger的纯Span模型多了一层"进程级"的聚合。
Span(跨度) :表示一个具体的操作单元,是Trace的最小执行单元。Span分为三种类型:
| 类型 | 含义 | 典型场景 |
|---|---|---|
| Entry Span | 入口Span,是一个Segment的起点 | HTTP/RPC服务端入口、MQ消费者入口 |
| Local Span | 本地方法调用 | Service层方法、工具类方法 |
| Exit Span | 出口Span,是对外部的调用 | HTTP/RPC客户端调用、数据库访问、MQ生产者 |
每个Span包含以下核心属性:
| 属性 | 含义 |
|---|---|
SpanID |
单个Span的唯一标识,单Trace内唯一 |
ParentSpanID |
父Span的ID,用于构建树形调用层级 |
| 操作名 | 标识Span的操作类型,如GET /api/user |
| 起止时间戳 | 记录操作的开始/结束时间,计算耗时 |
| 状态码 | 标识操作的执行结果(成功/失败/异常) |
| 属性/标签 | 键值对形式的元数据,如HTTP URL、状态码、SQL语句 |
2.3 上下文传播:跨服务追踪的核心
上下文传播是实现跨服务链路串联的核心技术难点 。它的核心任务是将Trace上下文(TraceID、SpanID、采样标记等)在跨进程、跨服务、跨线程的调用中进行传递,确保全链路的Span能被正确串联。
在HTTP场景中,上下文通过请求头 传递。SkyWalking Java Agent会自动在Feign调用的请求头中注入sw8头,下游服务的Agent解析该头并恢复Trace上下文,从而将两个服务的Span关联到同一个Trace中。对于Spring Cloud Gateway,流量经过SkyWalking Agent时会自动生成包含TraceID的请求头。
在异步场景(如MQ、线程池)中,上下文通过ThreadLocal快照 传递。SkyWalking的@Trace注解和ContextManager支持手动传递上下文,也可以通过apm-toolkit-trace工具包提供的TraceContext在异步线程中恢复上下文。
三、SkyWalking架构深度剖析
3.1 四层架构:Probe → OAP → Storage → UI
SkyWalking采用逻辑四层架构,每一层职责清晰、可独立扩展:
┌──────────────────────────────────────────────────────────────┐
│ Probe(探针层) │
│ Java Agent / Python Agent / Go Agent / Node.js Agent │
│ Service Mesh Receiver / eBPF / OpenTelemetry / Zipkin │
│ 职责:采集数据,通过gRPC/OTLP上报到OAP │
└──────────────────────────────┬───────────────────────────────┘
│ gRPC (11800) / HTTP (12800)
▼
┌──────────────────────────────────────────────────────────────┐
│ OAP(Observability Analysis Platform) │
│ 接收 Trace/Metrics/Logs/Events │
│ OAL(指标分析)/ MAL(Meter分析)/ LAL(日志分析)DSL流水线 │
│ 聚合 · 流式处理 · 告警 │
│ 职责:数据接收、聚合计算、清洗分析、告警触发 │
└──────────────────────────────┬───────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────┐
│ Storage(存储层) │
│ Elasticsearch / OpenSearch / BanyanDB / MySQL / H2 │
│ 职责:持久化存储链路数据、指标数据、日志数据 │
└──────────────────────────────┬───────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────┐
│ UI(可视化层) │
│ Booster UI(10.x) / Horizon UI(11.x) │
│ 拓扑 · Trace · 指标 · 日志 · Profiling │
│ 职责:Web控制台,查看拓扑图、链路详情、性能指标 │
└──────────────────────────────────────────────────────────────┘
Probe(探针层) :SkyWalking的核心优势在于零代码侵入 。Java Agent通过-javaagent参数挂载,不需要改一行业务代码,自动拦截Spring MVC、OpenFeign、Dubbo、MySQL、Redis、MQ等中间件操作,采集链路、耗时、异常和JVM指标,异步上报数据。
OAP(平台后端) 是架构重心。它接收Trace/Metrics/Logs/Events数据,经OAL(指标分析)、MAL(Meter分析)、LAL(日志分析)等DSL流水线生成实体与指标。10.4版本起,MAL/LAL走V2引擎,指标聚合与持久化worker池合并为BatchQueue调度。
Storage(存储层) 是插件化的。生产环境常见Elasticsearch/OpenSearch或BanyanDB(SkyWalking自研时序+追踪存储)。
UI(可视化层) 在10.x版本中使用Booster UI,11.x版本中已正式切换为Horizon UI。
3.2 核心数据模型
SkyWalking用Service → Service Instance → Endpoint → Process四层结构描述观测对象:
| 层级 | 含义 | 示例 |
|---|---|---|
| Service | 一组提供相同行为的工作负载 | service-user服务 |
| Service Instance | Service下的单个实例(一个JVM进程) | host1@service-user:8081 |
| Endpoint | HTTP URI或gRPC方法签名等入口路径 | GET /api/user/{id} |
| Process | 进程级信息 | 进程ID、OS信息 |
跨K8s、Mesh、OS等多Layer时,可通过Service Hierarchy关联同一逻辑服务在不同层级的视图。
3.3 Java Agent的字节码增强原理
SkyWalking Java Agent采用字节码增强(Bytecode Enhancement) 技术实现无侵入埋点。其核心机制是:
第一层:JVM Instrumentation API。 Java Agent通过premain方法在应用启动时注册ClassFileTransformer。当JVM加载每个类时,Transformer会拦截类字节码,根据SkyWalking的插件规则判断是否需要增强。
第二层:插件化拦截。 SkyWalking内置了数百个插件,覆盖Spring MVC、OpenFeign、MySQL、Redis、RabbitMQ、Kafka等主流框架。每个插件定义了需要拦截的类和方法,以及增强后的逻辑------在方法执行前创建Span,在方法执行后记录耗时和结果。
第三层:上下文传播。 增强后的代码在Entry Span创建时从请求头中提取Trace上下文,在Exit Span创建时向请求头中注入Trace上下文,实现跨服务的链路串联。
性能开销 :SkyWalking Agent对应用的性能影响通常小于3%,支持通过采样率进一步降低开销。
四、SkyWalking部署实战
4.1 Docker Quick Start部署
SkyWalking提供了官方一键部署脚本,交互式选择Elasticsearch或BanyanDB作为存储:
bash
# Linux / macOS / WSL
bash <(curl -sSL https://skywalking.apache.org/quickstart-docker.sh)
脚本会启动三个容器:
| 容器 | 端口 | 职责 |
|---|---|---|
skywalking-oap |
11800(gRPC)、12800(HTTP) | OAP平台后端 |
skywalking-ui |
8080 | Web控制台 |
elasticsearch |
9200 | 数据存储 |
手动部署方式(推荐生产环境):
bash
# 1. 启动Elasticsearch
docker run -d --name elasticsearch \
-p 9200:9200 \
-e "discovery.type=single-node" \
-e "ES_JAVA_OPTS=-Xms2g -Xmx2g" \
elasticsearch:8.15.0
# 2. 启动OAP Server(指定ES存储)
docker run -d --name oap \
-p 11800:11800 -p 12800:12800 \
-e SW_STORAGE=elasticsearch \
-e SW_STORAGE_ES_CLUSTER_NODES=elasticsearch:9200 \
apache/skywalking-oap-server:10.4.0
# 3. 启动UI
docker run -d --name ui \
-p 8080:8080 \
-e SW_OAP_ADDRESS=http://oap:12800 \
apache/skywalking-ui:10.4.0
端口说明 :OAP默认gRPC接收端口为11800 ,HTTP为12800 ;UI默认端口为8080。
4.2 验证部署
访问http://localhost:8080,应看到SkyWalking UI界面。首次访问时,服务列表为空------需要应用挂载Agent并上报数据后才会显示。
五、Java Agent探针配置
5.1 下载Agent
从SkyWalking官网下载Java Agent包,版本必须与OAP Server保持一致:
bash
wget https://archive.apache.org/dist/skywalking/java-agent/9.4.0/apache-skywalking-java-agent-9.4.0.tgz
tar -zxvf apache-skywalking-java-agent-9.4.0.tgz
解压后的目录结构:
skywalking-agent/
├── config/
│ └── agent.config # 主配置文件
├── plugins/ # 默认启用的插件
├── optional-plugins/ # 可选插件(需手动移入plugins/)
└── skywalking-agent.jar # Agent 主jar包
5.2 核心配置项
编辑config/agent.config,关键配置如下:
properties
# 服务名称(在UI中显示)
agent.service_name=${SW_AGENT_NAME:Your_ApplicationName}
# OAP服务器地址(gRPC端口)
collector.backend_service=${SW_AGENT_COLLECTOR_BACKEND_SERVICES:127.0.0.1:11800}
# 采样率:每3秒采集的请求数,-1表示全量采集,默认-1
agent.sample_n_per_3_secs=${SW_AGENT_SAMPLE:-1}
# 数据隔离命名空间
agent.namespace=${SW_AGENT_NAMESPACE:}
# 实例标识(默认自动生成)
agent.instance_name=${SW_AGENT_INSTANCE_NAME:}
5.3 配置覆盖优先级
SkyWalking支持多种配置方式,优先级从高到低依次为:
| 优先级 | 配置方式 | 示例 |
|---|---|---|
| 1(最高) | 探针配置(jar后加参数) | -javaagent:agent.jar=agent.service_name=order-service |
| 2 | 系统配置(-D参数) |
-Dskywalking.agent.service_name=order-service |
| 3 | 系统环境变量 | SW_AGENT_NAME=order-service |
| 4(最低) | 配置文件中的值 | agent.config 中的 Your_ApplicationName |
最佳实践 :推荐通过环境变量配置参数,便于不同环境切换:
bash
export SW_AGENT_NAME=service-user
export SW_AGENT_COLLECTOR_BACKEND_SERVICES=oap:11800
java -javaagent:/agent/skywalking-agent.jar -jar service-user.jar
5.4 Spring Boot应用的启动配置
在microservice-platform的每个服务中,通过JVM参数挂载Agent:
bash
# service-user 启动命令
java -javaagent:/opt/skywalking-agent/skywalking-agent.jar \
-Dskywalking.agent.service_name=service-user \
-Dskywalking.collector.backend_service=192.168.1.100:11800 \
-jar service-user-1.0.0.jar
Maven插件方式(适合开发环境):
xml
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<jvmArguments>
-javaagent:/opt/skywalking-agent/skywalking-agent.jar
-Dskywalking.agent.service_name=${project.artifactId}
-Dskywalking.collector.backend_service=127.0.0.1:11800
</jvmArguments>
</configuration>
</plugin>
5.5 Gateway与OpenFeign的链路透传
SkyWalking Agent原生支持 Spring Cloud Gateway和OpenFeign。Gateway的流量经过Agent时,会自动生成包含TraceID的请求头并在调用链中标记熔断器触发事件。OpenFeign的调用会被自动增强,在请求头中注入sw8头,下游服务解析后恢复Trace上下文。
需要在Gateway模块额外添加的依赖(确保Gateway的链路透传正确):
xml
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-trace</artifactId>
<version>9.4.0</version>
</dependency>
踩坑提示 :如果Gateway使用了自定义的
GlobalFilter修改了请求头,可能会覆盖 SkyWalking注入的sw8头,导致链路断裂。解决方案:在自定义过滤器中,将sw8头添加到白名单中,不做修改。
5.6 日志中注入TraceID
在logback-spring.xml中配置TraceID输出:
xml
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%X{tid}] [%thread] %-5level %logger{36} - %msg%n</pattern>
SkyWalking Agent会自动将TraceID注入到MDC的tid键中。配置后,日志中将显示类似:
2026-09-13 10:30:15 [a1b2c3d4e5f6.1234567890.123456.01] [http-nio-8081-exec-1] INFO c.e.m.u.controller.UserController - 查询用户: id=1
通过TraceID,可以在ELK中串联起该请求在所有服务中的日志。
六、调用链路分析与拓扑图实战
6.1 验证链路数据
启动所有服务(挂载Agent后),访问SkyWalking UI(http://localhost:8080):
- 服务列表 :左侧菜单中应显示
service-user、service-order、service-product、gateway-server四个服务 - 拓扑图:导航至Topology页面,应显示服务间的调用关系。外部请求 → Gateway → service-order → service-user / service-product
- 链路追踪:导航至Trace页面,应能看到最近的请求链路
6.2 拓扑图解读
SkyWalking自动采集服务间的调用数据,生成实时拓扑图,展示服务节点(微服务、数据库、消息队列)、调用方向(箭头表示请求流向)和调用指标(响应时间、错误率)。
拓扑图的关键作用:
- 发现隐藏依赖 :某版本发布后,拓扑图可能显示
order-service对perf-service的调用延迟突然升高 - 定位故障传播链路:当服务雪崩时,拓扑图能一眼看出故障从哪个服务开始、传播到了哪些服务
- 验证架构变更效果:例如将同步调用改为异步后,拓扑图中的实线箭头变为虚线箭头
依赖矩阵:拓扑图下方可以切换到依赖矩阵视图,以表格形式量化服务间依赖强度:
| 调用方 | 被调用方 | 调用次数/分钟 | 平均延迟 |
|---|---|---|---|
order-service |
user-service |
120 | 45ms |
order-service |
product-service |
240 | 12ms |
order-service |
mysql |
360 | 8ms |
6.3 链路详情分析
点击拓扑图中的某条调用边,或进入Trace页面查看单条链路的详情。SkyWalking的链路详情页面以火焰图 和调用树两种视图展示:
调用树视图:
Trace: a1b2c3d4e5f6 (总耗时: 523ms)
├── [Gateway] GET /api/order/1 (523ms)
│ ├── [service-order] OrderController.getOrder (515ms)
│ │ ├── [service-order] OrderService.query (510ms)
│ │ │ ├── [service-user] UserClient.getUserById (320ms) ← 慢!占比61%
│ │ │ │ └── [service-user] UserController.getUserById (310ms)
│ │ │ │ └── [MySQL] SELECT * FROM user WHERE id=1 (295ms) ← 慢SQL!
│ │ │ ├── [service-product] ProductClient.getProductById (150ms)
│ │ │ │ └── [service-product] ProductController.getProductById (145ms)
│ │ │ └── [service-order] OrderService.assemble (35ms)
│ │ └── [service-order] OrderController.response (5ms)
│ └── [Gateway] Response (523ms)
从调用树中可以精确定位瓶颈:
- 总耗时523ms,其中
service-user调用耗时320ms(占比61%) service-user的耗时主要来自MySQL查询(295ms)- 定位到具体问题:
service-user的数据库查询缺少索引,导致全表扫描
关键指标:
- 自身耗时(Self Time) :Span的总耗时减去子Span的耗时。如果某个Span的Self Time很高,说明瓶颈在该Span自身的代码逻辑中
- 异常标记:发生异常的Span会以红色高亮显示,点击可查看异常堆栈
- SQL记录:数据库查询的SQL语句会被记录,便于分析慢SQL
6.4 性能瓶颈排查实战
场景一:Feign调用超时 。在调用树中,UserClient.getUserById的耗时异常高(如3秒)。展开该Span,可以看到SkyWalking记录的HTTP请求详情------请求URL、状态码、响应时间。对比第15课配置的Feign超时时间(read-timeout),确认是否为下游服务响应慢导致的超时。
场景二:数据库慢查询 。展开MySQL Span,可以看到执行的SQL语句和耗时。SkyWalking自动记录SQL语句(需要开启plugin.jdbc.trace_sql_parameters=true配置)。
场景三:Gateway转发慢。在调用树中,Gateway的Span耗时高,但下游服务的Span耗时正常。这说明瓶颈在Gateway自身的处理逻辑(如鉴权过滤器、限流过滤器)中。
6.5 日志与链路的联动
SkyWalking支持将TraceID注入到日志中,通过日志中的TraceID可以在ELK中检索到该请求在所有服务 中的完整日志。当某个接口超时告警时,运维人员可以直接通过TraceID跳转到关联日志,查看当时数据库连接池的状态或异常堆栈。
七、生产采样策略与性能优化
7.1 采样率配置
SkyWalking的采样率通过agent.sample_n_per_3_secs配置,含义是每3秒采集的请求数:
| 配置值 | 含义 | 适用场景 |
|---|---|---|
-1 |
全量采集 | 开发/测试环境 |
0 |
不采集 | 关闭Agent |
100 |
每3秒采集100个请求 | 生产环境(中等流量) |
10 |
每3秒采集10个请求 | 生产环境(高流量) |
生产建议:核心服务(支付、订单)使用较高采样率(100-500),非核心服务(日志上报、推荐)使用较低采样率(10-50)。全量采集在生产环境可能导致OAP和ES的存储压力过大。
7.2 OAP Server性能调优
OAP Server的JVM参数需要根据数据量调整:
bash
# OAP Server JVM 参数
SW_JAVA_OPTS="-Xms4g -Xmx4g -XX:MetaspaceSize=256m"
存储层优化:
- Elasticsearch集群建议至少3节点,每个节点8核16G
- 配置ES的
index.refresh_interval为30s(而非默认的1s),减少写入压力 - 定期清理过期索引(OAP默认保留7天数据,可通过
SW_CORE_DATA_KEEPER_EXECUTE_PERIOD调整)
7.3 Agent性能优化
如果发现Agent对应用性能影响较大(超过5%),可以通过以下方式优化:
- 降低采样率 :从
-1调整为100或更低 - 禁用不必要的插件 :将
plugins/目录下不需要的插件移出(如kafka-plugin.jar、rocketmq-plugin.jar) - 关闭SQL参数记录 :设置
plugin.jdbc.trace_sql_parameters=false - 调整上报批大小 :增加
agent.buffer.channel_size和agent.buffer.buffer_size,减少网络请求次数
7.4 SkyWalking与Micrometer Tracing的协同
SkyWalking的Agent与Spring Boot Actuator的Micrometer Tracing可以共存,但需要注意:
- SkyWalking Agent:负责链路追踪(Trace/Span),通过字节码增强实现
- Micrometer Tracing:负责生成日志中的TraceID/SpanID,通过Spring Boot的自动配置实现
两者的TraceID是独立的 ------SkyWalking的TraceID存储在sw8头中,Micrometer的TraceID存储在traceparent头中。如果需要统一,可以通过SkyWalking的apm-toolkit-trace工具包将SkyWalking的TraceID注入到MDC中。
八、踩坑指南
坑一:Agent版本与OAP版本不匹配
现象 :应用启动时报The OAP version is not compatible,或UI中看不到数据。
原因:Java Agent与OAP Server的版本不一致。SkyWalking对版本兼容性要求严格。
解决 :确保Agent和OAP的主版本号一致。例如OAP使用10.4.0,Agent也应使用9.4.0(Java Agent的版本号与OAP版本号不完全对应,需要查看官方兼容性矩阵)。
坑二:Gateway自定义过滤器覆盖了sw8头
现象:Gateway的链路正常,但下游服务的链路断裂------下游服务的TraceID与Gateway的TraceID不同。
原因 :Gateway的自定义GlobalFilter在修改请求头时,覆盖了SkyWalking注入的sw8头。
解决 :在自定义过滤器中,对sw8头做白名单处理 ------读取但不对其进行修改。或者使用ServerHttpRequest.mutate()时保留原有的sw8头。
坑三:异步线程中链路断裂
现象 :@Async方法或线程池中的任务,其Span的TraceID与父线程不同,导致链路断裂。
原因 :SkyWalking的Trace上下文存储在ThreadLocal中,异步线程无法访问父线程的ThreadLocal。
解决 :使用apm-toolkit-trace工具包中的TraceContext手动传递上下文:
java
@Async
public void asyncMethod() {
// 在异步方法中手动恢复上下文
// 或者使用 @Trace 注解
}
或者使用ContextManager在异步任务提交前捕获上下文,在任务执行时恢复。
坑四:采样率为0导致无数据
现象:应用挂载了Agent,但UI中完全看不到数据。
原因 :agent.sample_n_per_3_secs被设置为0(不采集)。
解决 :检查agent.config中的agent.sample_n_per_3_secs,确保不是0。生产环境建议设置为100或更高。
坑五:Elasticsearch存储空间快速增长
现象:ES磁盘使用量快速增长,几天内占满磁盘。
原因 :默认保留7天数据,且采样率为全量(-1)。在高流量场景下,7天的链路数据可能达到数百GB。
解决 :降低采样率;缩短数据保留时间(通过SW_CORE_DATA_KEEPER_EXECUTE_PERIOD配置);定期清理过期索引。
坑六:JDK 21下Agent兼容性问题
现象:JDK 21环境下Agent启动报错,提示字节码增强失败。
原因 :SkyWalking Java Agent的字节码增强在JDK 21下可能遇到UnsupportedOperationException,因为JDK 21对Instrumentation API的某些方法有限制。
解决 :确保使用SkyWalking Java Agent 9.4.0或更高版本 ,这些版本已经适配了JDK 21。同时,在启动参数中添加--add-opens java.base/java.lang=ALL-UNNAMED。
九、课后作业
作业一:使用Docker部署SkyWalking(OAP + UI + Elasticsearch),验证UI可正常访问。记录OAP的gRPC端口和HTTP端口。
作业二 :为service-user、service-order、service-product、gateway-server四个服务挂载SkyWalking Java Agent。通过环境变量配置SW_AGENT_NAME和SW_AGENT_COLLECTOR_BACKEND_SERVICES。验证UI中四个服务均正常显示。
作业三:发起一次完整的下单请求(通过Gateway → service-order → service-user + service-product),在SkyWalking UI中查看完整的调用链路。记录每个Span的耗时,找出耗时最高的三个Span。
作业四 :在service-user的getUserById方法中添加Thread.sleep(2000),重新发起请求,通过链路详情验证能否精确定位到service-user的MySQL查询为瓶颈。
作业五(进阶) :配置plugin.jdbc.trace_sql_parameters=true,重新发起请求,验证链路详情中是否记录了完整的SQL语句和参数。分析SQL执行计划,确认是否存在索引缺失问题。
十、下节预告
第28课将进入统一日志收集、ELK搭建 & 线上问题排查体系 。内容包括日志规范与分级、Logback配置、ELK(Elasticsearch + Logstash + Kibana)搭建、日志检索、链路ID追踪和线上报错快速定位。本课完成了链路追踪 (Tracing)的完整链路,第28课将进入日志(Logging) 领域------指标告诉你"系统状态如何",链路告诉你"请求经过了哪些服务",日志告诉你"系统在某个时刻发生了什么"。三者结合,构成完整的可观测性体系。通过SkyWalking的TraceID与ELK日志的联动,可以实现"一键从链路跳转到日志"的高效排查体验。
🔗《最新版 SpringCloud 2025 从入门到实战》系列课程导航
第一部分:微服务前置基础 & 新版环境搭建(第1-5课)
第二部分:注册中心核心(Nacos 最新版)(第6-9课)
第三部分:配置中心核心(Nacos配置中心)(第10-12课)
第四部分:服务通信核心(OpenFeign + LoadBalancer)(第13-16课)
第五部分:网关核心(SpringCloud Gateway 新版)(第17-20课)
第六部分:熔断、限流、降级(Sentinel 新版)(第21-24课)
第七部分:微服务监控、链路追踪、日志体系(第25-28课)
第八部分:微服务高阶特性 & 分布式核心能力(第29-31课)
第九部分:企业级完整项目实战 & 架构复盘(第32-35课)