当前位置: 首页 > news >正文

从 0 到 1 精通 SkyWalking:分布式系统的 “透视镜“ 技巧全解析

引言:当分布式系统遇见 "盲人摸象" 困境

在单体应用时代,我们排查问题就像在自己家里找东西,虽然偶尔也会找不到,但至少对整个空间了如指掌。而进入分布式系统时代,排查问题更像是在一个陌生的大型商场里找一串丢失的钥匙 —— 你知道它就在某个地方,但完全不知道从何找起。

想象这样一个场景:用户投诉某个电商平台下单后长时间未收到确认信息。客服反馈给技术团队,前端工程师检查后发现接口调用超时,后端工程师查看服务日志未发现异常,数据库团队确认查询性能正常,运维团队表示服务器资源充足。每个环节看起来都没问题,但整个流程却失败了。这就是分布式系统的 "盲人摸象" 困境 —— 每个团队只能看到自己负责的部分,无法把握全局。

SkyWalking 正是为解决这一困境而生的分布式追踪系统。它就像给分布式系统装上了 "透视镜" 和 "黑匣子",不仅能看到系统的整体运行状态,还能在出现问题时快速定位根因。本文将从理论到实践,全面解析 SkyWalking 的核心原理、架构设计、实战应用和高级特性,帮助你真正理解并掌握这一强大的分布式追踪工具。

一、SkyWalking 核心概念与价值定位

1.1 什么是 SkyWalking?

SkyWalking 是一个开源的分布式追踪系统,由华为工程师吴晟(现 Apache 基金会董事)发起,目前已成为 Apache 顶级项目。它主要用于微服务、云原生和容器化应用的可观测性分析,提供分布式追踪、服务网格(Service Mesh)遥测分析、度量聚合和可视化一体化解决方案。

简单来说,SkyWalking 能帮助我们回答这些关键问题:

  • 一个请求在分布式系统中经过了哪些服务?
  • 每个服务处理请求花费了多长时间?
  • 哪个服务或组件是系统性能瓶颈?
  • 当请求失败时,具体是在哪个环节出了问题?
  • 系统整体的调用拓扑结构是怎样的?

1.2 SkyWalking 的核心价值

在分布式系统中,SkyWalking 的核心价值体现在三个方面:

  1. 问题定位:快速定位跨服务调用中的异常和性能瓶颈,减少故障排查时间
  2. 性能优化:通过分析调用链和性能指标,发现系统优化点
  3. 系统可视化:将抽象的分布式系统转化为直观的拓扑图和指标图表
  4. 容量规划:基于历史数据和趋势分析,为系统扩容提供决策依据
  5. 服务治理:识别不健康的服务实例,为服务熔断和降级提供数据支持

1.3 可观测性三支柱与 SkyWalking 的定位

现代分布式系统的可观测性(Observability)建立在三个支柱上:

  • 追踪(Tracing):记录请求在分布式系统中的完整路径,关注单个请求的流转
  • 度量(Metrics):对系统状态的数值化描述,关注聚合数据和趋势
  • 日志(Logging):系统产生的离散事件记录,关注具体细节

SkyWalking 以分布式追踪为核心,同时整合了度量和日志功能,形成了一个完整的可观测性平台。与其他工具相比,SkyWalking 的特点是:

  • 探针性能优异,对应用侵入性小
  • 支持多种语言和框架
  • 提供丰富的可视化界面
  • 可扩展性强,支持自定义插件
  • 对 Service Mesh 有良好支持

1.4 SkyWalking 与其他可观测性工具的对比

工具特点优势场景不足
SkyWalking全栈可观测性,性能优秀,国产开源微服务、云原生应用生态相对 Prometheus+Grafana 较小
Zipkin简单轻量,易于部署中小规模分布式系统功能相对简单,可视化较弱
JaegerCNCF 毕业项目,与 K8s 生态融合好Kubernetes 环境对部分旧框架支持不够完善
Pinpoint字节码增强,无需代码侵入无法修改代码的场景插件开发相对复杂
Prometheus+Grafana度量监控强大,生态丰富指标监控和告警追踪功能需要额外集成

二、SkyWalking 核心原理深度解析

2.1 分布式追踪的基础:追踪上下文传播

分布式追踪的核心是如何将跨服务的请求关联起来,形成完整的调用链。SkyWalking 采用了与 OpenTelemetry 兼容的上下文传播机制,主要通过以下几个标识符实现:

  • Trace ID:整个分布式调用链的唯一标识,一个 Trace ID 代表一个完整的请求链路
  • Segment ID:每个服务处理请求时生成的片段 ID,一个 Trace 由多个 Segment 组成
  • Span ID:每个 Segment 中具体操作的标识,代表一个具体的处理单元

当请求从一个服务传递到另一个服务时,这些标识符通过网络协议(如 HTTP 头、RPC 元数据)进行传递,从而将分散在不同服务的处理过程关联起来。

2.2 SkyWalking 的核心工作流程

SkyWalking 的工作流程可以分为四个主要阶段:

  1. 数据采集:通过 Agent 探针对应用进行字节码增强,自动生成追踪数据;同时支持手动埋点补充关键业务信息
  2. 数据传输:Agent 采集的数据通过 gRPC 或 HTTP 协议发送到 SkyWalking 后端(OAP Server)
  3. 数据存储:OAP Server 对数据进行分析和聚合后,存储到指定的存储介质(如 Elasticsearch)
  4. 数据展示:通过 SkyWalking UI 展示系统拓扑、调用链、性能指标等,并提供告警功能

