链路追踪

文章40 |   阅读 21601 |   点赞0

来源:https://blog.csdn.net/weixin_42073629/category_9940428.html

Spring Boot 链路追踪 SkyWalking 入门

x33g5p2x  于2021-12-21 转载在 其他  
字(53.2k)|赞(0)|评价(0)|浏览(1225)

1. 概述

如果胖友还没了解过分布式链路追踪 SkyWalking,建议先阅读下艿艿写的 《SkyWalking 极简入门》 文章。虽然这篇文章标题是安装部署,实际可以理解成《一文带你快速入门 SkyWalking》,哈哈哈。

可能会有胖友会有疑惑,Spring Boot 不是一个单体应用么,为什么可以使用 SkyWalking 进行分布式链路追踪呢?其实这里有一个误区!即使是一个 Spring Boot 单体应用,我们一般可能会和以下服务打交道:

  • 关系数据库,例如说 MySQL、Oracle、SQLServer、PostgreSQL 等等。
  • 文档数据库,例如说 MongoDB 等等。
  • 缓存数据库,例如说 Redis、Memcached 等等。
  • 外部三方服务,例如说微信公众号、微信支付、支付宝支付、短信平台等等。

那么即使是一个 Spring Boot 单体应用,就已经涉及到分布在不同进程中的服务。此时,就已经满足使用 SkyWalking 进行分布式链路追踪的条件,同时也是非常有必要的。例如说,我们线上某个 API 接口访问非常慢,可以通过 SkyWalking 来排查,是因为 MySQL 查询比较慢呢,还是调用的第三方服务比较慢。

在本文中,我们会比《SkyWalking 极简入门》提供更多在 Spring Boot 中使用的示例。例如说:

  • 对 SpringMVC 的 API 接口的链路追踪
  • 对 JDBC 访问 MySQL 的链路追踪
  • 对 Jedis 访问 Redis 的链路追踪
  • 对 RocketMQ 的消息的发送和消费的链路追踪
  • 等等等等

2. SpringMVC 示例

示例代码对应仓库:lab-39-springmvc

本小节,我们来搭建一个 SkyWalking 对 SpringMVC 的 API 接口的链路追踪。该链路通过如下插件实现收集:

2.1 引入依赖

在 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">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <packaging>jar</packaging>

    <artifactId>lab-39-springmvc</artifactId>

    <dependencies>
        <!-- 实现对 SpringMVC 的自动化配置 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

</project>

2.2 配置文件

在 application.yml 中,添加服务器端口配置,如下:

server:
  port: 8079
  • 置服务器的端口为 8079 ,避免和 SkyWalking UI 占用的 8080 冲突。

2.3 DemoController

在 cn.iocoder.springboot.lab39.skywalkingdemo.controller 包路径下,创建 DemoController 类,提供示例 API 接口。代码如下:

@RestController
@RequestMapping("/demo")
public class DemoController {

    @GetMapping("/echo")
    public String echo() {
        return "echo";
    }

    @GetMapping("/hello")
    public String hello() {
        return "hello";
    }
    
}

2.4 Application

创建 Application.java 类,配置 @SpringBootApplication 注解即可。代码如下:

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
    
}

2.5 IDEA 配置

通过 IDEA 的「Run/Debug Configurations」配置使用 SkyWalking Agent。如下图所示:

然后,执行 Application#main(String[] args) 方法,启动该 Spring Boot 应用。如果说控制台打印如下日志,说明 SkyWalking Agent 基本加载成功:

# 加载 SkyWalking Agent
DEBUG 2020-01-04 09:42:46:091 main AgentPackagePath : The beacon class location is jar:file:/Users/yunai/skywalking/apache-skywalking-apm-bin-es7/agent/skywalking-agent.jar!/org/apache/skywalking/apm/agent/core/boot/AgentPackagePath.class. 
INFO 2020-01-04 09:42:46:094 main SnifferConfigInitializer : Config file found in /Users/yunai/skywalking/apache-skywalking-apm-bin-es7/agent/config/agent.config.

2.6 简单测试

1、首先,使用浏览器,访问下 http://127.0.0.1:8079/demo/echo 地址,请求下 Spring Boot 应用提供的 API。因为,我们要追踪下该链路。

2、然后,继续使用浏览器,打开 http://127.0.0.1:8080/ 地址,进入 SkyWalking UI 界面。如下图所示:

3、之后,点击「拓扑图」菜单,进入查看拓扑图的界面,可以看到 SpringMVC 小方块。如下图所示:

4、再之后,点击「追踪」菜单,进入查看链路数据的界面。如下图所示:

3. 忽略部分 URL 的追踪

示例代码对应仓库:lab-39-springmvc 。

在「2. SpringMVC 示例」小节中,我们已经实现了对 SpringMVC 提供的 HTTP API 接口的链路追踪。但是,我们可能希望忽略部分特殊 URL 的追踪,例如说,健康检查的 HTTP API。

所以,我们可以使用 SkyWalking 提供 trace-ignore-plugin 插件,可以实现忽略部分 URL 的追踪。

本小节,我们无需单独搭建项目,而是直接使用 lab-39-springmvc 项目即可。

3.1 复制插件

trace-ignore-plugin 插件,在 optional-plugins 目录下,是可选插件,所以我们需要复制到 plugins 目录下。命令行操作如下:

# 查看当前所在目录
$ pwd
/Users/yunai/skywalking/apache-skywalking-apm-bin-es7/agent

# 复制插件到 plugins 目录
$ cp optional-plugins/apm-trace-ignore-plugin-6.6.0.jar plugins/

3.2 配置文件

trace-ignore-plugin 插件,读取 apm-trace-ignore-plugin.config 配置文件,默认情况下不存在,所以我们需要进行创建并配置。命令行操作如下:

# 查看当前所在目录
$ pwd
/Users/yunai/skywalking/apache-skywalking-apm-bin-es7/agent

# 创建 apm-trace-ignore-plugin.config 配置文件,并进行设置
$ vi config/apm-trace-ignore-plugin.config

配置文件内容如下: 

