如果胖友还没了解过分布式链路追踪 SkyWalking,建议先阅读下艿艿写的 《SkyWalking 极简入门》 文章。虽然这篇文章标题是安装部署,实际可以理解成《一文带你快速入门 SkyWalking》,哈哈哈。
可能会有胖友会有疑惑,Spring Boot 不是一个单体应用么,为什么可以使用 SkyWalking 进行分布式链路追踪呢?其实这里有一个误区!即使是一个 Spring Boot 单体应用,我们一般可能会和以下服务打交道:
那么即使是一个 Spring Boot 单体应用,就已经涉及到分布在不同进程中的服务。此时,就已经满足使用 SkyWalking 进行分布式链路追踪的条件,同时也是非常有必要的。例如说,我们线上某个 API 接口访问非常慢,可以通过 SkyWalking 来排查,是因为 MySQL 查询比较慢呢,还是调用的第三方服务比较慢。
在本文中,我们会比《SkyWalking 极简入门》提供更多在 Spring Boot 中使用的示例。例如说:
示例代码对应仓库:lab-39-springmvc。
本小节,我们来搭建一个 SkyWalking 对 SpringMVC 的 API 接口的链路追踪。该链路通过如下插件实现收集:
spring/mvc-annotation-3.x-plugin
spring/mvc-annotation-4.x-plugin
spring/mvc-annotation-5.x-plugin
在 pom.xml
文件中,引入相关依赖。
org.springframework.boot
spring-boot-starter-parent
2.2.2.RELEASE
4.0.0
jar
lab-39-springmvc
org.springframework.boot
spring-boot-starter-web
在 application.yml
中,添加服务器端口配置,如下:
server:
port: 8079
在 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";
}
}
创建 Application.java
类,配置 @SpringBootApplication
注解即可。代码如下:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
通过 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.
1、首先,使用浏览器,访问下 http://127.0.0.1:8079/demo/echo 地址,请求下 Spring Boot 应用提供的 API。因为,我们要追踪下该链路。
2、然后,继续使用浏览器,打开 http://127.0.0.1:8080/ 地址,进入 SkyWalking UI 界面。如下图所示:
3、之后,点击「拓扑图」菜单,进入查看拓扑图的界面,可以看到 SpringMVC 小方块。如下图所示:
4、再之后,点击「追踪」菜单,进入查看链路数据的界面。如下图所示:
示例代码对应仓库:lab-39-springmvc 。
在「2. SpringMVC 示例」小节中,我们已经实现了对 SpringMVC 提供的 HTTP API 接口的链路追踪。但是,我们可能希望忽略部分特殊 URL 的追踪,例如说,健康检查的 HTTP API。
所以,我们可以使用 SkyWalking 提供 trace-ignore-plugin
插件,可以实现忽略部分 URL 的追踪。
本小节,我们无需单独搭建项目,而是直接使用 lab-39-springmvc 项目即可。
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/
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
,这样方便我们自定义。通过 IDEA 的「Run/Debug Configurations」配置使用 SkyWalking Agent。如下图所示:
然后,执行 Application#main(String[] args)
方法,启动该 Spring Boot 应用。
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 对应的链路数据。如下图所示:
示例代码对应仓库:lab-39-mysql。
本小节,我们来搭建一个 SkyWalking 对 MySQL 操作的链路追踪。该链路通过如下插件实现收集:
jdbc-commons
mysql-common
mysql-5.x-plugin
mysql-6.x-plugin
mysql-8.x-plugin
我们将使用 Spring JdbcTemplate 进行 MySQL 的操作。对 Spring JdbcTemplate 感兴趣的胖友,可以后续去看看《芋道 Spring Boot JdbcTemplate 入门》文章。
在 pom.xml
文件中,引入相关依赖。
org.springframework.boot
spring-boot-starter-parent
2.2.2.RELEASE
4.0.0
jar
lab-39-mysql
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-jdbc
mysql
mysql-connector-java
5.1.46
在 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');
在 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 的查询。创建 MySQLApplication.java
类,配置 @SpringBootApplication
注解即可。代码如下:
@SpringBootApplication
public class MySQLApplication {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
通过 IDEA 的「Run/Debug Configurations」配置使用 SkyWalking Agent。如下图所示:
然后,执行 MySQLApplication#main(String[] args)
方法,启动该 Spring Boot 应用。
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
环境变量。示例代码对应仓库:lab-39-redis。
本小节,我们来搭建一个 SkyWalking 对 Redis 操作的链路追踪。该链路通过如下插件实现收集:
jedis-2.x-plugin
redisson-3.x-plugin
lettuce-5.x-plugin
我们将使用 Spring Data Redis + Jedis 进行 Redis 的操作。对 Spring Data Redis 感兴趣的胖友,可以后续去看看《Spring Boot Redis 入门》文章。
在 pom.xml
文件中,引入相关依赖。
org.springframework.boot
spring-boot-starter-parent
2.2.2.RELEASE
4.0.0
lab-39-redis
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-data-redis
io.lettuce
lettuce-core
redis.clients
jedis
在 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 ,表示不限制。
在 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 操作。创建 RedisApplication.java
类,配置 @SpringBootApplication
注解即可。代码如下:
@SpringBootApplication
public class RedisApplication {
public static void main(String[] args) {
SpringApplication.run(RedisApplication.class, args);
}
}
通过 IDEA 的「Run/Debug Configurations」配置使用 SkyWalking Agent。如下图所示:
然后,执行 RedisApplication#main(String[] args)
方法,启动该 Spring Boot 应用。
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());
}
示例代码对应仓库:lab-39-mongodb。
本小节,我们来搭建一个 SkyWalking 对 MongoDB 操作的链路追踪。该链路通过如下插件实现收集:
mongodb-2.x-plugin
mongodb-3.x-plugin
我们将使用 Spring Data MongoDB 进行 MongoDB 的操作。对 Spring Data MongoDB 感兴趣的胖友,可以后续去看看《Spring Boot MongoDB 入门》文章。
在 pom.xml
文件中,引入相关依赖。
org.springframework.boot
spring-boot-starter-parent
2.2.2.RELEASE
4.0.0
lab-39-mongodb
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-data-mongodb
在 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
在 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 查询操作。创建 MongoDBApplication.java
类,配置 @SpringBootApplication
注解即可。代码如下:
// Application.java
@SpringBootApplication
public class MongoDBApplication {
public static void main(String[] args) {
SpringApplication.run(MongoDBApplication.class, args);
}
}
默认情况下,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
环境变量开启。通过 IDEA 的「Run/Debug Configurations」配置使用 SkyWalking Agent。如下图所示:
然后,执行 MongoDBApplication#main(String[] args)
方法,启动该 Spring Boot 应用。
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 操作的链路数据,可以看到操作语句。如下图所示:
示例代码对应仓库:lab-39-elasticsearch-jest。
本小节,我们来搭建一个 SkyWalking 对 Elasticsearch 操作的链路追踪。该链路通过如下插件实现收集:
elasticsearch-5.x-plugin
elasticsearch-6.x-plugin
不过略微翻车了。原因是:
6.6.0
版本的 elasticsearch-5.x-plugin
插件,暂时只支持 transport-client
5.2.x
-5.6.x
版本。什么意思呢?如果使用 Elasticsearch TCP 协议的客户端,不能使用 6.X
开始的版本。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 入门》文章。
在 pom.xml
文件中,引入相关依赖。
org.springframework.boot
spring-boot-starter-parent
2.2.1.RELEASE
4.0.0
lab-39-elasticsearch-jest
org.springframework.boot
spring-boot-starter-web
com.github.vanroy
spring-boot-starter-data-jest
3.3.0.RELEASE
因为 Spring Data Jest 3.3.0.RELEASE
版本,最高只能支持 Elasticsearch 6.8.4
版本,所以 艿艿又不得不搭建一个 Elasticsearch 6.8.4
版本的服务。心疼自己 5 秒钟,各种倒腾。
在 application.yml
中,添加 Redis 配置,如下:
server:
port: 8079
spring:
data:
# Jest 配置项
jest:
uri: http://127.0.0.1:9400
在 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 插入和查询操作。创建 ElasticsearchJestApplication.java
类,配置 @SpringBootApplication
注解即可。代码如下:
@SpringBootApplication(exclude = {ElasticsearchAutoConfiguration.class, ElasticsearchDataAutoConfiguration.class})
public class ElasticsearchJestApplication {
public static void main(String[] args) {
SpringApplication.run(ElasticsearchJestApplication.class, args);
}
}
通过 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 请求的具体参数可能很长,所以最好做下最大长度的截取。
示例代码对应仓库:lab-39-rocketmq。
本小节,我们来搭建一个 SkyWalking 对 RocketMQ 消息的发送和消费的链路追踪。该链路通过如下插件实现收集:
rocketMQ-3.x-plugin
rocketMQ-4.x-plugin
我们将使用 RocketMQ-Spring 进行 RocketMQ 的操作。对 RocketMQ 感兴趣的胖友,可以后续去看看《芋道 Spring Boot 消息队列 RocketMQ 入门》文章。
考虑到让示例更简单,我们的示例项目包含 RocketMQ 的生产者 Producer 和消费者 Consumer。
在 pom.xml
文件中,引入相关依赖。
org.springframework.boot
spring-boot-starter-parent
2.2.1.RELEASE
4.0.0
lab-39-rocketmq
org.springframework.boot
spring-boot-starter-web
org.apache.rocketmq
rocketmq-spring-boot-starter
2.0.4
在 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 。
在 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 发送消息的操作。创建 RocketMQApplication.java
类,配置 @SpringBootApplication
注解即可。代码如下:
@SpringBootApplication
public class RocketMQApplication {
public static void main(String[] args) {
SpringApplication.run(RocketMQApplication.class, args);
}
}
通过 IDEA 的「Run/Debug Configurations」配置使用 SkyWalking Agent。如下图所示:
然后,执行 RocketMQApplication#main(String[] args)
方法,启动该 Spring Boot 应用。
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。如下图所示:
可能部分胖友采用的是阿里云的消息队列 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 服务的链路追踪。
示例代码对应仓库:lab-39-kafka。
本小节,我们来搭建一个 SkyWalking 对 Kafka 消息的发送和消费的链路追踪。该链路通过如下插件实现收集:
kafka-plugin
我们将使用 Spring-Kafka 进行 Kafka 的操作。对 Kafka 感兴趣的胖友,可以后续去看看《芋道 Spring Boot 消息队列 Kafka 入门》文章。
考虑到让示例更简单,我们的示例项目包含 Kafka 的生产者 Producer 和消费者 Consumer。
在 pom.xml
文件中,引入相关依赖。
org.springframework.boot
spring-boot-starter-parent
2.1.11.RELEASE
4.0.0
lab-39-kafka
org.springframework.kafka
spring-kafka
2.2.11.RELEASE
org.springframework.boot
spring-boot-starter-web
友情提示: SkyWalking
kafka-plugin
对高版本的kafka-clients
的链路追踪兼容性还存在一点问题,无法追踪到 Kafka Producer 发送消息。所以,这里我们将
spring-kafka
的版本从2.3.3.RELEASE
修改成2.2.11.RELEASE
,以使用kafka-clients
的低版版本2.0.1
。
在 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 ,解决报错
在 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 发送消息的操作。创建 KafkaApplication.java
类,配置 @SpringBootApplication
注解即可。代码如下:
@SpringBootApplication
public class KafkaApplication {
public static void main(String[] args) {
SpringApplication.run(KafkaApplication.class, args);
}
}
通过 IDEA 的「Run/Debug Configurations」配置使用 SkyWalking Agent。如下图所示:
然后,执行 KafkaApplication#main(String[] args)
方法,启动该 Spring Boot 应用。
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。如下图所示:
示例代码对应仓库:lab-39-rabbitmq-demo。
本小节,我们来搭建一个 SkyWalking 对 Rabbitmq 消息的发送和消费的链路追踪。该链路通过如下插件实现收集:
rabbitmq-5.x-plugin
我们将使用 Spring-AMQP 进行 RabbitMQ 的操作。对 RabbitMQ 感兴趣的胖友,可以后续去看看《芋道 Spring Boot 消息队列 RabbitMQ 入门》文章。
考虑到让示例更简单,我们的示例项目包含 RabbitMQ 的生产者 Producer 和消费者 Consumer。
在 pom.xml
文件中,引入相关依赖。
org.springframework.boot
spring-boot-starter-parent
2.2.1.RELEASE
4.0.0
lab-39-rabbitmq-demo
org.springframework.boot
spring-boot-starter-amqp
org.springframework.boot
spring-boot-starter-web
在 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 服务的密码
在 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 发送消息的操作。创建 RabbitMQApplication.java
类,配置 @SpringBootApplication
注解即可。代码如下:
@SpringBootApplication
public class RabbitMQApplication {
public static void main(String[] args) {
SpringApplication.run(RabbitMQApplication.class, args);
}
}
通过 IDEA 的「Run/Debug Configurations」配置使用 SkyWalking Agent。如下图所示:
然后,执行 KafkaApplication#main(String[] args)
方法,启动该 Spring Boot 应用。
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。如下图所示:
示例代码对应仓库:lab-39-activemq。
本小节,我们来搭建一个 SkyWalking 对 ActiveMQ 消息的发送和消费的链路追踪。该链路通过如下插件实现收集:
activemq-5.x-plugin
我们将使用 Spring-JMS 进行 ActiveMQ 的操作。对 ActiveMQ 感兴趣的胖友,可以后续去看看《Spring Boot 消息队列 ActiveMQ 入门》文章。
考虑到让示例更简单,我们的示例项目包含 ActiveMQ 的生产者 Producer 和消费者 Consumer。
在 pom.xml
文件中,引入相关依赖。
org.springframework.boot
spring-boot-starter-parent
2.2.1.RELEASE
4.0.0
lab-39-activemq
org.springframework.boot
spring-boot-starter-activemq
org.springframework.boot
spring-boot-starter-web
在 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 # 可信任的反序列化包
在 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 发送消息的操作。创建 ActiveMQApplication.java
类,配置 @SpringBootApplication
注解即可。代码如下:
@SpringBootApplication
public class ActiveMQApplication {
public static void main(String[] args) {
SpringApplication.run(ActiveMQApplication.class, args);
}
}
通过 IDEA 的「Run/Debug Configurations」配置使用 SkyWalking Agent。如下图所示:
然后,执行 ActiveMQApplication#main(String[] args)
方法,启动该 Spring Boot 应用。
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。如下图所示:
示例代码对应仓库:lab-39-logback。
在使用 SkyWalking 排查问题的时候,我们可能希望能够跟链路的日志进行关联,那么我们可以将链路编号( SkyWalking TraceId )记录到日志中,从而进行关联。
友情提示:艿艿自己的项目里,在一些业务数据希望跟 SkyWalking 链路进行关联时,会考虑新增一个
traceId
字段,存储 SkyWalking TraceId。例如说:
- 发送聊天消息时,消息记录上会存储链路编号。
- 创建交易订单时,订单记录上会存储链路编号。
这样,在排查该数据记录时,我们就可以拿着
traceId
字段,去查响应的链路信息和日志信息。
SkyWalking 提供了多种日志框架的支持,通过不同的插件:
apm-toolkit-log4j-1.x-activation
:支持 Log4j1 日志框架,对应《Application-toolkit-log4j-1.x.md》文档。apm-toolkit-log4j-2.x-activation
:支持 Log4j2 日志框架,对应《Application-toolkit-log4j-2.x.md》文档。apm-toolkit-logback-1.x-activation
:支持 Logback 日志框架,对应《Application-toolkit-logback-1.x.md》文档。本小节,我们来搭建一个 SLF4J + Logback 日志的 SkyWalking TraceId 的集成示例。对 Logging 感兴趣的胖友,可以后续去看看《芋道 Spring Boot 日志框架 Logging 入门》文章。
在 pom.xml
文件中,引入相关依赖。
org.springframework.boot
spring-boot-starter-parent
2.2.2.RELEASE
4.0.0
jar
lab-39-logback
org.apache.skywalking
apm-toolkit-logback-1.x
6.6.0
org.springframework.boot
spring-boot-starter-web
在 application.yml
中,添加配置,如下:
server:
port: 8079
spring:
application:
name: demo-application-logback
在 logback-spring.xml
中,添加 Logback 配置,如下:
${CONSOLE_LOG_PATTERN}
${LOG_FILE}
${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz
7
10MB
${FILE_LOG_PATTERN}
日志配置有点长哈,主要配置 2 处地方,我们来看看图。如下图锁标记:
在 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
接口中,会执行一次日志的记录。创建 LogbackApplication.java
类,配置 @SpringBootApplication
注解即可。代码如下:
@SpringBootApplication
public class LogbackApplication {
public static void main(String[] args) {
SpringApplication.run(LogbackApplication.class, args);
}
}
通过 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)
%tid
占位符被替换成了 TID:N/A
。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 集成到日志组件》文章。
示例代码对应仓库:lab-39-trace-annotations。
在上述的示例中,我们都是通过 SkyWalking 提供的插件,实现对指定框架的链路追踪。那么,如果我们希望对项目中的业务方法,实现链路追踪,方便我们排查问题,需要怎么做呢?SkyWalking 提供了两种方式:
@Trace
注解,可见《Application-toolkit-trace.md》文档。
配置,可见《Customize-enhance-trace.md》文档。艿艿在项目中,使用 SkyWalking @Trace
注解较多,所以本小节我们就来看看它的使用示例。
在 pom.xml
文件中,引入相关依赖。
org.springframework.boot
spring-boot-starter-parent
2.2.2.RELEASE
4.0.0
jar
lab-39-trace-annotations
org.apache.skywalking
apm-toolkit-trace
6.6.0
org.springframework.boot
spring-boot-starter-web
在 application.yml
中,添加配置,如下:
server:
port: 8079
在 cn.iocoder.springboot.lab39.skywalkingdemo.controller
包路径下,创建 DemoController 类,提供示例 API 接口。代码如下:
@RestController
@RequestMapping("/demo")
public class DemoController {
@GetMapping("/trace_annotations")
@Trace(operationName = "trace_annotations")
public String echo() {
// 自定义 SkyWalking Span
ActiveSpan.tag("mp", "芋道源码");
// 返回
return "trace_annotations";
}
}
在 #echo()
方法上,添加了 SkyWalking @Trace
注解,实现 SkyWalking 指定方法的追踪,会创建一个 SkyWalking LocalSpan。同时,可以通过 operationName
属性,设置操作名。
在
处,通过 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 链路追踪编号。
创建 TraceAnnotationsApplication.java
类,配置 @SpringBootApplication
注解即可。代码如下:
@SpringBootApplication
public class TraceAnnotationsApplication {
public static void main(String[] args) {
SpringApplication.run(TraceAnnotationsApplication.class, args);
}
}
通过 IDEA 的「Run/Debug Configurations」配置使用 SkyWalking Agent。如下图所示:
然后,执行 TraceAnnotationsApplication#main(String[] args)
方法,启动该 Spring Boot 应用。
1、首先,使用浏览器,访问下 http://127.0.0.1:8079/demo/trace_annotations 地址,请求下 Spring Boot 应用提供的 API。因为,我们要追踪下该链路。
2、然后,查看 SkyWalking UI 链路界面,可以看到我们自定义追踪的方法。示例如下图:
点击红圈的 @Trace
注解的链路数据,可以看到具体信息。如下图所示:
具体实现原理,感兴趣的胖友,可以看看《SkyWalking 源码分析 —— @Trace 注解想要追踪的任何方法》文章。
示例代码对应仓库: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 的使用示例。
在 pom.xml
文件中,引入相关依赖。
org.springframework.boot
spring-boot-starter-parent
2.2.2.RELEASE
4.0.0
lab-39-opentracing
org.apache.skywalking
apm-toolkit-opentracing
6.6.0
org.springframework.boot
spring-boot-starter-web
在 application.yml
中,添加配置,如下:
server:
port: 8079
在 cn.iocoder.springboot.lab39.skywalkingdemo.controller
包路径下,创建 DemoController 类,提供示例 API 接口。代码如下:
@RestController
@RequestMapping("/demo")
public class DemoController {
@GetMapping("/opentracing")
public String echo() {
// 创建一个 Span
Tracer tracer = new SkywalkingTracer();
tracer.buildSpan("custom_operation").withTag("mp", "芋道源码").startManual().finish();
// 返回
return "opentracing";
}
}
/demo/opentracing
接口中的
处,我们使用 Opentracing Java API 创建了一个 Span。创建 OpentracingApplication.java
类,配置 @SpringBootApplication
注解即可。代码如下
@SpringBootApplication
public class OpentracingApplication {
public static void main(String[] args) {
SpringApplication.run(OpentracingApplication.class, args);
}
}
通过 IDEA 的「Run/Debug Configurations」配置使用 SkyWalking Agent。如下图所示:
然后,执行 OpentracingApplication#main(String[] args)
方法,启动该 Spring Boot 应用。
1、首先,使用浏览器,访问下 http://127.0.0.1:8079/demo/opentracing 地址,请求下 Spring Boot 应用提供的 API。因为,我们要追踪下该链路。
2、然后,查看 SkyWalking UI 链路界面,可以看到使用 Opentracing 创建的链路。示例如下图:
点击红圈的 Opentracing 创建的链路数据,可以看到具体信息。如下图所示:
示例代码对应仓库:lab-39-async。
本小节,我们来搭建一个 SkyWalking 对 Spring 异步任务的链路追踪。该链路通过如下插件实现收集:
spring-plugins/async-annotation-plugin
下面,我们来搭建一个 Spring 异步任务的使用示例。。对 Spring 异步任务感兴趣的胖友,可以后续去看看《芋道 Spring Boot 异步任务入门》文章。
在 pom.xml
文件中,引入相关依赖。
org.springframework.boot
spring-boot-starter-parent
2.2.2.RELEASE
4.0.0
jar
lab-39-async
org.springframework.boot
spring-boot-starter-web
在 application.yml
中,添加配置,如下:
server:
port: 8079
在 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 异步任务。创建 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 发生了啥冲突,不太记得了。通过 IDEA 的「Run/Debug Configurations」配置使用 SkyWalking Agent。如下图所示:
然后,执行 OpentracingApplication#main(String[] args)
方法,启动该 Spring Boot 应用。
1、首先,使用浏览器,访问下 http://127.0.0.1:8079/demo/async 地址,请求下 Spring Boot 应用提供的 API。因为,我们要追踪下该链路。
2、然后,查看 SkyWalking UI 链路界面,可以看 Spring 异步任务的链路。示例如下图:
另外,如果胖友不想使用 Spring 提供的异步任务的功能,想自己使用线程池实现异步,同时又想实现对该异步任务的链路追踪,可以参考《SkyWalking —— Application-toolkit-trace-cross-thread.md》文档。
示例代码对应仓库:
- 服务 API 项目:
lab-39-skywalking-dubbo-api
- 服务 Provider 项目:
skywalking-dubbo-provider
- 服务 Consumer 项目:
skywalking-dubbo-consumer
本小节,我们来搭建一个 SkyWalking 对 Dubbo 的远程 RPC 调用的链路追踪。该链路通过如下插件实现收集:
dubbo-2.7.x-conflict-patch
dubbo-2.7.x-plugin
dubbo-conflict-patch
dubbo-plugin
我们来新建一个 lab-39-skywalking-dubbo
模块,一共包含三个子项目。最终如下图所示:
另外,考虑到目前 Dubbo 主要使用 Zookeeper 作为注册中心,所以本小节也是使用 Zookeeper。不了解的胖友,后续可以看看《Zookeeper 极简入门》文章。
创建 lab-39-skywalking-dubbo-api
项目,服务接口,定义 Dubbo Service API 接口,提供给消费者使用。
创建 UserService 接口,定义用户服务 RPC Service 接口。代码如下:
public interface UserService {
/**
* 根据指定用户编号,获得用户信息
*
* @param id 用户编号
* @return 用户信息
*/
String get(Integer id);
}
创建 skywalking-dubbo-provider
项目,服务提供者,实现 lab-39-skywalking-dubbo-api
项目定义的 Dubbo Service API 接口,提供相应的服务。
创建 pom.xml
文件中,引入依赖。
org.springframework.boot
spring-boot-starter-parent
2.2.2.RELEASE
4.0.0
lab-39-skywalking-dubbo-provider
cn.iocoder.springboot.labs
lab-39-skywalking-dubbo-api
1.0-SNAPSHOT
org.springframework.boot
spring-boot-starter
org.apache.dubbo
dubbo
2.7.4.1
org.apache.dubbo
dubbo-spring-boot-starter
2.7.4.1
org.apache.curator
curator-framework
2.13.0
org.apache.curator
curator-recipes
2.13.0
在 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 入门》文章。
创建 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;
}
}
创建 ProviderApplication 类,服务提供者的启动类。代码如下:
@SpringBootApplication
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class);
}
}
通过 IDEA 的「Run/Debug Configurations」配置使用 SkyWalking Agent。如下图所示:
创建 skywalking-dubbo-consumer
项目,服务消费者,会调用 lab-39-skywalking-dubbo-provider
项目提供的 User Service 服务。
创建 pom.xml
文件中,引入依赖。和「16.2.1 引入依赖」基本是一致的,胖友可以点击 pom.xml
文件查看。
在 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 入门》文章。
创建 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);
}
}
创建 ConsumerApplication 类,服务消费者的启动类。代码如下:
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class);
}
}
通过 IDEA 的「Run/Debug Configurations」配置使用 SkyWalking Agent。如下图所示:
使用 ProviderApplication 启动服务提供者,使用 ConsumerApplication 启动服务消费者。
① 首先,使用浏览器,访问 http://127.0.0.1:8079/user/get?id=1 地址,使用 Dubbo 调用 user-service-provider
服务。因为,我们要追踪下该链路。
② 然后,继续使用浏览器,打开 http://127.0.0.1:8080/ 地址,进入 SkyWalking UI 界面。如下图所示:
③ 之后,点击「拓扑图」菜单,进入查看拓扑图的界面,可以看到两个服务的小方块,以及对应的调用关系。如下图所示:
④ 再之后,点击「追踪」菜单,进入查看链路数据的界面。如下图所示:
示例代码对应仓库: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 项目即可。
修改 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
环境变量,可以实现自定义抽样收集数量。
通过 IDEA 的「Run/Debug Configurations」配置使用 SkyWalking Agent。如下图所示:
通过设置 SW_AGENT_SAMPLE
环境变量为 1,实现每 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 源码解析》。美滋滋~