2.3 字节码增强技术:SkyWalking 的 "无侵入" 秘诀

SkyWalking Agent 之所以能实现对应用的无侵入式监控,核心在于其采用了字节码增强技术。简单来说,就是在应用程序的类加载过程中,动态修改字节码,插入监控逻辑,而无需修改应用源代码。

字节码增强的工作流程:

SkyWalking 内置了对主流框架的增强器,如 Spring Boot、Dubbo、MyBatis、HttpClient 等,覆盖了大多数常见的调用场景。对于自定义框架或特殊场景,也可以开发自定义增强器。

2.4 SkyWalking 的数据模型

SkyWalking 定义了一套完整的数据模型来描述分布式系统的运行状态,核心模型包括:

  1. 服务(Service):具有相同功能的一组实例的集合,如订单服务、用户服务
  2. 服务实例(Service Instance):服务的具体运行实例,通常对应一个进程
  3. 端点(Endpoint):服务中可以被调用的具体接口或方法,如 HTTP 接口、RPC 方法
  4. 进程(Process):操作系统层面的进程,一个服务实例对应一个进程
  5. 追踪(Trace):一个请求在分布式系统中的完整调用路径
  6. 片段(Segment):追踪在单个服务实例中的部分
  7. 跨度(Span):片段中的一个具体操作,如一次数据库查询、一次 HTTP 调用

这些模型之间的关系如下:

2.5 OAP Server 的核心功能

SkyWalking OAP(Observability Analysis Platform)服务器是整个系统的核心,负责数据处理、分析和存储,主要功能包括:

  1. 数据接收:接收来自 Agent 和其他数据源的数据
  2. 数据解析:解析不同格式的输入数据
  3. 拓扑分析:根据调用关系自动构建服务拓扑图
  4. 指标计算:聚合计算各种性能指标(响应时间、吞吐量、错误率等)
  5. 数据存储:将处理后的数据存储到指定的存储介质
  6. 查询服务:提供查询接口供 UI 和其他系统使用
  7. 告警管理:根据预设规则判断是否触发告警

OAP Server 采用了模块化设计,不同功能通过插件实现,便于扩展和定制。

三、SkyWalking 环境搭建与基础配置

3.1 环境准备

在开始搭建 SkyWalking 之前,需要准备以下环境:

  • JDK 17+(SkyWalking 9.x 及以上版本推荐)
  • 操作系统:Linux、Windows 或 MacOS
  • 存储介质:推荐使用 Elasticsearch 7.x 或 8.x
  • 网络:确保 Agent、OAP Server 和 UI 之间的网络连通

3.2 搭建 Elasticsearch 存储

SkyWalking 支持多种存储介质,其中 Elasticsearch 是最常用的选择,因为它在处理时序数据和支持复杂查询方面表现优异。

使用 Docker 快速启动 Elasticsearch 8.11.3(最新稳定版):

bash

# 拉取镜像
docker pull elasticsearch:8.11.3
# 启动容器
docker run -d \
--name elasticsearch \
-p 9200:9200 \
-p 9300:9300 \
-e "discovery.type=single-node" \
-e "xpack.security.enabled=false" \
-e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \
elasticsearch:8.11.3

验证 Elasticsearch 是否启动成功:

bash

curl http://localhost:9200

成功启动会返回类似以下的响应:

json

{
"name" : "3f1a91f8b6a",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "3zH7x1a5Qv-5L7Z9y8YJ-Q",
"version" : {
"number" : "8.11.3",
"build_flavor" : "default",
"build_type" : "docker",
"build_hash" : "64cf052f3b56b10c041973289942cb37b108e6",
"build_date" : "2023-12-08T11:33:53.634979450Z",
"build_snapshot" : false,
"lucene_version" : "9.8.0",
"minimum_wire_compatibility_version" : "7.17.0",
"minimum_index_compatibility_version" : "7.0.0"
},
"tagline" : "You Know, for Search"
}

3.3 安装 SkyWalking OAP Server

下载并解压 SkyWalking 9.7.0(最新稳定版):

bash

# 下载
wget https://archive.apache.org/dist/skywalking/9.7.0/apache-skywalking-apm-9.7.0.tar.gz
# 解压
tar -zxvf apache-skywalking-apm-9.7.0.tar.gz
cd apache-skywalking-apm-bin

配置 OAP Server 使用 Elasticsearch 存储:

编辑config/application.yml文件,修改存储配置:

yaml

storage:
selector: ${SW_STORAGE:elasticsearch}
elasticsearch:
namespace: ${SW_NAMESPACE:""}
clusterNodes: ${SW_STORAGE_ES_CLUSTER_NODES:localhost:9200}
protocol: ${SW_STORAGE_ES_HTTP_PROTOCOL:http}
connectTimeout: ${SW_STORAGE_ES_CONNECT_TIMEOUT:3000}
socketTimeout: ${SW_STORAGE_ES_SOCKET_TIMEOUT:30000}
responseTimeout: ${SW_STORAGE_ES_RESPONSE_TIMEOUT:15000}
numHttpClientThread: ${SW_STORAGE_ES_NUM_HTTP_CLIENT_THREAD:0}
user: ${SW_ES_USER:""}
password: ${SW_ES_PASSWORD:""}
# 其他配置保持默认