# If the operation name of the first span is matching, this segment should be ignored
#  ant path match style
#  /path/?   Match any single character
#  /path/*   Match any number of characters
#  /path/**  Match any number of characters and support multilevel directories
#  Multiple path comma separation, like trace.ignore_path=/eureka/**,/consul/**
trace.ignore_path=${SW_AGENT_TRACE_IGNORE_PATH:/eureka/**}
  • trace.ignore_path 配置项,设置忽略的 URL 路径,基于 Ant 风格路径表达式
  • 这里,我们配置了读取环境变量 SW_AGENT_TRACE_IGNORE_PATH ,这样方便我们自定义。

3.3 IDEA 配置

通过 IDEA 的「Run/Debug Configurations」配置使用 SkyWalking Agent。如下图所示:

然后,执行 Application#main(String[] args) 方法,启动该 Spring Boot 应用。

3.4 简单测试

1、首先,使用浏览器,访问下 http://127.0.0.1:8079/demo/hello 地址,请求下 Spring Boot 应用提供的 API。

2、然后,查看 SkyWaking Agent 日志,可以看到该 URL 的链路追踪被忽略日志。操作命令如下:

# 查看当前所在目录
$ pwd
/Users/yunai/skywalking/apache-skywalking-apm-bin-es7/agent

# 查看 SkyWaking Agent 日志,然后搜 TraceIgnoreExtendService 关键字
$ vi logs/skywalking-api.log +
# 日志示例
DEBUG 2020-01-04 13:07:41:720 http-nio-8079-exec-4 TraceIgnoreExtendService : operationName : /demo/hello Ignore tracking

3、之后,在 SkyWalking UI 的查看链路追踪的界面,也看不到该 URL 对应的链路数据。如下图所示:

4. MySQL 示例

示例代码对应仓库:lab-39-mysql

本小节,我们来搭建一个 SkyWalking 对 MySQL 操作的链路追踪。该链路通过如下插件实现收集:

我们将使用 Spring JdbcTemplate 进行 MySQL 的操作。对 Spring JdbcTemplate 感兴趣的胖友,可以后续去看看《芋道 Spring Boot JdbcTemplate 入门》文章。

4.1 引入依赖

在 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">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <packaging>jar</packaging>

    <artifactId>lab-39-mysql</artifactId>

    <dependencies>
        <!-- 实现对 SpringMVC 的自动化配置 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- 实现对数据库连接池的自动化配置 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency> <!-- 本示例,我们使用 MySQL -->
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.46</version>
        </dependency>
    </dependencies>

</project>

4.2 配置文件

在 application.yml 中,添加 MySQL 配置,如下:

server:
  port: 8079

spring:
  # datasource 数据源配置内容
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/lab-39-mysql?useSSL=false&useUnicode=true&characterEncoding=UTF-8
    driver-class-name: com.mysql.jdbc.Driver
    username: root
    password:

这里,胖友记得在测试的数据库中,创建 t_user 表,并插入一条 id = 1 的记录。SQL 脚本如下: 

CREATE TABLE `t_user` (
  `id` int(8) NOT NULL AUTO_INCREMENT COMMENT '主键自增',
  `username` varchar(50) NOT NULL COMMENT '用户名',
  `password` varchar(50) NOT NULL COMMENT '密码',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='用户表';

INSERT INTO `t_user`(`id`, `username`, `password`) VALUES (1, 'yudaoyuanma', 'nicai');

4.3 DemoController

在 cn.iocoder.springboot.lab39.skywalkingdemo.controller 包路径下,创建 DemoController 类,提供示例 API 接口。代码如下:

@RestController
@RequestMapping("/demo")
public class DemoController {

    @Autowired
    private JdbcTemplate template;

    @GetMapping("/mysql")
    public String mysql() {
        this.selectById(1);
        return "mysql";
    }

    public Object selectById(Integer id) {
        return template.queryForObject("SELECT id, username, password FROM t_user WHERE id = ?",
                new BeanPropertyRowMapper<>(Object.class), // 结果转换成对应的对象。Object 理论来说是 UserDO.class ,这里偷懒了。
                id);
    }

}
  • 在 /demo/mysql 接口中,会执行一次 MySQL 的查询。

4.4 MySQLApplication

创建 MySQLApplication.java 类,配置 @SpringBootApplication 注解即可。代码如下:

@SpringBootApplication
public class MySQLApplication {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
    
}

4.5 IDEA 配置

通过 IDEA 的「Run/Debug Configurations」配置使用 SkyWalking Agent。如下图所示:

然后,执行 MySQLApplication#main(String[] args) 方法,启动该 Spring Boot 应用。

4.6 简单测试

1、首先,使用浏览器,访问下 http://127.0.0.1:8079/demo/mysql 地址,请求下 Spring Boot 应用提供的 API。因为,我们要追踪下该链路。

2、然后,继续使用浏览器,打开 http://127.0.0.1:8080/ 地址,进入 SkyWalking UI 界面。如下图所示:

接着,点击「Database Dashboard」选项,再点击「Database」选项,可以以数据库为维度的监控数据。如下图所示:

3、之后,点击「拓扑图」菜单,进入查看拓扑图的界面,可以看到 MySQL 小方块。如下图所示:

4、再之后,点击「追踪」菜单,进入查看链路数据的界面。如下图所示:

点击红圈的 MySQL 操作的链路数据,可以看到数据的 SQL 语句。如下图所示:

这里,我们暂时无法看到 SQL 的数据参数,可以通过修改 config/agent.config 配置文件,将 plugin.mysql.trace_sql_parameters 配置项,设置为 true 。例如:

# mysql plugin configuration
plugin.mysql.trace_sql_parameters=${SW_MYSQL_TRACE_SQL_PARAMETERS:true}
  • 当然,也可以通过 SW_MYSQL_TRACE_SQL_PARAMETERS 环境变量。

5. Redis 示例

示例代码对应仓库:lab-39-redis

本小节,我们来搭建一个 SkyWalking 对 Redis 操作的链路追踪。该链路通过如下插件实现收集:

我们将使用 Spring Data Redis + Jedis 进行 Redis 的操作。对 Spring Data Redis 感兴趣的胖友,可以后续去看看《Spring Boot Redis 入门》文章。

5.1 引入依赖

在 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">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>lab-39-redis</artifactId>

    <dependencies>
        <!-- 实现对 SpringMVC 的自动化配置 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- 实现对 Spring Data Redis 的自动化配置 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <exclusions>
                <!-- 去掉对 Lettuce 的依赖,因为 Spring Boot 优先使用 Lettuce 作为 Redis 客户端 -->
                <exclusion>
                    <groupId>io.lettuce</groupId>
                    <artifactId>lettuce-core</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- 引入 Jedis 的依赖,这样 Spring Boot 实现对 Jedis 的自动化配置 -->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>
    </dependencies>

</project>

5.2 配置文件

在 application.yml 中,添加 Redis 配置,如下:

server:
  port: 8079

spring:
  # 对应 RedisProperties 类
  redis:
    host: 127.0.0.1
    port: 6379
    password: # Redis 服务器密码,默认为空。生产中,一定要设置 Redis 密码!
    database: 0 # Redis 数据库号,默认为 0 。
    timeout: 0 # Redis 连接超时时间,单位:毫秒。
    # 对应 RedisProperties.Jedis 内部类
    jedis:
      pool:
        max-active: 8 # 连接池最大连接数,默认为 8 。使用负数表示没有限制。
        max-idle: 8 # 默认连接数最小空闲的连接数,默认为 8 。使用负数表示没有限制。
        min-idle: 0 # 默认连接池最小空闲的连接数,默认为 0 。允许设置 0 和 正数。
        max-wait: -1 # 连接池最大阻塞等待时间,单位:毫秒。默认为 -1 ,表示不限制。

5.3 DemoController

在 cn.iocoder.springboot.lab39.skywalkingdemo.controller 包路径下,创建 DemoController 类,提供示例 API 接口。代码如下:

@RestController
@RequestMapping("/demo")
public class DemoController {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @GetMapping("/redis")
    public String redis() {
        this.get("demo");
        return "redis";
    }

    public void get(String key) {
        redisTemplate.opsForValue().get(key);
    }

}
  • 在 /demo/redis 接口中,会执行一次 Redis GET 操作。

5.4 RedisApplication

创建 RedisApplication.java 类,配置 @SpringBootApplication 注解即可。代码如下:

@SpringBootApplication
public class RedisApplication {

    public static void main(String[] args) {
        SpringApplication.run(RedisApplication.class, args);
    }
    
}

5.5 IDEA 配置

通过 IDEA 的「Run/Debug Configurations」配置使用 SkyWalking Agent。如下图所示:

然后,执行 RedisApplication#main(String[] args) 方法,启动该 Spring Boot 应用。

5.6 简单测试

1、首先,使用浏览器,访问下 http://127.0.0.1:8079/demo/redis 地址,请求下 Spring Boot 应用提供的 API。因为,我们要追踪下该链路。

2、然后,继续使用浏览器,打开 http://127.0.0.1:8080/ 地址,进入 SkyWalking UI 界面。如下图所示:

3、之后,点击「拓扑图」菜单,进入查看拓扑图的界面,可以看到 Redis 小方块。如下图所示:

4、再之后,点击「追踪」菜单,进入查看链路数据的界面。如下图所示:

点击红圈的 Redis 操作的链路数据,可以看到 Redis 具体操作。如下图所示:

不过没有看到 Redis 操作的具体参数。因为 Spring Data Redis 会把提前具体参数转换成二进制数组,导致 jedis-2.x-plugin 插件的 JedisMethodInterceptor 不进行收集。代码如下:

// JedisMethodInterceptor.java

// String 类型,则进行收集
if (allArguments.length > 0 && allArguments[0] instanceof String) {
    Tags.DB_STATEMENT.set(span, method.getName() + " " + allArguments[0]);
// byte[] 类型,则不进行收集
} else if (allArguments.length > 0 && allArguments[0] instanceof byte[]) {
    Tags.DB_STATEMENT.set(span, method.getName());
}

6. MongoDB 示例

示例代码对应仓库:lab-39-mongodb

本小节,我们来搭建一个 SkyWalking 对 MongoDB 操作的链路追踪。该链路通过如下插件实现收集:

我们将使用 Spring Data MongoDB 进行 MongoDB 的操作。对 Spring Data MongoDB 感兴趣的胖友,可以后续去看看《Spring Boot MongoDB 入门》文章。

6.1 引入依赖

在 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">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>lab-39-mongodb</artifactId>

    <dependencies>
        <!-- 实现对 SpringMVC 的自动化配置 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- 自动化配置 Spring Data Mongodb -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>
    </dependencies>

</project>

6.2 配置文件

在 application.yml 中,添加 Redis 配置,如下:

server:
  port: 8079

spring:
  data:
    # MongoDB 配置项,对应 MongoProperties 类
    mongodb:
      host: 127.0.0.1
      port: 27017
      database: yourdatabase
      username: test01
      password: password01
      # 上述属性,也可以只配置 uri

6.3 DemoController

在 cn.iocoder.springboot.lab39.skywalkingdemo.controller 包路径下,创建 DemoController 类,提供示例 API 接口。代码如下:

@RestController
@RequestMapping("/demo")
public class DemoController {

    @Autowired
    private MongoTemplate mongoTemplate;

    @GetMapping("/mongodb")
    public String mysql() {
        this.findById(1);
        return "mongodb";
    }

    public UserDO findById(Integer id) {
        return mongoTemplate.findOne(new Query(Criteria.where("_id").is(id)), UserDO.class);
    }

}
  • 在 /demo/mongodb 接口中,会执行一次 MongoDB 查询操作。
  • UserDO 实体类,直接点击查看。

6.4 MongoDBApplication

创建 MongoDBApplication.java 类,配置 @SpringBootApplication 注解即可。代码如下:

// Application.java

@SpringBootApplication
public class MongoDBApplication {

    public static void main(String[] args) {
        SpringApplication.run(MongoDBApplication.class, args);
    }

}

6.5 插件配置

默认情况下,SkyWalking Agent MongoDB 插件,不记录操作参数,需要通过配置。命令行操作如下:

# 查看当前所在目录
$ pwd
/Users/yunai/skywalking/apache-skywalking-apm-bin-es7/agent

# 需改 agent.config 配置文件,并进行设置
$ vi config/agent.config

额外新增如下配置内容如下: 

# mongodb plugin configuration
plugin.mongodb.trace_param=${SW_MONGODB_TRACE_PARAM:false}
  • 这样,默认情况下还是保持不记录操作参数,可通过 SW_MONGODB_TRACE_PARAM 环境变量开启。

6.6 IDEA 配置

通过 IDEA 的「Run/Debug Configurations」配置使用 SkyWalking Agent。如下图所示:

然后,执行 MongoDBApplication#main(String[] args) 方法,启动该 Spring Boot 应用。

6.7 简单测试

1、首先,使用浏览器,访问下 http://127.0.0.1:8079/demo/mongodb 地址,请求下 Spring Boot 应用提供的 API。因为,我们要追踪下该链路。

2、然后,继续使用浏览器,打开 http://127.0.0.1:8080/ 地址,进入 SkyWalking UI 界面。如下图所示:

接着,点击「Database Dashboard」选项,再点击「Database」选项,可以以数据库为维度的监控数据。如下图所示:

3、之后,点击「拓扑图」菜单,进入查看拓扑图的界面,可以看到 MongoDB 小方块。如下图所示:

4、再之后,点击「追踪」菜单,进入查看链路数据的界面。如下图所示:

点击红圈的 MongoDB 操作的链路数据,可以看到操作语句。如下图所示:

7. Elasticsearch 示例

示例代码对应仓库:lab-39-elasticsearch-jest

本小节,我们来搭建一个 SkyWalking 对 Elasticsearch 操作的链路追踪。该链路通过如下插件实现收集:

不过略微翻车了。原因是:

  • SkyWalking 6.6.0 版本的 elasticsearch-5.x-plugin 插件,暂时只支持 transport-client 5.2.x-5.6.x 版本。什么意思呢?如果使用 Elasticsearch TCP 协议的客户端,不能使用 6.X 开始的版本。
  • SkyWalking 6.6.0 版本的 elasticsearch-6.x-plugin 插件,暂时只支持 Elasticsearch Rest 协议的客户端。

听起来好像也没啥问题?目前项目中,一般不会直接使用 Elasticsearch 原生的 TCP 协议和 Rest 协议的客户端,而是采用 Spring Data Elasticsearch 库。该库的主流版本是基于 Elasticsearch TCP 协议的客户端,并且使用 transport-client 的 6.X 开始的版本。因此,在我们使用 Spring Data Elasticsearch 主流版本的情况下,SkyWalking 暂时无法实现对 Elasticsearch 的链路追踪。具体艿艿测试的代码示例,可见 lab-39-elasticsearch 仓库。😈 等后面 SkyWalking 提供了支持,艿艿再来更新一波。

不过,目前 Elasticsearch 官方较为推荐采用它提供的 Rest 协议。所以我们也可以采用 Spring Data Jest 库。而 Spring Data Jest 是基于 Jest 之上,对 Spring Data 的实现。Jest 是基于 Elasticsearch Rest 协议的第三方客户端,其内部采用 HttpClient 发起 HTTP 请求。因此,我们可以采用 SkyWalking 的 httpClient-4.x-plugin 插件,间接实现对 Elasticsearch 的链路追踪。咳咳咳 😈

因此,我们最终使用 Spring Data Jest 进行 Elasticsearch 的操作。对 Elasticsearch 感兴趣的胖友,可以后续去看看《芋道 Spring Boot Elasticsearch 入门》文章。

7.1 引入依赖

在 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">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>lab-39-elasticsearch-jest</artifactId>

    <dependencies>
        <!-- 实现对 SpringMVC 的自动化配置 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- 自动化配置 Spring Data Jest -->
        <dependency>
            <groupId>com.github.vanroy</groupId>
            <artifactId>spring-boot-starter-data-jest</artifactId>
            <version>3.3.0.RELEASE</version>
        </dependency>
    </dependencies>

</project>
  • 具体每个依赖的作用,胖友自己认真看下艿艿添加的所有注释噢。

因为 Spring Data Jest 3.3.0.RELEASE 版本,最高只能支持 Elasticsearch 6.8.4 版本,所以 😭 艿艿又不得不搭建一个 Elasticsearch 6.8.4 版本的服务。心疼自己 5 秒钟,各种倒腾。

7.2 配置文件

在 application.yml 中,添加 Redis 配置,如下:

server:
  port: 8079

spring:
  data:
    # Jest 配置项
    jest:
      uri: http://127.0.0.1:9400

7.3 DemoController

在 cn.iocoder.springboot.lab39.skywalkingdemo.controller 包路径下,创建 DemoController 类,提供示例 API 接口。代码如下:

@RestController
@RequestMapping("/demo")
public class DemoController {

    @Autowired
    private ESUserRepository userRepository;

    @GetMapping("/elasticsearch")
    public String mysql() {
        this.save(1);
        this.findById(1);
        return "elasticsearch";
    }

    public void save(Integer id) {
        ESUserDO user = new ESUserDO();
        user.setId(id);
        user.setUsername("username:" + id);
        user.setPassword("password:" + id);
        user.setCreateTime(new Date());
        userRepository.save(user);
    }

    public ESUserDO findById(Integer id) {
        return userRepository.findById(id).orElse(null);
    }

}
  • 在 /demo/elasticsearch 接口中,会执行一次 Elasticsearch 插入和查询操作。
  • ESUserDO 实体类,直接点击查看。
  • ESUserRepository ES 数据访问类,直接点击查看。

7.4 ElasticsearchJestApplication

创建 ElasticsearchJestApplication.java 类,配置 @SpringBootApplication 注解即可。代码如下:

@SpringBootApplication(exclude = {ElasticsearchAutoConfiguration.class, ElasticsearchDataAutoConfiguration.class})
public class ElasticsearchJestApplication {

    public static void main(String[] args) {
        SpringApplication.run(ElasticsearchJestApplication.class, args);
    }

}

7.5 简单测试

通过 IDEA 的「Run/Debug Configurations」配置使用 SkyWalking Agent。如下图所示:

然后,执行 ElasticsearchJestApplication#main(String[] args) 方法,启动该 Spring Boot 应用。

1、首先,使用浏览器,访问下 http://127.0.0.1:8079/demo/elasticsearch 地址,请求下 Spring Boot 应用提供的 API。因为,我们要追踪下该链路。

2、然后,继续使用浏览器,打开 http://127.0.0.1:8080/ 地址,进入 SkyWalking UI 界面。如下图所示:

3、之后,点击「拓扑图」菜单,进入查看拓扑图的界面,可以看到特殊的小方块,就是 Elasticsearch 服务。如下图所示:

4、再之后,点击「追踪」菜单,进入查看链路数据的界面。如下图所示:

点击红圈的使用 HttpClient 发起 HTTP 请求,操作 Elasticsearch 的链路数据。如下图所示:

不过没有看到 HTTP 请求的具体参数。如果想要的话,胖友需要自行去修改 httpClient-4.x-plugin 插件。不过要注意,因为 HTTP 请求的具体参数可能很长,所以最好做下最大长度的截取。

8. RocketMQ 示例

示例代码对应仓库:lab-39-rocketmq

本小节,我们来搭建一个 SkyWalking 对 RocketMQ 消息的发送和消费的链路追踪。该链路通过如下插件实现收集:

我们将使用 RocketMQ-Spring 进行 RocketMQ 的操作。对 RocketMQ 感兴趣的胖友,可以后续去看看《芋道 Spring Boot 消息队列 RocketMQ 入门》文章。

考虑到让示例更简单,我们的示例项目包含 RocketMQ 的生产者 Producer 和消费者 Consumer。

8.1 引入依赖

在 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">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>lab-39-rocketmq</artifactId>

    <dependencies>
        <!-- 实现对 SpringMVC 的自动化配置 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- 实现对 RocketMQ 的自动化配置 -->
        <dependency>
            <groupId>org.apache.rocketmq</groupId>
            <artifactId>rocketmq-spring-boot-starter</artifactId>
            <version>2.0.4</version>
        </dependency>
    </dependencies>

</project>

8.2 配置文件

在 application.yml 中,添加 RocketMQ 配置,如下:

server:
  port: 8079

# rocketmq 配置项,对应 RocketMQProperties 配置类
rocketmq:
  name-server: 127.0.0.1:9876 # RocketMQ Namesrv
  # Producer 配置项
  producer:
    group: demo-producer-group # 生产者分组
    send-message-timeout: 3000 # 发送消息超时时间,单位:毫秒。默认为 3000 。

8.3 DemoController

在 cn.iocoder.springboot.lab39.skywalkingdemo.controller 包路径下,创建 DemoController 类,提供示例 API 接口。代码如下:

@RestController
@RequestMapping("/demo")
public class DemoController {

    @Autowired
    private DemoProducer producer;

    @GetMapping("/rocketmq")
    public String echo() {
        this.sendMessage(1);
        return "rocketmq";
    }

    public void sendMessage(Integer id) {
        producer.syncSend(id);
    }

}
  • 在 /demo/rocketmq 接口中,会执行一次 RocketMQ 发送消息的操作。
  • DemoMessage 消息类,直接点击查看。
  • DemoProducer 生产者类,直接点击查看。
  • DemoConsumer 消费者类,直接点击查看。

8.4 RocketMQApplication

创建 RocketMQApplication.java 类,配置 @SpringBootApplication 注解即可。代码如下:

@SpringBootApplication
public class RocketMQApplication {

    public static void main(String[] args) {
        SpringApplication.run(RocketMQApplication.class, args);
    }

}

8.5 IDEA 配置

通过 IDEA 的「Run/Debug Configurations」配置使用 SkyWalking Agent。如下图所示:

然后,执行 RocketMQApplication#main(String[] args) 方法,启动该 Spring Boot 应用。

8.6 简单测试

1、首先,使用浏览器,访问下 http://127.0.0.1:8079/demo/rocketmq 地址,请求下 Spring Boot 应用提供的 API。因为,我们要追踪下该链路。

2、然后,继续使用浏览器,打开 http://127.0.0.1:8080/ 地址,进入 SkyWalking UI 界面。如下图所示:

3、之后,点击「拓扑图」菜单,进入查看拓扑图的界面,可以看到 RocketMQ 小方块。如下图所示:

4、再之后,点击「追踪」菜单,进入查看链路数据的界面。如下图所示:

注意,可以看到 RocketMQ 消息的发送,到该消息的异步的消费,都被串联在一个整体链路中。这样对我们日常排查问题,会非常便捷舒服。

点击 RocketMQ Producer 发送消息的链路数据,可以看到 Producer 发送消息的 Topic。如下图所示:

点击 RocketMQ Consumer 消费消息的链路数据,可以看到 Consumer 消费消息的 Topic。如下图所示:

8.7 阿里云的消息队列 ONS 服务

可能部分胖友采用的是阿里云的消息队列 ONS 服务,使用的是 ons-client 库进行 RocketMQ 消息的发送和消费。那么此时,我们就无法使用 SkyWalking 进行 RocketMQ 的链路追踪了。怎么解决呢?

① 方案一,参考 SkyWalking rocketMQ-4.x-plugin 插件的源码,修改成支持 ons-client 库的链路追踪。ons-client 库的代码,和 rocketmq-client 的代码是非常接近的,胖友只要稍微改改就能支持。

② 方案二,阿里云的消息队列 ONS 服务,已经支持 rocketmq-client 进行 RocketMQ 消息的发送和消费。这样,我们就可以继续使用 SkyWalking rocketMQ-4.x-plugin 插件来进行链路追踪。

不过要注意,阿里云消息 ONS 服务大于开源的 RocketMQ 中间件,所以用到 ONS 服务的独有的特性的功能,还是需要使用 ons-client 库。

目前艿艿线上所采用的是方案一,新建了一个 ons-1.x-plugin 插件,实现了对 ONS 服务的链路追踪。

9. Kafka 示例

示例代码对应仓库:lab-39-kafka

本小节,我们来搭建一个 SkyWalking 对 Kafka 消息的发送和消费的链路追踪。该链路通过如下插件实现收集:

我们将使用 Spring-Kafka 进行 Kafka 的操作。对 Kafka 感兴趣的胖友,可以后续去看看《芋道 Spring Boot 消息队列 Kafka 入门》文章。

考虑到让示例更简单,我们的示例项目包含 Kafka 的生产者 Producer 和消费者 Consumer。

9.1 引入依赖

在 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">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.11.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>lab-39-kafka</artifactId>

    <dependencies>
        <!-- 引入 Spring-Kafka 依赖 -->
        <!-- 已经内置 kafka-clients 依赖,所以无需重复引入 -->
        <dependency>
            <groupId>org.springframework.kafka</groupId>
            <artifactId>spring-kafka</artifactId>
            <version>2.2.11.RELEASE</version>
        </dependency>

        <!-- 实现对 SpringMVC 的自动化配置 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

</project>
  • 具体每个依赖的作用,胖友自己认真看下艿艿添加的所有注释噢。
    友情提示: SkyWalking kafka-plugin 对高版本的 kafka-clients 的链路追踪兼容性还存在一点问题,无法追踪到 Kafka Producer 发送消息。

所以,这里我们将 spring-kafka 的版本从 2.3.3.RELEASE 修改成 2.2.11.RELEASE,以使用 kafka-clients 的低版版本 2.0.1

9.2 配置文件

在 application.yml 中,添加 Kafka 配置,如下:

server:
  port: 8079

spring:
  # Kafka 配置项,对应 KafkaProperties 配置类
  kafka:
    bootstrap-servers: 127.0.0.1:9092 # 指定 Kafka Broker 地址,可以设置多个,以逗号分隔
    # Kafka Producer 配置项
    producer:
      acks: 1 # 0-不应答。1-leader 应答。all-所有 leader 和 follower 应答。
      retries: 3 # 发送失败时,重试发送的次数
      key-serializer: org.apache.kafka.common.serialization.StringSerializer # 消息的 key 的序列化
      value-serializer: org.springframework.kafka.support.serializer.JsonSerializer # 消息的 value 的序列化
    # Kafka Consumer 配置项
    consumer:
      auto-offset-reset: earliest # 设置消费者分组最初的消费进度为 earliest 。可参考博客 https://blog.csdn.net/lishuangzhe7047/article/details/74530417 理解
      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer
      properties:
        spring:
          json:
            trusted:
              packages: cn.iocoder.springboot.lab39.skywalkingdemo.message # 消息 POJO 可信目录,解决 JSON 无法反序列化的问题
    # Kafka Consumer Listener 监听器配置
    listener:
      missing-topics-fatal: false # 消费监听接口监听的主题不存在时,默认会报错。所以通过设置为 false ,解决报错

9.3 DemoController

在 cn.iocoder.springboot.lab39.skywalkingdemo.controller 包路径下,创建 DemoController 类,提供示例 API 接口。代码如下:

@RestController
@RequestMapping("/demo")
public class DemoController {

    @Autowired
    private DemoProducer producer;

    @GetMapping("/kafka")
    public String echo() throws ExecutionException, InterruptedException {
        this.sendMessage(1);
        return "kafka";
    }

    public void sendMessage(Integer id) throws ExecutionException, InterruptedException {
        producer.syncSend(id);
    }

}
  • 在 /demo/kafka 接口中,会执行一次 Kafka 发送消息的操作。
  • DemoMessage 消息类,直接点击查看。
  • DemoProducer 生产者类,直接点击查看。
  • DemoConsumer 消费者类,直接点击查看。

9.4 KafkaApplication

创建 KafkaApplication.java 类,配置 @SpringBootApplication 注解即可。代码如下:

@SpringBootApplication
public class KafkaApplication {

    public static void main(String[] args) {
        SpringApplication.run(KafkaApplication.class, args);
    }

}

9.5 IDEA 配置

通过 IDEA 的「Run/Debug Configurations」配置使用 SkyWalking Agent。如下图所示:

然后,执行 KafkaApplication#main(String[] args) 方法,启动该 Spring Boot 应用。

9.6 简单测试

1、首先,使用浏览器,访问下 http://127.0.0.1:8079/demo/kafka 地址,请求下 Spring Boot 应用提供的 API。因为,我们要追踪下该链路。

2、然后,继续使用浏览器,打开 http://127.0.0.1:8080/ 地址,进入 SkyWalking UI 界面。如下图所示:

3、之后,点击「拓扑图」菜单,进入查看拓扑图的界面,可以看到 Kafka 小方块。如下图所示:

4、再之后,点击「追踪」菜单,进入查看链路数据的界面。如下图所示:

注意,可以看到 Kafka 消息的发送,到该消息的异步的消费,都被串联在一个整体链路中。这样对我们日常排查问题,会非常便捷舒服。

点击 Kafka Producer 发送消息的链路数据,可以看到 Kafka 发送消息的 Topic。如下图所示:

点击 Kafka Consumer 消费消息的链路数据,可以看到 Consumer 消费消息的 Topic。如下图所示:

10. RabbitMQ 示例

示例代码对应仓库:lab-39-rabbitmq-demo

本小节,我们来搭建一个 SkyWalking 对 Rabbitmq 消息的发送和消费的链路追踪。该链路通过如下插件实现收集:

我们将使用 Spring-AMQP 进行 RabbitMQ 的操作。对 RabbitMQ 感兴趣的胖友,可以后续去看看《芋道 Spring Boot 消息队列 RabbitMQ 入门》文章。

考虑到让示例更简单,我们的示例项目包含 RabbitMQ 的生产者 Producer 和消费者 Consumer。

10.1 引入依赖

在 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">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>lab-39-rabbitmq-demo</artifactId>

    <dependencies>
        <!-- 实现对 RabbitMQ 的自动化配置 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>

        <!-- 实现对 SpringMVC 的自动化配置 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

</project>

10.2 配置文件

在 application.yml 中,添加 RabbitMQ 配置,如下:

server:
  port: 8079

spring:
  # RabbitMQ 配置项,对应 RabbitProperties 配置类
  rabbitmq:
    host: 127.0.0.1 # RabbitMQ 服务的地址
    port: 5672 # RabbitMQ 服务的端口
    username: guest # RabbitMQ 服务的账号
    password: guest # RabbitMQ 服务的密码

10.3 DemoController

在 cn.iocoder.springboot.lab39.skywalkingdemo.controller 包路径下,创建 DemoController 类,提供示例 API 接口。代码如下:

@RestController
@RequestMapping("/demo")
public class DemoController {

    @Autowired
    private DemoProducer producer;

    @GetMapping("/rabbitmq")
    public String echo() {
        this.sendMessage(1);
        return "rabbitmq";
    }

    public void sendMessage(Integer id) {
        producer.syncSend(id);
    }

}
  • 在 /demo/rabbitmq 接口中,会执行一次 RabbitMQ 发送消息的操作。
  • RabbitConfig 配置类,直接点击查看。
  • DemoMessage 消息类,直接点击查看。
  • DemoProducer 生产者类,直接点击查看。
  • DemoConsumer 消费者类,直接点击查看。

10.4 RabbitMQApplication

创建 RabbitMQApplication.java 类,配置 @SpringBootApplication 注解即可。代码如下:

@SpringBootApplication
public class RabbitMQApplication {

    public static void main(String[] args) {
        SpringApplication.run(RabbitMQApplication.class, args);
    }

}

10.5 IDEA 配置

通过 IDEA 的「Run/Debug Configurations」配置使用 SkyWalking Agent。如下图所示:

然后,执行 KafkaApplication#main(String[] args) 方法,启动该 Spring Boot 应用。

10.6 简单测试

1、首先,使用浏览器,访问下 http://127.0.0.1:8079/demo/rabbitmq 地址,请求下 Spring Boot 应用提供的 API。因为,我们要追踪下该链路。

2、然后,继续使用浏览器,打开 http://127.0.0.1:8080/ 地址,进入 SkyWalking UI 界面。如下图所示:

3、之后,点击「拓扑图」菜单,进入查看拓扑图的界面,可以看到 RabbitMQ 小方块。如下图所示:

4、再之后,点击「追踪」菜单,进入查看链路数据的界面。如下图所示:

注意,可以看到 RabbitMQ 消息的发送,到该消息的异步的消费,都被串联在一个整体链路中。这样对我们日常排查问题,会非常便捷舒服。

点击 RabbitMQ Producer 发送消息的链路数据,可以看到 RabbitMQ 发送消息的 RoutingKey、Exchange。如下图所示:

点击 RabbitMQ Consumer 消费消息的链路数据,可以看到 Consumer 消费消息的 RoutingKey、Exchange、Queue。如下图所示:

11. ActiveMQ 示例

示例代码对应仓库:lab-39-activemq

本小节,我们来搭建一个 SkyWalking 对 ActiveMQ 消息的发送和消费的链路追踪。该链路通过如下插件实现收集:

我们将使用 Spring-JMS 进行 ActiveMQ 的操作。对 ActiveMQ 感兴趣的胖友,可以后续去看看《Spring Boot 消息队列 ActiveMQ 入门》文章。

考虑到让示例更简单,我们的示例项目包含 ActiveMQ 的生产者 Producer 和消费者 Consumer。

11.1 引入依赖

在 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">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>lab-39-activemq</artifactId>

    <dependencies>
        <!-- 实现对 ActiveMQ 的自动化配置 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-activemq</artifactId>
        </dependency>

        <!-- 实现对 SpringMVC 的自动化配置 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

</project>

11.2 配置文件

在 application.yml 中,添加 ActiveMQ 配置,如下:

server:
  port: 8079

spring:
  # ActiveMQ 配置项,对应 ActiveMQProperties 配置类
  activemq:
    broker-url: tcp://127.0.0.1:61616 # Activemq Broker 的地址
    user: admin # 账号
    password: admin # 密码
    packages:
      trust-all: true # 可信任的反序列化包

11.3 DemoController

在 cn.iocoder.springboot.lab39.skywalkingdemo.controller 包路径下,创建 DemoController 类,提供示例 API 接口。代码如下:

@RestController
@RequestMapping("/demo")
public class DemoController {

    @Autowired
    private DemoProducer producer;

    @GetMapping("/activemq")
    public String echo() {
        this.sendMessage(1);
        return "activemq";
    }

    public void sendMessage(Integer id) {
        producer.syncSend(id);
    }

}
  • 在 /demo/activemq 接口中,会执行一次 ActiveMQ 发送消息的操作。
  • DemoMessage 消息类,直接点击查看。
  • DemoProducer 生产者类,直接点击查看。
  • DemoConsumer 消费者类,直接点击查看。

11.4 ActiveMQApplication

创建 ActiveMQApplication.java 类,配置 @SpringBootApplication 注解即可。代码如下:

@SpringBootApplication
public class ActiveMQApplication {

    public static void main(String[] args) {
        SpringApplication.run(ActiveMQApplication.class, args);
    }

}

11.5 IDEA 配置

通过 IDEA 的「Run/Debug Configurations」配置使用 SkyWalking Agent。如下图所示:

然后,执行 ActiveMQApplication#main(String[] args) 方法,启动该 Spring Boot 应用。

11.6 简单测试

1、首先,使用浏览器,访问下 http://127.0.0.1:8079/demo/activemq 地址,请求下 Spring Boot 应用提供的 API。因为,我们要追踪下该链路。

2、然后,继续使用浏览器,打开 http://127.0.0.1:8080/ 地址,进入 SkyWalking UI 界面。如下图所示:

3、之后,点击「拓扑图」菜单,进入查看拓扑图的界面,可以看到 ActiveMQ 小方块。如下图所示:

4、再之后,点击「追踪」菜单,进入查看链路数据的界面。如下图所示:

注意,可以看到 ActiveMQ 消息的发送,到该消息的异步的消费,都被串联在一个整体链路中。这样对我们日常排查问题,会非常便捷舒服。

点击 ActiveMQ Producer 发送消息的链路数据,可以看到 ActiveMQ 发送消息的 Queue。如下图所示:

点击 ActiveMQ Consumer 消费消息的链路数据,可以看到 Consumer 消费消息的 Queue。如下图所示:

12. 日志框架示例

示例代码对应仓库:lab-39-logback

在使用 SkyWalking 排查问题的时候,我们可能希望能够跟链路的日志进行关联,那么我们可以将链路编号( SkyWalking TraceId )记录到日志中,从而进行关联。

友情提示:艿艿自己的项目里,在一些业务数据希望跟 SkyWalking 链路进行关联时,会考虑新增一个 traceId 字段,存储 SkyWalking TraceId。例如说:

  • 发送聊天消息时,消息记录上会存储链路编号。
  • 创建交易订单时,订单记录上会存储链路编号。

这样,在排查该数据记录时,我们就可以拿着 traceId 字段,去查响应的链路信息和日志信息。

SkyWalking 提供了多种日志框架的支持,通过不同的插件:

本小节,我们来搭建一个 SLF4J + Logback 日志的 SkyWalking TraceId 的集成示例。对 Logging 感兴趣的胖友,可以后续去看看《芋道 Spring Boot 日志框架 Logging 入门》文章。

12.1 引入依赖

在 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">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <packaging>jar</packaging>

    <artifactId>lab-39-logback</artifactId>

    <dependencies>
        <!-- SkyWalking 对 Logback 的集成 -->
        <dependency>
            <groupId>org.apache.skywalking</groupId>
            <artifactId>apm-toolkit-logback-1.x</artifactId>
            <version>6.6.0</version>
        </dependency>

        <!-- 实现对 SpringMVC 的自动化配置 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

</project>

12.2 应用配置文件

在 application.yml 中,添加配置,如下:

server:
  port: 8079

spring:
  application:
    name: demo-application-logback

12.3 Logback 配置文件

在 logback-spring.xml 中,添加 Logback 配置,如下:

<?xml version="1.0" encoding="UTF-8"?>

<configuration>

    <!-- 引入 Spring Boot 默认的 logback XML 配置文件  -->
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>

    <!-- 控制台 Appender -->
    <property name="CONSOLE_LOG_PATTERN" value="%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %tid %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
    <appender name="console" 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>${CONSOLE_LOG_PATTERN}</Pattern>
            </layout>
        </encoder>
    </appender>

    <!-- 从 Spring Boot 配置文件中,读取 spring.application.name 应用名 -->
    <springProperty name="applicationName" scope="context" source="spring.application.name" />
    <property name="FILE_LOG_PATTERN" value="%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } %tid --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
    <!-- 日志文件的路径 -->
    <property name="LOG_FILE" value="/Users/yunai/logs/${applicationName}.log"/>​
    <!-- 日志文件 Appender -->
    <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_FILE}</file>
        <!--滚动策略,基于时间 + 大小的分包策略 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz</fileNamePattern>
            <maxHistory>7</maxHistory>
            <maxFileSize>10MB</maxFileSize>
        </rollingPolicy>
        <!-- 日志的格式化 -->
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
                <Pattern>${FILE_LOG_PATTERN}</Pattern>
            </layout>
        </encoder>
    </appender>

    <!-- 设置 Appender -->
    <root level="INFO">
        <appender-ref ref="console"/>
        <appender-ref ref="file"/>
    </root>

</configuration>

日志配置有点长哈,主要配置 2 处地方,我们来看看图。如下图锁标记:

12.4 DemoController

在 cn.iocoder.springboot.lab39.skywalkingdemo.controller 包路径下,创建 DemoController 类,提供示例 API 接口。代码如下:

@RestController
@RequestMapping("/demo")
public class DemoController {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @GetMapping("/logback")
    public String echo() {
        logger.info("测试日志");
        return "logback";
    }

}
  • 在 /demo/logback 接口中,会执行一次日志的记录。

12.5 LogbackApplication

创建 LogbackApplication.java 类,配置 @SpringBootApplication 注解即可。代码如下:

@SpringBootApplication
public class LogbackApplication {

    public static void main(String[] args) {
        SpringApplication.run(LogbackApplication.class, args);
    }

}

12.6 IDEA 配置

通过 IDEA 的「Run/Debug Configurations」配置使用 SkyWalking Agent。如下图所示:

然后,执行 LogbackApplication#main(String[] args) 方法,启动该 Spring Boot 应用。启动日志如下:

// ... 省略其它日志

2020-01-05 21:19:11.420  INFO 18611 TID:N/A --- [           main] c.i.s.l.s.LogbackApplication             : Started LogbackApplication in 2.606 seconds (JVM running for 5.456)
  • 因为此时没有 SkyWalking TraceId,所以 %tid 占位符被替换成了 TID:N/A

12.7 简单测试

1、首先,使用浏览器,访问下 http://127.0.0.1:8079/demo/logback 地址,请求下 Spring Boot 应用提供的 API。因为,我们要追踪下该链路。看到日志如下:

2020-01-05 21:21:51.521  INFO 18611 TID:22.37.15782305114330001 --- [nio-8079-exec-1] c.i.s.l.s.controller.DemoController      : 测试日志
  • %tid 占位符被替换成了 SkyWalking TraceId 22.37.15782305114330001

2、然后,可以使用该 SkyWalking TraceId 在 SkyWalking UI 中,进行检索。如下图所示:

具体实现原理,感兴趣的胖友,可以看看《SkyWalking 源码分析 —— traceId 集成到日志组件》文章。

13. 自定义追踪方法

示例代码对应仓库:lab-39-trace-annotations

在上述的示例中,我们都是通过 SkyWalking 提供的插件,实现对指定框架的链路追踪。那么,如果我们希望对项目中的业务方法,实现链路追踪,方便我们排查问题,需要怎么做呢?SkyWalking 提供了两种方式:

艿艿在项目中,使用 SkyWalking @Trace 注解较多,所以本小节我们就来看看它的使用示例。

13.1 引入依赖

在 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">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <packaging>jar</packaging>

    <artifactId>lab-39-trace-annotations</artifactId>

    <dependencies>
        <!-- SkyWalking 工具类 -->
        <dependency>
            <groupId>org.apache.skywalking</groupId>
            <artifactId>apm-toolkit-trace</artifactId>
            <version>6.6.0</version>
        </dependency>

        <!-- 实现对 SpringMVC 的自动化配置 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

</project>

13.2 配置文件

在 application.yml 中,添加配置,如下:

server:
  port: 8079

13.3 DemoController

在 cn.iocoder.springboot.lab39.skywalkingdemo.controller 包路径下,创建 DemoController 类,提供示例 API 接口。代码如下:

@RestController
@RequestMapping("/demo")
public class DemoController {

    @GetMapping("/trace_annotations")
    @Trace(operationName = "trace_annotations")
    public String echo() {
        // <X> 自定义 SkyWalking Span
        ActiveSpan.tag("mp", "芋道源码");

        // 返回
        return "trace_annotations";
    }

}
  • 在 #echo() 方法上,添加了 SkyWalking @Trace 注解,实现 SkyWalking 指定方法的追踪,会创建一个 SkyWalking LocalSpan。同时,可以通过 operationName 属性,设置操作名。
  • 在 <X> 处,通过 ActiveSpan#tag(String key, String value) 方法,设置该 LocalSpan 的标签。ActiveSpan 还有其它方法,如下:
  • ActiveSpan.error() 方法:将当前 Span 标记为出错状态.
  • ActiveSpan.error(String errorMsg) 方法:将当前 Span 标记为出错状态, 并带上错误信息.
  • ActiveSpan.error(Throwable throwable) 方法:将当前 Span 标记为出错状态, 并带上 Throwable。
  • ActiveSpan.debug(String debugMsg) 方法:在当前 Span 添加一个 debug 级别的日志信息.
  • ActiveSpan.info(String infoMsg) 方法:在当前 Span 添加一个 info 级别的日志信息.

另外,我们可以使用 TraceContext#traceId() 方法,获得当前的 SkyWalking TraceId 链路追踪编号。

13.4 TraceAnnotationsApplication

创建 TraceAnnotationsApplication.java 类,配置 @SpringBootApplication 注解即可。代码如下:

@SpringBootApplication
public class TraceAnnotationsApplication {

    public static void main(String[] args) {
        SpringApplication.run(TraceAnnotationsApplication.class, args);
    }

}

13.5 IDEA 配置

通过 IDEA 的「Run/Debug Configurations」配置使用 SkyWalking Agent。如下图所示:

然后,执行 TraceAnnotationsApplication#main(String[] args) 方法,启动该 Spring Boot 应用。

13.6 简单测试

1、首先,使用浏览器,访问下 http://127.0.0.1:8079/demo/trace_annotations 地址,请求下 Spring Boot 应用提供的 API。因为,我们要追踪下该链路。

2、然后,查看 SkyWalking UI 链路界面,可以看到我们自定义追踪的方法。示例如下图:

点击红圈的 @Trace 注解的链路数据,可以看到具体信息。如下图所示:

具体实现原理,感兴趣的胖友,可以看看《SkyWalking 源码分析 —— @Trace 注解想要追踪的任何方法》文章。

14. OpenTracing 示例

示例代码对应仓库:lab-39-opentracing

在开始本节之前,推荐胖友先阅读下《OpenTracing 官方标准 —— 中文版》规范,对 OpenTracing 有个简单的了解。

在 opentracing-java 项目中,定义了 OpenTracing Java API。而 SkyWalking apm-toolkit-opentracing 项目,提供了对该 OpenTracing Java API 的实现。因此,我们可以使用它,实现比「13. 自定义追踪方法」小节,更加灵活的自定义追踪,同时可以做到和 SkyWalking 特性无关,毕竟咱使用的是 OpenTracing Java API。

下面,我们来搭建一个 OpenTracing Java API 的使用示例。

14.1 引入依赖

在 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">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>lab-39-opentracing</artifactId>

    <dependencies>
        <!-- SkyWalking Opentracing 集成 -->
        <dependency>
            <groupId>org.apache.skywalking</groupId>
            <artifactId>apm-toolkit-opentracing</artifactId>
            <version>6.6.0</version>
        </dependency>

        <!-- 实现对 SpringMVC 的自动化配置 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

</project>

14.2 配置文件

在 application.yml 中,添加配置,如下:

server:
  port: 8079

14.3 DemoController

在 cn.iocoder.springboot.lab39.skywalkingdemo.controller 包路径下,创建 DemoController 类,提供示例 API 接口。代码如下:

@RestController
@RequestMapping("/demo")
public class DemoController {

    @GetMapping("/opentracing")
    public String echo() {
        // <X>创建一个 Span
        Tracer tracer = new SkywalkingTracer();
        tracer.buildSpan("custom_operation").withTag("mp", "芋道源码").startManual().finish();

        // 返回
        return "opentracing";
    }

}
  • 在 /demo/opentracing 接口中的<X> 处,我们使用 Opentracing Java API 创建了一个 Span。
  • 更多的 Opentracing Java API 的使用,可以看看 opentracing-java 项目提供的示例哈。

14.4 OpentracingApplication

创建 OpentracingApplication.java 类,配置 @SpringBootApplication 注解即可。代码如下

@SpringBootApplication
public class OpentracingApplication {

    public static void main(String[] args) {
        SpringApplication.run(OpentracingApplication.class, args);
    }

}

14.5 IDEA 配置

通过 IDEA 的「Run/Debug Configurations」配置使用 SkyWalking Agent。如下图所示:

然后,执行 OpentracingApplication#main(String[] args) 方法,启动该 Spring Boot 应用。

14.6 简单测试

1、首先,使用浏览器,访问下 http://127.0.0.1:8079/demo/opentracing 地址,请求下 Spring Boot 应用提供的 API。因为,我们要追踪下该链路。

2、然后,查看 SkyWalking UI 链路界面,可以看到使用 Opentracing 创建的链路。示例如下图:

点击红圈的 Opentracing 创建的链路数据,可以看到具体信息。如下图所示:

15. Spring 异步任务示例

示例代码对应仓库:lab-39-async

本小节,我们来搭建一个 SkyWalking 对 Spring 异步任务的链路追踪。该链路通过如下插件实现收集:

下面,我们来搭建一个 Spring 异步任务的使用示例。。对 Spring 异步任务感兴趣的胖友,可以后续去看看《芋道 Spring Boot 异步任务入门》文章。

15.1 引入依赖

在 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">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <packaging>jar</packaging>

    <artifactId>lab-39-async</artifactId>

    <dependencies>
        <!-- 实现对 SpringMVC 的自动化配置 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

</project>

15.2 配置文件

在 application.yml 中,添加配置,如下:

server:
  port: 8079

15.3 DemoController

在 cn.iocoder.springboot.lab39.skywalkingdemo.controller 包路径下,创建 DemoController 类,提供示例 API 接口。代码如下:

// DemoController.java
@RestController
@RequestMapping("/demo")
public class DemoController {

    @Autowired
    private DemoService demoService;

    @GetMapping("/async")
    public String echo() {
        demoService.async();
        return "async";
    }

}

// DemoService.java
@Service
public class DemoService {

    @Async
    public void async() {
        System.out.println("异步任务的执行");
    }

}
  • 在 DemoService#async() 方法上,我们添加了 Spring @Async 注解,实现 Spring 异步任务。

15.4 AsyncApplication

创建 AsyncApplication.java 类,配置 @SpringBootApplication 注解即可。代码如下:

@SpringBootApplication
@EnableAsync(proxyTargetClass = true) // 开启 @Async 的支持
public class AsyncApplication {

    public static void main(String[] args) {
        SpringApplication.run(AsyncApplication.class, args);
    }

}
  • 通过 @EnableAsync 注解,开启 Spring @Async 异步任务的支持。这里,我们设置了 proxyTargetClass = true,使用 CGLIB 实现动态代理,忘记当时踩过什么坑,好像是和 SkyWalking 发生了啥冲突,不太记得了。

15.5 IDEA 配置

通过 IDEA 的「Run/Debug Configurations」配置使用 SkyWalking Agent。如下图所示:

然后,执行 OpentracingApplication#main(String[] args) 方法,启动该 Spring Boot 应用。

15.6 简单测试

1、首先,使用浏览器,访问下 http://127.0.0.1:8079/demo/async 地址,请求下 Spring Boot 应用提供的 API。因为,我们要追踪下该链路。

2、然后,查看 SkyWalking UI 链路界面,可以看 Spring 异步任务的链路。示例如下图:

另外,如果胖友不想使用 Spring 提供的异步任务的功能,想自己使用线程池实现异步,同时又想实现对该异步任务的链路追踪,可以参考《SkyWalking —— Application-toolkit-trace-cross-thread.md》文档。

16. Dubbo 示例

示例代码对应仓库:

本小节,我们来搭建一个 SkyWalking 对 Dubbo 的远程 RPC 调用的链路追踪。该链路通过如下插件实现收集:

我们来新建一个 lab-39-skywalking-dubbo 模块,一共包含三个子项目。最终如下图所示:

另外,考虑到目前 Dubbo 主要使用 Zookeeper 作为注册中心,所以本小节也是使用 Zookeeper。不了解的胖友,后续可以看看《Zookeeper 极简入门》文章。

16.1 搭建 API 项目

创建 lab-39-skywalking-dubbo-api 项目,服务接口,定义 Dubbo Service API 接口,提供给消费者使用。

16.1.1 UserService

创建 UserService 接口,定义用户服务 RPC Service 接口。代码如下:

public interface UserService {

    /**
     * 根据指定用户编号,获得用户信息
     *
     * @param id 用户编号
     * @return 用户信息
     */
    String get(Integer id);

}

