
👋 大家好,欢迎来到我的技术博客!
📚 在这里,我会分享学习笔记、实战经验与技术思考,力求用简单的方式讲清楚复杂的问题。
🎯 本文将围绕SkyWalking 这个话题展开,希望能为你带来一些启发或实用的参考。
🌱 无论你是刚入门的新手,还是正在进阶的开发者,希望你都能有所收获!
文章目录
- [SkyWalking - Spring Cloud Alibaba 全链路追踪实战 🚀](#SkyWalking - Spring Cloud Alibaba 全链路追踪实战 🚀)
-
- [1. 环境准备与核心概念 🧰](#1. 环境准备与核心概念 🧰)
-
- [1.1 核心概念解析](#1.1 核心概念解析)
- [1.2 环境准备](#1.2 环境准备)
- [2. 构建 Spring Cloud Alibaba 微服务项目 🏗️](#2. 构建 Spring Cloud Alibaba 微服务项目 🏗️)
-
- [2.1 创建父工程](#2.1 创建父工程)
- [2.2 构建 `inventory-service`(库存服务)](#2.2 构建
inventory-service(库存服务)) - [2.3 构建 `order-service`(订单服务)](#2.3 构建
order-service(订单服务)) - [2.4 验证基础功能](#2.4 验证基础功能)
- [3. 集成 SkyWalking Agent 🕵️♂️](#3. 集成 SkyWalking Agent 🕵️♂️)
-
- [3.1 下载 SkyWalking Agent](#3.1 下载 SkyWalking Agent)
- [3.2 配置 Agent](#3.2 配置 Agent)
- [3.3 启动应用并挂载 Agent](#3.3 启动应用并挂载 Agent)
-
- [启动 `inventory-service`](#启动
inventory-service) - [启动 `order-service`](#启动
order-service)
- [启动 `inventory-service`](#启动
- [3.4 验证追踪效果](#3.4 验证追踪效果)
- [4. 深入 SkyWalking:自定义追踪与告警 ⚙️](#4. 深入 SkyWalking:自定义追踪与告警 ⚙️)
-
- [4.1 手动埋点(Manual Context Propagation)](#4.1 手动埋点(Manual Context Propagation))
- [4.2 配置告警](#4.2 配置告警)
- [5. 高级特性与最佳实践 🧠](#5. 高级特性与最佳实践 🧠)
-
- [5.1 日志集成(Log Integration)](#5.1 日志集成(Log Integration))
- [5.2 性能剖析(Profile)](#5.2 性能剖析(Profile))
- [5.3 生产环境最佳实践](#5.3 生产环境最佳实践)
- [6. 总结与展望 🌈](#6. 总结与展望 🌈)
SkyWalking - Spring Cloud Alibaba 全链路追踪实战 🚀
在微服务架构日益普及的今天,一个请求往往需要穿越多个服务才能完成。这种分布式调用虽然带来了系统解耦和扩展性优势,但也给问题排查、性能分析和系统监控带来了巨大挑战。当用户反馈"系统变慢"或"请求失败"时,我们如何快速定位问题发生在哪个服务?是数据库慢了?还是某个中间件响应延迟?亦或是网络抖动?这时候,全链路追踪(Distributed Tracing) 就显得尤为重要。
Apache SkyWalking 是一款开源的 APM(Application Performance Monitoring)系统,专为微服务、云原生和容器化环境设计。它提供了强大的分布式追踪、服务网格遥测分析、度量聚合和可视化一体化解决方案。而 Spring Cloud Alibaba 则是一套基于 Spring Cloud 的微服务开发工具集,它整合了阿里巴巴的中间件,如 Nacos(服务发现与配置中心)、Sentinel(流量控制)、Seata(分布式事务)等,极大地简化了微服务应用的开发和治理。
将 SkyWalking 与 Spring Cloud Alibaba 结合,可以构建一个功能强大、可观测性极佳的微服务系统。本文将带你从零开始,搭建一个基于 Spring Cloud Alibaba 的微服务项目,并集成 SkyWalking,实现端到端的全链路追踪。
1. 环境准备与核心概念 🧰
在动手之前,我们需要先了解一些核心概念,并准备好必要的环境。
1.1 核心概念解析
- Trace(追踪): 一次完整的请求调用链。从用户发起请求到最终返回结果,整个过程中所有经过的服务和操作都属于同一个 Trace。
- Span(跨度): Trace 中的一个基本工作单元。例如,一个服务内部的方法调用、一次数据库查询、一次 HTTP 请求都可以是一个 Span。Span 之间存在父子关系,共同构成一棵调用树。
- Segment(片段): SkyWalking 特有的概念。在一个 JVM 进程内,一次 Trace 可能会生成多个 Segment。每个 Segment 代表了该进程内的一段连续的执行路径。SkyWalking Agent 会将这些 Segment 上报给 OAP Server,OAP Server 再将它们拼接成完整的 Trace。
- OAP Server(Observability Analysis Platform): SkyWalking 的后端服务,负责接收、分析、聚合来自各个 Agent 的数据,并提供查询接口。
- UI: SkyWalking 提供的 Web 可视化界面,用于展示拓扑图、服务列表、追踪详情、性能指标等。
- Agent : 一个 Java Agent,以
-javaagent参数的方式挂载到你的 Java 应用上。它会在不修改你代码的情况下,通过字节码增强技术自动收集应用的追踪数据和性能指标。
1.2 环境准备
为了顺利进行本次实战,你需要准备以下环境:
- JDK 8+: 用于编译和运行 Java 应用。
- Maven: 用于项目依赖管理和构建。
- Docker & Docker Compose: 用于快速部署 SkyWalking 后端服务(OAP Server + UI)和 Nacos。
- IDEA 或其他 Java IDE: 用于开发。
首先,我们需要启动 SkyWalking 和 Nacos。这里我们使用 docker-compose 来一键部署。
创建一个 docker-compose.yml 文件:
yaml
version: '3.8'
services:
nacos:
image: nacos/nacos-server:v2.2.3
container_name: nacos-standalone
environment:
- MODE=standalone
ports:
- "8848:8848"
- "9848:9848" # 用于 gRPC 通信
restart: always
oap:
image: apache/skywalking-oap-server:9.7.0
container_name: skywalking-oap
ports:
- "11800:11800" # gRPC 端口 (旧版)
- "12800:12800" # HTTP 端口
environment:
- SW_STORAGE=h2 # 使用 H2 内存数据库,生产环境请用 ES
depends_on:
- nacos
restart: always
ui:
image: apache/skywalking-ui:9.7.0
container_name: skywalking-ui
ports:
- "8080:8080"
environment:
- SW_OAP_ADDRESS=oap:12800
depends_on:
- oap
restart: always
在终端中执行 docker-compose up -d,等待几分钟,所有服务就会启动完毕。
- Nacos : 访问
http://localhost:8848/nacos,默认账号密码都是nacos。 - SkyWalking UI : 访问
http://localhost:8080,即可看到 SkyWalking 的仪表盘。
现在,我们的基础设施已经就绪!接下来,让我们开始构建微服务应用。
2. 构建 Spring Cloud Alibaba 微服务项目 🏗️
我们将构建一个简单的电商场景:用户下单。这个场景涉及两个核心服务:
order-service: 订单服务,负责创建订单。inventory-service: 库存服务,负责扣减库存。
order-service 会通过 Feign 调用 inventory-service。
2.1 创建父工程
首先,创建一个 Maven 父工程 skywalking-sca-demo,用于统一管理依赖版本。
xml
<!-- pom.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>skywalking-sca-demo</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<modules>
<module>order-service</module>
<module>inventory-service</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.18</version>
<relativePath/>
</parent>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-cloud.version>2021.0.8</spring-cloud.version>
<spring-cloud-alibaba.version>2021.0.5.0</spring-cloud-alibaba.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- Spring Cloud -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Spring Cloud Alibaba -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2.2 构建 inventory-service(库存服务)
这是一个简单的服务,提供一个 /deduct 接口用于扣减库存。
- 添加依赖 (
pom.xml):
xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.example</groupId>
<artifactId>skywalking-sca-demo</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>inventory-service</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Nacos 服务发现 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
</project>
- 配置文件 (
application.yml):
yaml
server:
port: 8082
spring:
application:
name: inventory-service # 服务名,在 Nacos 中注册
cloud:
nacos:
discovery:
server-addr: localhost:8848 # Nacos 地址
# 开启 Actuator 健康检查端点,便于 SkyWalking 监控
management:
endpoints:
web:
exposure:
include: '*'
- 主启动类:
java
package com.example.inventory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient // 启用服务发现
public class InventoryServiceApplication {
public static void main(String[] args) {
SpringApplication.run(InventoryServiceApplication.class, args);
}
}
- 控制器:
java
package com.example.inventory.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/inventory")
public class InventoryController {
private static final Logger log = LoggerFactory.getLogger(InventoryController.class);
@PostMapping("/deduct")
public String deduct(@RequestParam String productId, @RequestParam Integer count) {
log.info("收到扣减库存请求: productId={}, count={}", productId, count);
// 模拟业务处理时间
try {
Thread.sleep(200);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
log.info("库存扣减成功");
return "success";
}
}
2.3 构建 order-service(订单服务)
这个服务会暴露一个 /create 接口,并通过 Feign 调用 inventory-service。
- 添加依赖 (
pom.xml):
xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.example</groupId>
<artifactId>skywalking-sca-demo</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>order-service</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Nacos 服务发现 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- OpenFeign 用于服务间调用 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
</project>
- 配置文件 (
application.yml):
yaml
server:
port: 8081
spring:
application:
name: order-service
cloud:
nacos:
discovery:
server-addr: localhost:8848
# Feign 配置
feign:
client:
config:
default:
connectTimeout: 5000
readTimeout: 5000
management:
endpoints:
web:
exposure:
include: '*'
- 主启动类:
java
package com.example.order;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients // 启用 Feign
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
}
- 定义 Feign Client:
java
package com.example.order.feign;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
// value 指向 Nacos 中注册的服务名
@FeignClient(value = "inventory-service")
public interface InventoryFeignClient {
@PostMapping("/inventory/deduct")
String deduct(@RequestParam("productId") String productId, @RequestParam("count") Integer count);
}
- 控制器:
java
package com.example.order.controller;
import com.example.order.feign.InventoryFeignClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/order")
public class OrderController {
private static final Logger log = LoggerFactory.getLogger(OrderController.class);
@Autowired
private InventoryFeignClient inventoryFeignClient;
@PostMapping("/create")
public String createOrder(@RequestParam String userId, @RequestParam String productId, @RequestParam Integer count) {
log.info("收到创建订单请求: userId={}, productId={}, count={}", userId, productId, count);
// 调用库存服务
String result = inventoryFeignClient.deduct(productId, count);
log.info("订单创建成功");
return "order created, inventory result: " + result;
}
}
2.4 验证基础功能
现在,我们可以分别启动两个服务。
- 启动
inventory-service。 - 启动
order-service。
访问 Nacos 控制台 (http://localhost:8848/nacos),你应该能看到 order-service 和 inventory-service 都已成功注册。
然后,使用 curl 或 Postman 调用订单服务:
bash
curl -X POST "http://localhost:8081/order/create?userId=1&productId=P001&count=1"
如果返回 order created, inventory result: success,说明我们的微服务调用链路是通的!
然而,此时如果我们想了解这次调用的详细耗时、经过了哪些服务,或者排查性能瓶颈,我们无从下手。这就是 SkyWalking 大显身手的时候了。
3. 集成 SkyWalking Agent 🕵️♂️
SkyWalking 的核心在于其 Java Agent。它通过字节码增强技术,在应用运行时动态地注入追踪逻辑,无需修改一行业务代码。
3.1 下载 SkyWalking Agent
访问 Apache SkyWalking 官方下载页面,下载与你的 OAP Server 版本(9.7.0)匹配的 Agent 包。通常选择 apache-skywalking-java-agent-*.tar.gz。
下载后,将其解压到一个目录,例如 /opt/skywalking-agent。解压后的目录结构大致如下:
skywalking-agent/
├── activations/
├── bootstrap-plugins/
├── config/
│ └── agent.config <-- 主配置文件
├── licenses/
├── logs/
├── optional-plugins/
├── plugins/
└── skywalking-agent.jar <-- 核心 Jar 包
3.2 配置 Agent
我们需要对 config/agent.config 文件进行一些关键配置。
properties
# The service name in UI
agent.service_name=${SW_AGENT_NAME:Your_ApplicationName}
# Backend service addresses.
collector.backend_service=${SW_AGENT_COLLECTOR_BACKEND_SERVICES:127.0.0.1:11800}
# Logging file name
logging.file_name=${SW_LOGGING_FILE_NAME:skywalking-api.log}
# Logging level
logging.level=${SW_LOGGING_LEVEL:INFO}
我们将为两个服务创建各自的配置文件,以区分它们在 SkyWalking UI 中的显示。
-
为
order-service创建配置 :在
skywalking-agent/config/目录下创建order-service.config:propertiesagent.service_name=order-service collector.backend_service=127.0.0.1:11800 -
为
inventory-service创建配置 :在
skywalking-agent/config/目录下创建inventory-service.config:propertiesagent.service_name=inventory-service collector.backend_service=127.0.0.1:11800
3.3 启动应用并挂载 Agent
现在,我们需要通过 -javaagent 参数来启动我们的 Java 应用。
启动 inventory-service
bash
java -javaagent:/opt/skywalking-agent/skywalking-agent.jar \
-Dskywalking.agent.config_path=/opt/skywalking-agent/config/inventory-service.config \
-jar inventory-service/target/inventory-service-1.0.0.jar
启动 order-service
bash
java -javaagent:/opt/skywalking-agent/skywalking-agent.jar \
-Dskywalking.agent.config_path=/opt/skywalking-agent/config/order-service.config \
-jar order-service/target/order-service-1.0.0.jar
注意 : 请将
/opt/skywalking-agent替换为你实际的 Agent 路径。
启动成功后,你会在应用的日志中看到类似 [SkyWalking Agent] ... 的信息,表明 Agent 已成功加载。
3.4 验证追踪效果
再次调用我们的订单接口:
bash
curl -X POST "http://localhost:8081/order/create?userId=1&productId=P001&count=1"
然后,打开 SkyWalking UI (http://localhost:8080)。
-
查看服务拓扑图 :
在左侧菜单栏点击 Topology 。你会看到一个清晰的拓扑图,展示了
order-service和inventory-service之间的调用关系。箭头方向表示调用流向。HTTP
Feign/HTTP
Browser/User
order-service
inventory-service -
查看追踪列表 :
点击 Trace 菜单。在这里,你可以看到所有被追踪的请求。找到你刚刚发起的请求(可以通过时间、Endpoint
/order/create来筛选),点击它。 -
分析追踪详情 :
在追踪详情页,你会看到一个非常直观的瀑布流图(Gantt Chart)。它清晰地展示了整个调用链路:
- 最顶层是
order-service的/order/create请求。 - 展开后,可以看到它内部调用了
inventory-service的/inventory/deduct。 - 每个 Span 都标注了耗时,以及发生的时间线。
通过这个图,你可以一目了然地看出哪个环节最耗时。例如,如果
inventory-service的处理时间很长,那么问题很可能出在库存服务本身。 - 最顶层是
4. 深入 SkyWalking:自定义追踪与告警 ⚙️
虽然 SkyWalking Agent 已经为我们自动追踪了大部分场景(如 Spring MVC, Feign, JDBC, Redis 等),但在某些复杂的业务逻辑中,我们可能希望手动创建 Span 来追踪特定的代码块,或者设置告警规则。
4.1 手动埋点(Manual Context Propagation)
假设在 order-service 中,除了调用库存服务,我们还需要记录一个重要的业务日志到数据库,并且我们希望这个数据库操作也能体现在追踪链路中。
- 添加数据库依赖 :
在order-service/pom.xml中添加 H2 数据库和 MyBatis 依赖(仅用于演示)。
xml
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.3.0</version>
</dependency>
- 配置数据库 (
application.yml):
yaml
spring:
# ... 其他配置
datasource:
url: jdbc:h2:mem:testdb
driver-class-name: org.h2.Driver
username: sa
password: password
-
创建 Mapper 和实体:
java// Order.java public class Order { private Long id; private String userId; private String productId; private Integer count; // getters and setters... } // OrderMapper.java @Mapper public interface OrderMapper { @Insert("INSERT INTO orders(user_id, product_id, count) VALUES(#{userId}, #{productId}, #{count})") void insert(Order order); } -
在 Service 中手动埋点 :
SkyWalking 提供了
TraceContextAPI 来手动创建 Span。
java
package com.example.order.service;
import com.example.order.feign.InventoryFeignAssistant;
import com.example.order.mapper.OrderMapper;
import com.example.order.model.Order;
import org.apache.skywalking.apm.toolkit.trace.Trace;
import org.apache.skywalking.apm.toolkit.trace.TraceContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class OrderService {
private static final Logger log = LoggerFactory.getLogger(OrderService.class);
@Autowired
private InventoryFeignAssistant inventoryFeignAssistant;
@Autowired
private OrderMapper orderMapper;
// 使用 @Trace 注解可以自动为方法创建 Span
@Trace
public String createOrder(String userId, String productId, Integer count) {
log.info("开始创建订单");
// 手动创建一个 Span 来包裹数据库操作
String before = TraceContext.traceId(); // 获取当前 TraceId
try (final var ignored = TraceContext.createLocalSpan("OrderService.saveToDB")) {
Order order = new Order();
order.setUserId(userId);
order.setProductId(productId);
order.setCount(count);
orderMapper.insert(order);
log.info("订单已保存到数据库");
}
// 调用库存服务(Feign 调用会被自动追踪)
String result = inventoryFeignAssistant.deduct(productId, count);
log.info("订单创建流程结束");
return "success";
}
}
同时,别忘了在 Controller 中调用这个 Service。
java
// OrderController.java
@Autowired
private OrderService orderService;
@PostMapping("/create")
public String createOrder(...) {
return orderService.createOrder(userId, productId, count);
}
现在,当你再次发起请求并在 SkyWalking UI 中查看追踪详情时,你会发现多了一个名为 OrderService.saveToDB 的 Span,它精确地反映了数据库插入操作的耗时。
4.2 配置告警
SkyWalking 不仅能追踪,还能根据预设的规则进行告警。这对于及时发现线上问题至关重要。
SkyWalking 的告警规则配置在 OAP Server 的 config/alarm-settings.yml 文件中。由于我们是用 Docker 启动的,需要进入容器进行修改。
-
进入 OAP 容器:
bashdocker exec -it skywalking-oap /bin/sh -
编辑告警配置文件:
bashvi config/alarm-settings.yml -
添加一个简单的告警规则 :
例如,我们希望当
order-service的/order/create接口的平均响应时间超过 500ms 时,触发告警。
yaml
rules:
# Rule unique name, must be unique.
service_resp_time_rule:
# Metrics names to be monitored. Only one metric per rule is allowed.
metrics-name: service_resp_time
# The threshold of the metrics. The value should be a number.
threshold: 500
# The period of time in minutes to evaluate the metrics.
period: 10
# How many times after the metrics exceed the threshold, will trigger alarm.
count: 1
# The silence period in minutes after alarm triggered.
silence-period: 10
# Define the scope of the rule.
include-names:
- order-service
exclude-names:
- .*unstable.* # Regular expression, if you want to exclude some services.
# The message format for the alarm.
message: Response time of service {name} is more than {value} ms in {period} minutes.
webhooks:
# Add your webhook URL here to receive alarm messages.
# - http://your-webhook-url
-
重启 OAP 容器 :
修改完配置后,需要重启容器使配置生效。bashdocker restart skywalking-oap
现在,如果你故意在 order-service 中增加一个长时间的 Thread.sleep(600),然后持续调用接口,SkyWalking 就会触发告警。告警信息会显示在 UI 的 Alarm 菜单中。
提示: 在生产环境中,通常会将告警消息通过 Webhook 发送到钉钉、企业微信或 Slack 等即时通讯工具,以便团队能第一时间收到通知。
5. 高级特性与最佳实践 🧠
掌握了基础用法后,让我们探讨一些更高级的特性和在生产环境中应该遵循的最佳实践。
5.1 日志集成(Log Integration)
追踪(Trace)和日志(Log)是可观测性的两大支柱。将它们关联起来,可以极大地提升问题排查效率。SkyWalking 支持将 TraceId 和 SpanId 注入到应用日志中。
-
在
pom.xml中添加依赖:xml<!-- SkyWalking Logback 插件 --> <dependency> <groupId>org.apache.skywalking</groupId> <artifactId>apm-toolkit-logback-1.x</artifactId> <version>8.16.0</version> <!-- 与 Agent 版本保持一致 --> </dependency> -
配置
logback-spring.xml:在
resources目录下创建logback-spring.xml文件。
xml
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%tid] [%thread] %-5level %logger{36} -%msg%n</pattern>
</layout>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
关键点在于 %tid,它会被 SkyWalking Agent 自动替换为当前的 TraceId。
现在,当你查看应用日志时,每条日志都会带上一个唯一的 TraceId。例如:
2023-10-27 10:00:00.123 [TID:1234567890abcdef] [http-nio-8081-exec-1] INFO c.e.o.c.OrderController - 收到创建订单请求...
在 SkyWalking UI 的追踪详情页,你也可以直接点击 Logs 标签,看到与该 Trace 关联的所有日志,前提是你的日志系统(如 ELK)也集成了 SkyWalking 的日志格式。
5.2 性能剖析(Profile)
当某个接口突然变慢,但常规的追踪无法定位到具体是哪一行代码导致的,这时就可以使用 SkyWalking 的 Performance Profiling 功能。它可以在不重启应用的情况下,对指定的 Endpoint 进行 CPU 热点分析。
- 在 SkyWalking UI 中,进入 Trace 页面,找到那个慢的请求。
- 在该 Trace 的详情页,点击右上角的 Profile 按钮。
- 设置采样间隔(如 10ms)和最大采样数(如 1000)。
- 确认后,SkyWalking 会自动在目标 JVM 上开启一个剖析任务。
- 任务完成后,你可以在 Profile 菜单中看到详细的火焰图(Flame Graph),它能精确地告诉你 CPU 时间都花在了哪些方法上。
这是一个非常强大的在线诊断工具,对于解决偶发性性能问题极为有效。
5.3 生产环境最佳实践
- 存储选型 : 本文为了方便,使用了 H2 内存数据库。但在生产环境中,必须使用 Elasticsearch 作为 SkyWalking 的后端存储,以保证数据的持久化和高可用性。
- Agent 升级: 尽量保持 Agent 和 OAP Server 的版本一致,以避免兼容性问题。
- 采样率 : 对于高流量的应用,可以适当调整采样率(
agent.sample_n_per_3_secs),避免上报过多数据给 OAP Server 带来压力。 - 安全: OAP Server 的 gRPC 和 HTTP 端口应做好网络安全隔离,避免暴露在公网。
- 资源监控: 监控 OAP Server 本身的 CPU、内存和磁盘 I/O,确保其健康运行。
6. 总结与展望 🌈
通过本文的实战,我们成功地将 Apache SkyWalking 集成到了一个基于 Spring Cloud Alibaba 的微服务项目中。我们不仅实现了自动化的全链路追踪,还学习了如何手动埋点、配置告警、集成日志以及使用性能剖析等高级功能。
SkyWalking 以其无侵入性 、强大的可视化能力 和丰富的生态系统,成为了微服务可观测性领域的佼佼者。它帮助我们从"盲人摸象"式的故障排查,转变为"上帝视角"下的精准定位,极大地提升了研发和运维效率。
未来,随着云原生和 Service Mesh 的进一步发展,SkyWalking 也在积极拥抱 eBPF、OpenTelemetry 等新技术,为更复杂的混合架构提供统一的可观测性解决方案。对于每一位致力于构建稳定、高效、可维护的现代应用的开发者来说,掌握 SkyWalking 这样的 APM 工具,已经成为一项必备技能。
希望这篇详尽的实战指南能为你在微服务之路上点亮一盏明灯!✨
🙌 感谢你读到这里!
🔍 技术之路没有捷径,但每一次阅读、思考和实践,都在悄悄拉近你与目标的距离。
💡 如果本文对你有帮助,不妨 👍 点赞 、📌 收藏 、📤 分享 给更多需要的朋友!
💬 欢迎在评论区留下你的想法、疑问或建议,我会一一回复,我们一起交流、共同成长 🌿
🔔 关注我,不错过下一篇干货!我们下期再见!✨