启动 OAP Server:

bash

# Linux/Mac
bin/oapService.sh
# Windows
bin/oapService.bat

OAP Server 启动成功后,会监听 11800 端口(gRPC)和 12800 端口(HTTP)。

3.4 启动 SkyWalking UI

SkyWalking UI 是一个基于 React 的前端应用,用于可视化展示监控数据。

启动 UI 服务:

bash

# Linux/Mac
bin/webappService.sh
# Windows
bin/webappService.bat

默认情况下,UI 会监听 8080 端口,并连接本地的 OAP Server(127.0.0.1:12800)。如果 OAP Server 部署在其他地址,需要修改webapp/application.yml文件:

yaml

server:
port: 8080
spring:
cloud:
gateway:
routes:
- id: oap-route
uri: http://localhost:12800  # 修改为实际的OAP Server地址
predicates:
- Path=/graphql/**,/ui/**,/api/**,/analysis/**,/logs/**

启动成功后,访问http://localhost:8080即可打开 SkyWalking UI 界面。

3.5 配置 SkyWalking Agent

SkyWalking Agent 是嵌入到应用中的探针,负责收集监控数据。

下载 Agent:

SkyWalking Agent 已经包含在之前下载的安装包中,位于agent目录下。也可以单独下载:

bash

wget https://archive.apache.org/dist/skywalking/java-agent/8.16.0/apache-skywalking-java-agent-8.16.0.tgz
tar -zxvf apache-skywalking-java-agent-8.16.0.tgz

Agent 核心配置:

Agent 的主要配置文件是agent/config/agent.config,关键配置项包括:

properties

# 应用名称(服务名称)
agent.service_name=${SW_AGENT_NAME:YourApplicationName}
# OAP Server地址
collector.backend_service=${SW_AGENT_COLLECTOR_BACKEND_SERVICES:127.0.0.1:11800}
# 采样率,1表示100%采样
agent.sample_n_per_3_secs=${SW_AGENT_SAMPLE:-1}
# 日志级别
logging.level=${SW_LOGGING_LEVEL:INFO}
# 插件配置,默认启用所有插件
plugin.mount=${SW_MOUNT_PLUGINS:}

3.6 在 Spring Boot 应用中集成 Agent

创建一个简单的 Spring Boot 应用:

首先,创建一个 Maven 项目,pom.xml配置如下:

xml

4.0.0
org.springframework.boot
spring-boot-starter-parent
3.2.0
com.example
skywalking-demo
1.0.0
17
1.18.30
2.1.0
org.springframework.boot
spring-boot-starter-web
org.projectlombok
lombok
${lombok.version}
provided
org.springdoc
springdoc-openapi-starter-webmvc-ui
${springdoc.version}
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-maven-plugin

创建一个简单的控制器:

java

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.Random;
/**
* 演示控制器
*
* @author ken
*/
@Slf4j
@RestController
@RequestMapping("/demo")
@Tag(name = "演示接口", description = "用于SkyWalking演示的接口")
public class DemoController {
private final RestTemplate restTemplate = new RestTemplate();
private final Random random = new Random();
/**
* 简单的Hello接口
*
* @param name 名称
* @return 问候语
*/
@GetMapping("/hello/{name}")
@Operation(summary = "Hello接口", description = "返回简单的问候语")
public String hello(@PathVariable String name) {
log.info("收到hello请求,名称:{}", name);
// 模拟处理时间
try {
Thread.sleep(random.nextInt(200));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
log.error("处理hello请求时发生中断", e);
}
return "Hello, " + name + "!";
}
/**
* 调用另一个接口的示例
*
* @param id ID参数
* @return 处理结果
*/
@GetMapping("/call/{id}")
@Operation(summary = "调用示例", description = "调用另一个接口的示例")
public String callAnother(@PathVariable Long id) {
log.info("收到call请求,ID:{}", id);
// 模拟调用另一个服务
String result = restTemplate.getForObject("http://localhost:8081/demo/process/" + id, String.class);
return "处理结果:" + result;
}
}

创建应用启动类:

java

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* 应用启动类
*
* @author ken
*/
@SpringBootApplication
public class SkywalkingDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SkywalkingDemoApplication.class, args);
}
}

使用 Agent 启动应用:

bash

java -javaagent:/path/to/skywalking-agent/skywalking-agent.jar \
-Dskywalking.agent.service_name=demo-service \
-Dskywalking.collector.backend_service=localhost:11800 \
-jar target/skywalking-demo-1.0.0.jar

其中:

  • -javaagent:指定 Agent 的路径
  • -Dskywalking.agent.service_name:设置服务名称
  • -Dskywalking.collector.backend_service:设置 OAP Server 地址

启动成功后,访问几次http://localhost:8080/demo/hello/world接口,然后打开 SkyWalking UI(http://localhost:8080),就可以看到服务的监控数据了。

四、SkyWalking 核心功能实战

4.1 服务拓扑图分析

服务拓扑图是 SkyWalking 最直观的功能之一,它能自动根据服务间的调用关系生成可视化的系统架构图。

查看服务拓扑图的步骤:

  1. 登录 SkyWalking UI
  2. 在左侧菜单中选择 "拓扑图"
  3. 选择时间范围(如最近 10 分钟)
  4. 点击 "刷新" 按钮