16.2 搭建服务提供者

创建 skywalking-dubbo-provider 项目,服务提供者,实现 lab-39-skywalking-dubbo-api 项目定义的 Dubbo Service API 接口,提供相应的服务。

16.2.1 引入依赖

创建 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">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>lab-39-skywalking-dubbo-provider</artifactId>

    <dependencies>
        <!-- 引入定义的 Dubbo API 接口 -->
        <dependency>
            <groupId>cn.iocoder.springboot.labs</groupId>
            <artifactId>lab-39-skywalking-dubbo-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <!-- 引入 Spring Boot 依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <!-- 实现对 Dubbo 的自动化配置 -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo</artifactId>
            <version>2.7.4.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>2.7.4.1</version>
        </dependency>

        <!-- 使用 Zookeeper 作为注册中心 -->
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>2.13.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>2.13.0</version>
        </dependency>
    </dependencies>

</project>

16.2.2 配置文件

在 application.yml 中,添加 Dubbo 配置,如下:

spring:
  application:
    name: user-service-provider

# dubbo 配置项,对应 DubboConfigurationProperties 配置类
dubbo:
  # Dubbo 应用配置
  application:
    name: ${spring.application.name} # 应用名
  # Dubbo 注册中心配
  registry:
    address: zookeeper://127.0.0.1:2181 # 注册中心地址。个鞥多注册中心,可见 http://dubbo.apache.org/zh-cn/docs/user/references/registry/introduction.html 文档。
  # Dubbo 服务提供者协议配置
  protocol:
    port: -1 # 协议端口。使用 -1 表示随机端口。
    name: dubbo # 使用 `dubbo://` 协议。更多协议,可见 http://dubbo.apache.org/zh-cn/docs/user/references/protocol/introduction.html 文档
  # 配置扫描 Dubbo 自定义的 @Service 注解,暴露成 Dubbo 服务提供者
  scan:
    base-packages: cn.iocoder.springboot.lab39.skywalkingdemo.providerdemo.service

