全链条追踪:引入SkyWalking
- 在V2.3中,利用 Prometheus+Grafana 解决了宏观上的观测问题,在V3.2中,利用自造的“轮子”mini-apm-agent实现了单点的观测问题,可以告诉我们createOrderIndb方法的耗时。但是,我们无法得知时间在具体环节上的时间花费。
- 在V3.3,引入SkyWalking,每一个穿过系统的请求,都可以被追踪,可以清晰的看到每一个服务、每一个组件上花费的精确时间。
配置
- 部署SkyWalking后台(OAP + UI),更新docker-compose.yml文件,在 services: 部分,新增 skywalking-oap 和 skywalking-ui 两个服务。
- 下载并放置 SkyWalking Agent。
- 修改 IntelliJ IDEA 启动配置(挂载探针)
- 【核心改动】 将 -javaagent:… 参数从指向 mini-apm-agent.jar,替换为指向 SkyWalking Agent 的路径,并增加两个新的系统属性 (-D):
1
2
3-javaagent:D:\Javaproject\skywalking-agent\skywalking-agent.jar
-Dskywalking.agent.service_name=seckill-system
-Dskywalking.collector.backend_service=localhost:11800 - 参数
- javaagent:…: 挂载 SkyWalking 探针。
- Dskywalking.agent.service_name=…: 告诉探针,应用叫什么名字。
- Dskywalking.collector.backend_service=…: 告诉探针,数据中心(OAP)的地址在 localhost:11800。因为 skywalking-oap 容器的 11800 端口已经被我们映射到了 localhost。
启动
- 运行
docker-compose up -d,启动 seckill-system 应用。 - 发起压测: 启动 JMeter,对 Nginx (http://localhost) 发起一轮小规模的压测。
- 访问 http://localhost:8081 ,可以看到全链路追踪图像。

图表分析
DashBoard

Service Apdex -总分:1.00
- 这是一个工业级别的“用户满意度”指数,分数从0-1,1.00是满分,说明服务响应极快。
- 异步架构是成功的,Controller几乎在瞬间就响应了所有请求。
Success Rate -总分:100.00%
- 表示在seckill-system服务处理的所有请求中,有多少是成功的。
- 在压测期间,应用没有抛出任何一个未被捕获的异常,没有发生任何导致服务器崩溃的500错误。
Service Load (calls/min)
- 按分钟聚合的QPS / RPS 图表。
Service Avg Response Time (ms) (服务平均响应时间)
- seckill-system 服务处理一个请求平均花了多少毫秒
Service Response Time Percentile (ms) (服务响应时间百分位图)
- 衡量性能最重要的图表
- P99 (紫线): 99% 的用户,他们的请求在约 150毫秒 内得到了响应。
- P95 (红线): 95% 的用户,他们的请求在约 60毫秒 内得到了响应。
- P90/P75/P50
Message Queue Consuming Count (MQ 消费计数)
- 消费者每分钟处理了多少条消息。
Message Queue Avg Consuming Latency (ms) (MQ 平均消费延迟)
- OrderConsumerService 处理单条消息(从收到消息到方法执行完毕)平均花了多长时间。
Trace

Trace 与 Span (跨度):
- Trace: 是一次请求的完整生命周期,由一个唯一的 TraceID 标识。
- Span: 是 Trace 中的一个独立工作单元(比如一次 Controller 调用、一次 Redis 命令、一次 MQ 发送)。
“瀑布图”的核心三要素:
- 层级(垂直): 父子关系(Span 之间的调用栈)。
- 时序(水平): 每个 Span 的开始时间和结束时间。
- 时长(条块长度): 每个 Span 自身的执行耗时。
两个最重要的诊断信号:
- 寻找“最长”: 瀑布图中最长的那个 Span,就是同步链路中的性能瓶颈。
- 寻找“空白”: 两个 Span 之间如果存在巨大的时间鸿沟,这通常代表着“等待”(如线程池排队、MQ 队列排队、网络延迟)。
解析:
- 从第一个图像中可以看出,RabbitMQ-Producer 在第1.4ms左右完成了消息发送,但是RabbitMQ-Consumer 在第11ms才开始处理这段消息,在两个紫色条块之间,有7.6ms的等待时间。也就是这条订单消息在RabbitMQ队列中排队等待所花费的时间。表明生产者处理请求的速度,远远快于消费者写入数据库的速度。即“削峰填谷”,JMeter 的流量洪峰,被 RabbitMQ 成功地拦截并“蓄洪”在了队列中。
- 后来,在第二个图像中,4秒后,producer 在第 0.6ms 左右完成了发送。consumer 在第 1.9ms 就开始处理了。两者之间的空白时间,已经急剧缩短到了 1.3ms 。说明压测的瞬时洪峰已经过去。两者之间的空白时间,已经急剧缩短到了 1.3 秒。
学学八股
SkyWalking
- Trace (追踪): 是一次请求的完整生命周期,代表了一个完整的“调用链”。比如,从用户点击秒杀按钮,到订单创建成功返回,这整个流程共享一个唯一的 TraceID。
- Span (跨度): 是 Trace 中的一个独立的工作单元或步骤。每一个 Span 都有自己的开始和结束时间、一个操作名称(如 SpringMVC: /seckill 或 MySQL: UPDATE),以及一个 SpanID。
- 关系: 一个 Trace 是由一棵 Span 树组成的。
- 树的根节点 (Root Span) 是整个请求的入口(比如 SpringMVC: /seckill)。
- 它的子节点(Child Span)是它在执行过程中调用的其他方法(比如 Redis: Lua)。
- 这些 Span 通过 TraceID(标识它们同属一个“家族”)和 ParentSpanID(标识“父子”调用关系)组织在一起,最终构成了在 SkyWalking UI 上看到的“瀑布图”。