拓扑图会展示:

  • 所有被监控的服务节点
  • 服务之间的调用关系
  • 调用的吞吐量(每秒请求数)
  • 调用的响应时间
  • 调用的错误率

通过拓扑图,我们可以快速了解:

  • 系统由哪些服务组成
  • 服务之间的依赖关系
  • 哪些服务之间的交互频繁
  • 哪些调用路径存在性能问题(红色表示响应时间长或错误率高)

4.2 分布式调用链追踪

当系统出现问题时,调用链追踪是定位问题的关键工具。SkyWalking 可以展示一个请求从开始到结束的完整路径,包括每个环节的处理时间。

查询调用链的步骤:

  1. 在 SkyWalking UI 左侧菜单中选择 "追踪"
  2. 设置查询条件(如服务名称、时间范围、是否包含错误等)
  3. 点击 "查询" 按钮
  4. 在结果列表中选择一个追踪记录查看详情

调用链详情展示:

  • 每个服务的处理时间
  • 每个 Span 的具体信息(如 HTTP 方法、URL、参数摘要)
  • 异常信息(如果有)
  • 标签信息(如数据库语句、缓存键等)

示例:分析一个慢查询

假设我们发现/demo/call/{id}接口响应缓慢,通过调用链追踪发现:

  1. demo-service调用process-service/demo/process/{id}接口耗时 2.3 秒
  2. process-service中,ProcessService.process()方法耗时 2.2 秒
  3. 进一步查看发现,ProcessService中的数据库查询耗时 2.1 秒

通过这个调用链,我们可以快速定位到性能瓶颈在process-service的数据库查询上,而不是网络传输或其他环节。

4.3 性能指标监控

SkyWalking 提供了丰富的性能指标监控,帮助我们了解系统的运行状态。主要指标包括:

  • 响应时间(Response Time):服务处理请求的时间,包括 P50、P90、P99 等百分位值
  • 吞吐量(Throughput):单位时间内处理的请求数
  • 错误率(Error Rate):错误请求占总请求的比例
  • SLA(Service Level Agreement):服务可用性指标

查看性能指标的步骤:

  1. 在 SkyWalking UI 左侧菜单中选择 "仪表盘"
  2. 选择要查看的服务
  3. 选择时间范围
  4. 查看各项指标图表

通过性能指标,我们可以:

  • 发现服务的性能趋势
  • 比较不同服务的性能表现
  • 识别性能异常(如响应时间突增、错误率上升)
  • 评估系统的整体健康状况

4.4 日志集成与分析

SkyWalking 可以与应用日志集成,将日志与调用链关联起来,方便问题排查。

集成 Logback 日志框架:

  1. 添加 Logback 依赖:

xml

ch.qos.logback
logback-classic
1.4.8
  1. 创建src/main/resources/logback-spring.xml配置文件:

xml

%d{yyyy-MM-dd HH:mm:ss.SSS} [%tid] [%thread] %-5level %logger{36} - %msg%n
%d{yyyy-MM-dd HH:mm:ss.SSS} [%tid] [%thread] %-5level %logger{36} - %msg%n
  1. 添加 SkyWalking 日志工具包依赖:

xml

org.apache.skywalking
apm-toolkit-logback-1.x
8.16.0

配置完成后,应用日志中会自动包含TraceID,并且日志会被发送到 SkyWalking OAP Server。在 SkyWalking UI 的 "日志" 菜单中,可以根据TraceID查询与特定调用链相关的所有日志,实现日志与调用链的联动分析。

4.5 告警配置与使用

SkyWalking 支持基于各种指标设置告警规则,当指标超过阈值时会触发告警通知。

配置告警规则:

编辑 OAP Server 的config/alarm-settings.yml文件,添加或修改告警规则:

yaml

rules:
# 服务响应时间告警
service_resp_time_rule:
metrics-name: service_resp_time
op: ">"
threshold: 1000
period: 10
count: 3
silence-period: 5
message: "服务 {name} 的响应时间超过1000ms,持续3个周期"
# 服务错误率告警
service_error_rate_rule:
metrics-name: service_error_rate
op: ">"
threshold: 0.05
period: 10
count: 2
silence-period: 5
message: "服务 {name} 的错误率超过5%,持续2个周期"
# 端点响应时间告警
endpoint_resp_time_rule:
metrics-name: endpoint_resp_time
op: ">"
threshold: 500
period: 10
count: 3
silence-period: 5
message: "端点 {name} 的响应时间超过500ms,持续3个周期"
# 告警通知器配置
notification-settings:
default:
# 钉钉通知器
dingtalk:
enabled: true
webhook: https://oapi.dingtalk.com/robot/send?access_token=your_token
secret: your_secret
message-type: TEXT
# 邮件通知器
email:
enabled: false
host: smtp.example.com
port: 587
username: alert@example.com
password: password
from: alert@example.com
to: admin@example.com
subject: "SkyWalking 告警通知"

配置说明:

  • metrics-name:要监控的指标名称
  • op:比较运算符(>、<、>=、<=、==)
  • threshold:阈值
  • period:检查周期(分钟)
  • count:连续多少次超过阈值后触发告警
  • silence-period:告警沉默期,避免重复告警(分钟)
  • message:告警消息内容

修改配置后需要重启 OAP Server 生效。在 SkyWalking UI 的 "告警" 菜单中,可以查看所有触发的告警记录。