关于 dubbo 配置项,胖友可以后续阅读《芋道 Spring Boot Dubbo 入门》文章。

16.2.3 UserServiceImpl

创建 UserServiceImpl 类,实现 UserService 接口,用户服务具体实现类。代码如下:

@org.apache.dubbo.config.annotation.Service(version = "1.0.0")
public class UserServiceImpl implements UserService {

    @Override
    public String get(Integer id) {
        return "user:" + id;
    }

}

16.2.4 ProviderApplication

创建 ProviderApplication 类,服务提供者的启动类。代码如下:

@SpringBootApplication
public class ProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication.class);
    }

}

16.2.5 IDEA 配置项

通过 IDEA 的「Run/Debug Configurations」配置使用 SkyWalking Agent。如下图所示:

16.3 搭建服务消费者

创建 skywalking-dubbo-consumer 项目,服务消费者,会调用 lab-39-skywalking-dubbo-provider 项目提供的 User Service 服务。

16.3.1 引入依赖

创建 pom.xml 文件中,引入依赖。和「16.2.1 引入依赖」基本是一致的,胖友可以点击 pom.xml 文件查看。

16.3.2 配置文件

在 application.yml 中,添加 Dubbo 配置,如下:

server:
  port: 8079

spring:
  application:
    name: user-service-consumer