五、SkyWalking 高级特性与定制化

5.1 自定义埋点与增强

虽然 SkyWalking 的自动埋点已经覆盖了大部分场景,但在某些情况下,我们需要添加自定义埋点来跟踪特定的业务逻辑。

使用 SkyWalking 工具包进行自定义埋点:

  1. 添加工具包依赖:

xml

org.apache.skywalking
apm-toolkit-trace
8.16.0
  1. 在代码中添加自定义埋点:

java

import org.apache.skywalking.apm.toolkit.trace.ActiveSpan;
import org.apache.skywalking.apm.toolkit.trace.Trace;
import org.apache.skywalking.apm.toolkit.trace.TraceContext;
import org.springframework.stereotype.Service;
/**
* 自定义埋点示例服务
*
* @author ken
*/
@Service
public class CustomTraceService {
/**
* 使用@Trace注解标记需要追踪的方法
*
* @param orderId 订单ID
* @return 处理结果
*/
@Trace
public String processOrder(Long orderId) {
// 添加自定义标签
ActiveSpan.tag("orderId", orderId.toString());
try {
// 模拟业务处理
validateOrder(orderId);
calculatePrice(orderId);
saveOrder(orderId);
// 记录日志,包含TraceID
log.info("订单处理完成,订单ID:{},TraceID:{}",
orderId, TraceContext.traceId());
return "SUCCESS";
} catch (Exception e) {
// 标记Span为错误状态
ActiveSpan.error(e);
log.error("订单处理失败,订单ID:{}", orderId, e);
return "FAIL";
}
}
/**
* 子方法也会被追踪
*/
@Trace
private void validateOrder(Long orderId) {
// 模拟验证逻辑
ActiveSpan.tag("step", "validate");
}
/**
* 子方法也会被追踪
*/
@Trace
private void calculatePrice(Long orderId) {
// 模拟计算价格
ActiveSpan.tag("step", "calculate");
}
/**
* 子方法也会被追踪
*/
@Trace
private void saveOrder(Long orderId) {
// 模拟保存订单
ActiveSpan.tag("step", "save");
}
}

@Trace注解会让 SkyWalking 对方法进行追踪,创建相应的 Span。ActiveSpan类可以用来添加标签、记录错误等。通过自定义埋点,我们可以更细致地追踪业务流程,特别是核心业务逻辑的执行情况。

5.2 自定义指标与仪表盘

SkyWalking 允许我们定义自定义指标,并在 UI 中创建自定义仪表盘来展示这些指标。

创建自定义指标:

  1. 首先,在代码中使用 SkyWalking API 记录自定义指标:

java

import org.apache.skywalking.apm.toolkit.meter.MeterFactory;
import org.apache.skywalking.apm.toolkit.meter.api.Counter;
import org.apache.skywalking.apm.toolkit.meter.api.Gauge;
import org.apache.skywalking.apm.toolkit.meter.api.Histogram;
import org.springframework.stereotype.Service;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 自定义指标服务
*
* @author ken
*/
@Service
public class CustomMetricService {
// 订单创建计数器
private final Counter orderCreateCounter = MeterFactory.counter("order.create.count")
.tag("status", "success")
.build();
// 订单支付计数器
private final Counter orderPayCounter = MeterFactory.counter("order.pay.count")
.tag("status", "success")
.build();
// 库存 gauge 指标
private final AtomicInteger inventory = new AtomicInteger(1000);
private final Gauge inventoryGauge = MeterFactory.gauge("product.inventory", inventory::get)
.tag("product", "phone")
.build();
// 订单金额直方图
private final Histogram orderAmountHistogram = MeterFactory.histogram("order.amount")
.tag("type", "normal")
.build();
/**
* 记录订单创建
*/
public void recordOrderCreate() {
orderCreateCounter.increment();
}
/**
* 记录订单支付
*/
public void recordOrderPay() {
orderPayCounter.increment();
}
/**
* 更新库存
*/
public void updateInventory(int amount) {
inventory.addAndGet(amount);
}
/**
* 记录订单金额
*/
public void recordOrderAmount(double amount) {
orderAmountHistogram.observe(amount);
}
}
  1. 在业务代码中使用这些指标:
@Service
public class OrderService {
@Autowired
private CustomMetricService metricService;
public void createOrder(Order order) {
// 业务逻辑...
// 记录指标
metricService.recordOrderCreate();
metricService.recordOrderAmount(order.getAmount());
metricService.updateInventory(-order.getQuantity());
}
public void payOrder(Long orderId) {
// 业务逻辑...
// 记录指标
metricService.recordOrderPay();
}
}
  1. 在 SkyWalking UI 中创建自定义仪表盘:
  • 登录 SkyWalking UI
  • 点击右上角的 "+" 号,选择 "创建仪表盘"
  • 输入仪表盘名称和描述
  • 点击 "添加图表",选择自定义指标
  • 配置图表类型、时间范围等
  • 保存仪表盘

通过自定义指标和仪表盘,我们可以监控业务层面的关键指标,如订单量、支付转化率、库存水平等,实现技术指标与业务指标的统一监控。

5.3 SkyWalking 插件开发

SkyWalking 的插件机制允许我们扩展其功能,支持更多的框架和组件。下面以开发一个简单的插件为例,介绍插件开发的基本流程。

插件开发步骤:

  1. 创建插件项目,pom.xml配置:

xml

4.0.0
com.example
skywalking-custom-plugin
1.0.0
8.16.0
17
org.apache.skywalking
apm-agent-core
${skywalking.version}
provided
org.apache.skywalking
apm-util
${skywalking.version}
provided
com.example
custom-framework
1.0.0
provided
org.apache.maven.plugins
maven-compiler-plugin
3.8.1
${java.version}
${java.version}
  1. 创建增强类:
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.matcher.ElementMatcher;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
/**
* 自定义框架插件定义
*
* @author ken
*/
public class CustomFrameworkPlugin extends ClassInstanceMethodsEnhancePluginDefine {
/**
* 定义需要增强的类
*/
@Override
protected ClassMatch enhanceClass() {
// 匹配com.example.framework.CustomService类
return byName("com.example.framework.CustomService");
}
/**
* 定义构造方法拦截点
*/
@Override
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
return new ConstructorInterceptPoint[0];
}
/**
* 定义实例方法拦截点
*/
@Override
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
return new InstanceMethodsInterceptPoint[]{
new InstanceMethodsInterceptPoint() {
@Override
public ElementMatcher getMethodsMatcher() {
// 匹配execute方法
return named("execute");
}
@Override
public String getMethodsInterceptor() {
// 拦截器类
return "com.example.plugin.CustomServiceInterceptor";
}
@Override
public boolean isOverrideArgs() {
return false;
}
}
};
}
}
  1. 创建拦截器类:
import org.apache.skywalking.apm.agent.core.context.ContextCarrier;
import org.apache.skywalking.apm.agent.core.context.ContextManager;
import org.apache.skywalking.apm.agent.core.context.tag.Tags;
import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
import org.apache.skywalking.apm.agent.core.interceptor.enhance.EnhancedInstance;
import org.apache.skywalking.apm.agent.core.interceptor.enhance.InstanceMethodsAroundInterceptor;
import org.apache.skywalking.apm.agent.core.interceptor.enhance.MethodInterceptResult;
import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
import java.lang.reflect.Method;
/**
* 自定义服务拦截器
*
* @author ken
*/
public class CustomServiceInterceptor implements InstanceMethodsAroundInterceptor {
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments,
Class[] argumentsTypes, MethodInterceptResult result) throws Throwable {
// 创建一个新的Span
AbstractSpan span = ContextManager.createLocalSpan("CustomService.execute()");
// 设置组件类型
span.setComponent(ComponentsDefine.CUSTOM);
// 设置层级为中间件
SpanLayer.asMiddleware(span);
// 添加标签
if (allArguments != null && allArguments.length > 0) {
Tags.ARGS.set(span, String.valueOf(allArguments[0]));
}
}
@Override
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments,
Class[] argumentsTypes, Object ret) throws Throwable {
// 结束Span
ContextManager.stopSpan();
return ret;
}
@Override
public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
Class[] argumentsTypes, Throwable t) {
// 记录异常
ContextManager.activeSpan().log(t);
}
}
  1. 创建插件描述文件:

src/main/resources目录下创建skywalking-plugin.def文件:

custom-framework-plugin=com.example.plugin.CustomFrameworkPlugin
  1. 打包插件:
mvn clean package
  1. 安装插件:

将生成的 jar 包复制到 SkyWalking Agent 的plugins目录下,重启应用即可生效。

通过开发自定义插件,我们可以扩展 SkyWalking 的监控能力,使其支持特定的框架、组件或业务逻辑,满足个性化的监控需求。

5.4 SkyWalking 与 Kubernetes 集成

在云原生环境中,SkyWalking 可以与 Kubernetes 无缝集成,实现对容器化应用的全面监控。

在 Kubernetes 中部署 SkyWalking:

  1. 创建命名空间:

yaml

apiVersion: v1
kind: Namespace
metadata:
name: skywalking
  1. 部署 Elasticsearch:

yaml

apiVersion: apps/v1
kind: StatefulSet
metadata:
name: elasticsearch
namespace: skywalking
spec:
serviceName: elasticsearch
replicas: 1
selector:
matchLabels:
app: elasticsearch
template:
metadata:
labels:
app: elasticsearch
spec:
containers:
- name: elasticsearch
image: elasticsearch:8.11.3
ports:
- containerPort: 9200
name: rest
protocol: TCP
- containerPort: 9300
name: inter-node
protocol: TCP
env:
- name: discovery.type
value: single-node
- name: xpack.security.enabled
value: "false"
- name: ES_JAVA_OPTS
value: -Xms512m -Xmx512m
resources:
limits:
cpu: 1
memory: 1Gi
requests:
cpu: 500m
memory: 512Mi
volumeMounts:
- name: data
mountPath: /usr/share/elasticsearch/data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 10Gi
---
apiVersion: v1
kind: Service
metadata:
name: elasticsearch
namespace: skywalking
spec:
selector:
app: elasticsearch
ports:
- port: 9200
targetPort: 9200
clusterIP: None
  1. 部署 SkyWalking OAP Server:

yaml