# dubbo 配置项,对应 DubboConfigurationProperties 配置类
dubbo:
  # Dubbo 应用配置
  application:
    name: ${spring.application.name} # 应用名
  # Dubbo 注册中心配置
  registry:
    address: zookeeper://127.0.0.1:2181 # 注册中心地址。个鞥多注册中心,可见 http://dubbo.apache.org/zh-cn/docs/user/references/registry/introduction.html 文档。

关于 dubbo 配置项,胖友可以后续阅读《芋道 Spring Boot Dubbo 入门》文章。

16.3.3 UserController

创建 UserController 类,提供调用 UserService 服务的 HTTP 接口。代码如下:

@RestController
@RequestMapping("/user")
public class UserController {

    @Reference(protocol = "dubbo", version = "1.0.0")
    private UserService userService;

    @GetMapping("/get")
    public String  get(@RequestParam("id") Integer id) {
        return userService.get(id);
    }

}

16.3.4 ConsumerApplication

创建 ConsumerApplication 类,服务消费者的启动类。代码如下:

@SpringBootApplication
public class ConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class);
    }

}

16.3.5 IDEA 配置项

通过 IDEA 的「Run/Debug Configurations」配置使用 SkyWalking Agent。如下图所示:

16.4 简单测试

使用 ProviderApplication 启动服务提供者,使用 ConsumerApplication 启动服务消费者。

① 首先,使用浏览器,访问 http://127.0.0.1:8079/user/get?id=1 地址,使用 Dubbo 调用 user-service-provider 服务。因为,我们要追踪下该链路。

② 然后,继续使用浏览器,打开 http://127.0.0.1:8080/ 地址,进入 SkyWalking UI 界面。如下图所示:

③ 之后,点击「拓扑图」菜单,进入查看拓扑图的界面,可以看到两个服务的小方块,以及对应的调用关系。如下图所示:

④ 再之后,点击「追踪」菜单,进入查看链路数据的界面。如下图所示:

17. 抽样收集示例

示例代码对应仓库:lab-39-springmvc 。

在访问量较少时,链路全量收集不会对系统带来多少负担,同时能够完整的观测到系统的运行状况。但是在访问量较大时,全量的链路收集,对链路收集的客户端(应用)、服务端(例如说 SkyWalking OAP Collector)、存储器(例如说 Elastcsearch)都会带来较大的性能开销,甚至会影响应用的正常运行。

因此,在访问量级较大的情况下,我们往往会选择抽样采样,只选择收集部分链路信息。SkyWalking Agent 在 agent/config/agent.config 配置文件中,定义了 agent.sample_n_per_3_secs 配置项,设置每 3 秒可收集的链路数据的数量
Negative or zero means off, by default.SAMPLE_N_PER_3_SECS means sampling N TraceSegment in 3 seconds tops.

  • 默认配置下,不进行限制,即获取全部链路数据。
    友情提示:哈哈哈~如果访问量不是特别大,建议还是全量收集!