apiVersion: apps/v1
kind: Deployment
metadata:
name: skywalking-oap
namespace: skywalking
spec:
replicas: 1
selector:
matchLabels:
app: skywalking-oap
template:
metadata:
labels:
app: skywalking-oap
spec:
containers:
- name: skywalking-oap
image: apache/skywalking-oap-server:9.7.0
ports:
- containerPort: 11800
name: grpc
- containerPort: 12800
name: rest
env:
- name: SW_STORAGE
value: elasticsearch
- name: SW_STORAGE_ES_CLUSTER_NODES
value: elasticsearch:9200
- name: JAVA_OPTS
value: -Xms512m -Xmx512m
---
apiVersion: v1
kind: Service
metadata:
name: skywalking-oap
namespace: skywalking
spec:
selector:
app: skywalking-oap
ports:
- port: 11800
targetPort: 11800
name: grpc
- port: 12800
targetPort: 12800
name: rest
  1. 部署 SkyWalking UI:

yaml

apiVersion: apps/v1
kind: Deployment
metadata:
name: skywalking-ui
namespace: skywalking
spec:
replicas: 1
selector:
matchLabels:
app: skywalking-ui
template:
metadata:
labels:
app: skywalking-ui
spec:
containers:
- name: skywalking-ui
image: apache/skywalking-ui:9.7.0
ports:
- containerPort: 8080
env:
- name: SW_OAP_ADDRESS
value: http://skywalking-oap:12800
---
apiVersion: v1
kind: Service
metadata:
name: skywalking-ui
namespace: skywalking
spec:
selector:
app: skywalking-ui
ports:
- port: 80
targetPort: 8080
type: NodePort
  1. 在 Kubernetes 中部署应用时集成 SkyWalking Agent:

yaml

apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-service
spec:
replicas: 1
selector:
matchLabels:
app: demo-service
template:
metadata:
labels:
app: demo-service
spec:
initContainers:
- name: init-agent
image: busybox:1.35
command:
- sh
- -c
- wget -q -O /skywalking/agent.tar.gz https://archive.apache.org/dist/skywalking/java-agent/8.16.0/apache-skywalking-java-agent-8.16.0.tgz && tar -zxf /skywalking/agent.tar.gz -C /skywalking
volumeMounts:
- name: skywalking-agent
mountPath: /skywalking
containers:
- name: demo-service
image: demo-service:1.0.0
ports:
- containerPort: 8080
env:
- name: JAVA_OPTS
value: >-
-javaagent:/skywalking/agent/skywalking-agent.jar
-Dskywalking.agent.service_name=demo-service
-Dskywalking.collector.backend_service=skywalking-oap.skywalking:11800
volumeMounts:
- name: skywalking-agent
mountPath: /skywalking
volumes:
- name: skywalking-agent
emptyDir: {}

通过这种方式,我们可以在 Kubernetes 环境中实现 SkyWalking 的完整部署,并对容器化应用进行全面监控。SkyWalking 能够自动识别 Kubernetes 中的服务和实例,提供与容器平台深度集成的监控能力。

六、SkyWalking 性能优化与最佳实践

6.1 Agent 性能优化

SkyWalking Agent 作为嵌入在应用中的组件,其性能对整个系统有直接影响。以下是一些优化 Agent 性能的建议:

  1. 合理设置采样率

    • 高流量系统可以降低采样率(如 1%),减少数据量
    • 关键业务或调试期间可以提高采样率(如 100%)
    • 配置方式:agent.sample_n_per_3_secs=1(每 3 秒采样 1 个请求)
  2. 禁用不必要的插件

    • SkyWalking 默认启用所有插件,对于不需要的插件可以禁用
    • 配置方式:plugin.mount=!mysql,!redis(禁用 mysql 和 redis 插件)
  3. 调整缓存大小

    • 对于高并发系统,可以适当增大 Agent 的缓存
    • 配置方式:agent.buffer_size=30000(设置缓存大小为 30000)
  4. 异步报告数据

    • 确保 Agent 使用异步方式向 OAP Server 报告数据
    • 配置方式:agent.force_tls=false(禁用 TLS,提高传输效率)
  5. 合理设置批量发送参数

    • 调整批量发送的大小和间隔,平衡实时性和性能
    • 配置方式:

      plaintext

      agent.batch_size=1000
      agent.batch_interval=3000

6.2 OAP Server 性能优化

OAP Server 作为数据处理和分析的核心,其性能优化同样重要:

  1. 集群部署

    • 对于大规模系统,OAP Server 应采用集群部署,分担负载
    • 配置方式:通过cluster配置项设置集群模式(如 zookeeper、kubernetes)
  2. 调整 JVM 参数

    • 根据服务器配置合理分配内存,避免 OOM 或 GC 问题
    • 推荐配置:-Xms4g -Xmx8g -XX:+UseG1GC -XX:MaxGCPauseMillis=200
  3. 优化存储配置

    • 使用性能更好的存储介质(如 Elasticsearch 集群)
    • 调整索引生命周期管理,自动清理过期数据
    • 配置方式:在application.yml中设置storage.elasticsearch.indexTTL
  4. 水平扩展

    • 根据数据量和查询压力,增加 OAP Server 实例数量
    • 确保存储层也能相应扩展
  5. 优化线程池配置

    • 根据 CPU 核心数调整处理线程池大小
    • 配置方式:在application.yml中调整core.default.workers

6.3 存储优化