本小节,我们无需单独搭建项目,而是直接使用 lab-39-springmvc 项目即可。

17.1 SkyWalking Agent 配置文件

修改 SkyWalking Agent 的 agent/config/agent.config 配置文件,开放 agent.sample_n_per_3_secs 配置项,支持使用 SW_AGENT_SAMPLE 环境变量。命令行操作如下:

# 查看当前所在目录
$ pwd
/Users/yunai/skywalking/apache-skywalking-apm-bin-es7/agent

# 创建 apm-trace-ignore-plugin.config 配置文件,并进行设置
$ vi config/apm-trace-ignore-plugin.config

配置文件内容如下: 

# The number of sampled traces per 3 seconds
# Negative number means sample traces as many as possible, most likely 100%
# agent.sample_n_per_3_secs=${SW_AGENT_SAMPLE:-1}

这样,每个项目可以通过 SW_AGENT_SAMPLE 环境变量,可以实现自定义抽样收集数量。

17.2 IDEA 配置

通过 IDEA 的「Run/Debug Configurations」配置使用 SkyWalking Agent。如下图所示:

通过设置 SW_AGENT_SAMPLE 环境变量为 1,实现每 3 秒只收集一个链路数据,方便演示测试。

17.3 简单测试

① 首先,使用浏览器,疯狂访问下 http://127.0.0.1:8079/demo/echo 地址,请求下 Spring Boot 应用提供的 API。

② 之后,在 SkyWalking UI 的查看链路追踪的界面,看到只有部分链路被收集。😈 这里暂时就不贴图了,嘿嘿~

有一点要注意,SkyWalking Agent 提供的插件,是基于我们使用的框架的方法,通过 AOP 的方式进行追踪,所以可能存在不兼容的情况,毕竟框架的代码在不断迭代,方法可能存在一定的变更。因此,一定要注意查看《SkyWalking —— Supported-list.md》文档。

当然,文档罗列的是 SkyWalking 开发团队已经测试过,经过确认支持的框架的版本。具体的,胖友最好动手测试下,自己再验证一波。如果碰到不支持的情况,可以查看对应框架的 SkyWalking 插件代码,比较容易就能定位到源码落。

嘻嘻,想要对 SkyWalking 做进一步深入的胖友,欢迎来看艿艿写的《SkyWalking 源码解析》。美滋滋~

相关文章