存储是 SkyWalking 性能的关键瓶颈之一,合理的存储优化可以显著提升系统性能:

  1. 选择合适的存储介质

    • 中小规模系统:可以使用 MySQL 或 TiDB
    • 大规模系统:推荐使用 Elasticsearch 集群
    • 超大规模系统:考虑使用专门的时序数据库(如 InfluxDB、TimescaleDB)
  2. Elasticsearch 优化

    • 增加数据节点数量,提高存储和查询性能
    • 合理设置分片和副本数量(推荐分片数 = 数据节点数)
    • 配置索引生命周期管理(ILM),自动删除过期数据
    • 调整刷新间隔(index.refresh_interval),平衡实时性和性能
  3. 数据保留策略

    • 根据业务需求设置不同数据的保留时间
    • 配置方式:

      yaml

      storage:
      elasticsearch:
      traceDataTTL: 7 # 追踪数据保留7天
      metricsDataTTL: 30 # 指标数据保留30天
      logDataTTL: 15 # 日志数据保留15天
  4. 定期优化

    • 定期执行存储优化操作(如 ES 的 force merge)
    • 监控存储性能指标,及时扩容

6.4 生产环境最佳实践

在生产环境中使用 SkyWalking,建议遵循以下最佳实践:

  1. 分环境部署

    • 开发、测试、生产环境使用独立的 SkyWalking 部署
    • 生产环境配置应更注重性能和稳定性
  2. 渐进式接入

    • 初次接入时,可以先选择非核心服务进行试点
    • 逐步扩大监控范围,观察系统性能影响
  3. 完善的监控告警

    • 不仅监控业务系统,也要监控 SkyWalking 自身
    • 设置关键指标的告警阈值,及时发现问题
  4. 安全配置

    • 生产环境应启用 TLS 加密传输
    • 限制 UI 和 API 的访问权限
    • 敏感数据脱敏处理
  5. 定期备份

    • 定期备份 SkyWalking 的配置和数据
    • 制定灾难恢复计划
  6. 持续优化

    • 定期 review 监控数据,优化系统性能
    • 关注 SkyWalking 新版本,及时升级获取新功能和性能优化
  7. 文档和培训

    • 建立 SkyWalking 使用文档
    • 对开发和运维人员进行培训,提高问题排查效率

七、总结与展望

SkyWalking 作为一款优秀的开源分布式追踪系统,为我们解决分布式系统的可观测性问题提供了全面的解决方案。从核心原理来看,它通过字节码增强技术实现了对应用的无侵入式监控,通过分布式追踪上下文传播将分散的服务调用关联起来,形成完整的调用链。

在功能上,SkyWalking 不仅提供了基础的服务拓扑图和调用链追踪,还整合了性能指标监控、日志分析和告警功能,形成了一个完整的可观测性平台。通过本文的介绍,我们了解了 SkyWalking 的核心概念、工作原理、环境搭建、功能使用以及高级特性。

从实践角度来看,SkyWalking 的优势在于:

  • 对应用的侵入性小,部署和使用简单
  • 性能优秀,对系统的影响小
  • 支持多种语言和框架,兼容性好
  • 提供丰富的可视化界面,易于理解和使用
  • 可扩展性强,支持自定义埋点、指标和插件

掌握 SkyWalking 不仅能帮助我们快速定位分布式系统中的问题,还能让我们更深入地理解系统的运行状态,为系统优化和架构演进提供数据支持。希望本文能成为你学习和使用 SkyWalking 的有益指南,让你在分布式系统的复杂世界中,拥有一双 "透视" 的眼睛。

http://www.hskmm.com/?act=detail&tid=16908

相关文章:

  • 系统调用brk 和 mmap 有什么不同?
  • 雷达系统杂波设计与仿真
  • 国标GB28181视频平台EasyCVR一体化加油站安防视频监控方案与实践
  • JavaScript 沙箱
  • PDF入参以及模板对应签章图踩坑点
  • 高性能PCIe 3.0软核,x1~x16,支持EP/RC,AXI4接口,内置DMA控制器,适用ASIC和FPGA
  • 使用git clone 批量下载huggingface模型文件
  • Python 换进安装GDAL
  • sync(同步本地文件到OSS)
  • MyBatisPlus 会默认设置 mybatis 的 scanPackages 为当前 BeanFactory 的 auto-configuration 的 base packages
  • 工程实践 使用本地包开发python项目
  • 详细介绍:Python + Flask + API Gateway + Lambda + EKS 实战
  • 日记4
  • P2042 [NOI2005] 维护数列 题解
  • 达梦数据库查询字段类型为Date 修改为DateTime
  • C++ new 操作符在操作系统层执行了什么操作?
  • [ABC422F-G] 题解
  • 别再靠 “关设备” 减碳!EMS 的 “预测性控能”,让企业满产也能达标双碳
  • LAMP 架构说明及部署实践 - 教程
  • MyEMS 深度解析:核心功能模块、数据流转逻辑与工业能源优化落地路径
  • kettle插件-国产数据库金仓插件,助力国产数据库腾飞
  • 制造业碳足迹追踪:开源能源管理系统如何助力企业实现“碳数据可视化”?
  • iframe安全盲区:支付信息窃取攻击的新温床 - 教程
  • 综合网表中有assign怎么办
  • 极限与导数
  • 呼叫中心开源社区专栏第一篇 - 详解
  • 原核表达可溶性蛋白难题破解
  • 深入解析:Adobe Fresco下载教程Adobe Fresco 2025保姆级安装步骤(附安装包)
  • Torch中的tensor size
  • Codeforces 1053 (Div.2)