本文源码存放在GitHub如有帮助请start三连
本文将讲解:zipkin搭建、SpringBoot2.X整合、redis监控、mysql监控、依赖树
SpringBoot整合Zipkin链路追踪
Zipkin
是Twitter
基于google
的分布式监控系统Dapper(论文)的开发源实现,zipkin用于跟踪分布式服务之间的应用数据链路,分析处理延时,帮助我们改进系统的性能和定位故障。Dapper论文地址
如果日志文件中有跟踪ID,则可以直接跳转到该文件。 否则,你可以根据服务,操作名称,tag标签和持续时间等属性进行查询。 将为您总结一些有趣的数据,例如在服务中花费的时间占比,以及操作是否失败。
Zipkin服务下载安装
下载与启动
$ curl -sSL https://zipkin.io/quickstart.sh | bash -s
$ java -jar zipin.jar
上面启动是前台的,控制台关闭后服务就停止了,接下来我们编写start.sh
和stop.sh
脚本
-
start.sh
脚本#!/bin/bash nohup java -jar zipkin.jar 2>&1 &
-
stop.sh
脚本#!/bin/bash ps -ef|grep zipkin|grep -v grep|awk '{print $2}'|xargs kill -9
接下来我们就可以通过
sh start.sh
或sh stop.sh
来开启和停止zipkin服务了
浏览器访问
服务启动后,默认会占用9411端口,对于Linux服务器有种方式开放这个端口
-
虚拟机
虚拟机若开启了防火墙,则可以采用如下命令进行开放端口
# 开启防火墙8777端口 $ firewall-cmd --zone=public --add-port=9411/tcp --permanent # 使配置生效 $ firewall-cmd --reload
-
云服务器
云服务器需要在
控制台->ECS控制台->网络安全->安全组
中添加安全组端口,这里我以阿里云为例: -
浏览器访问
http://ip:9411/
,出现如下界面表示服务启动成功
编写SpringBoot程序
这里我们除了监控rest调用外,还监控mysql和redis,所以我们一次性的集成mysql和redis
服务生产者
-
新建
maven
项目,编写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> <artifactId>05-zipkin</artifactId> <groupId>com.it235.cloud.example</groupId> <version>1.0.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>05-zipkin-producer</artifactId> <properties> <druid.version>1.1.10</druid.version> <mybatis.version>3.5.5</mybatis.version> <mybatisplus.version>3.4.0</mybatisplus.version> <mysql.version>8.0.21</mysql.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.5.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <!--SpringCloud--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Hoxton.SR3</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <!--Redis依赖--> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis-reactive</artifactId> </dependency> <!--MySQL依赖--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>${mybatisplus.version}</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>${druid.version}</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <!--zipkin链路追踪--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-sleuth</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-sleuth-zipkin</artifactId> </dependency> <!--这里我的数据库驱动是8的,所以采用8--> <dependency> <groupId>io.zipkin.brave</groupId> <artifactId>brave-instrumentation-mysql8</artifactId> <version>5.10.1</version> </dependency> </dependencies> </project>
-
新建
Application
启动程序和Controller
这里我只列出以下2个类,完整代码请下载GitHub源码
@SpringBootApplication public class ZipkinSpringBootApplication { public static void main(String[] args) { SpringApplication.run(ZipkinSpringBootApplication.class , args); } }
package com.it235.cloud.example.zipkin.controller; import com.baomidou.mybatisplus.core.metadata.IPage; import com.it235.cloud.example.redis.util.RedisUtil; import com.it235.cloud.example.zipkin.entity.SysProvince; import com.it235.cloud.example.zipkin.service.SysProvinceService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @description: 对外暴露API接口,其中的方法自行实现即可 * @package: com.it235.cloud.example.zipkin * @author: jianjun.ren * @date: Created in 2020/10/12 12:13 * @copyright: Copyright (c) 2019 * @modified: jianjun.ren */ @RestController @RequestMapping("/province") public class DatasourceMpController { @Autowired private SysProvinceService sysProvinceService; @GetMapping("/get/{id}") public SysProvince getById(@PathVariable("id") int id){ SysProvince province1 = sysProvinceService.getByIdAnnotation(id); test(String.valueOf(id)); return province1; } @Autowired private RedisUtil redisUtil; @GetMapping("test") public String test(String key){ Boolean flag = redisUtil.set(key, "redis测试"); if(flag){ return (String) redisUtil.get(key); } return "失败"; } }
-
编写
application.yml
添加关键依赖server: port: 7050 spring: application: name: it235-boot-zipkin-producer profiles: active: test datasource: url: jdbc:mysql://47.92.230.143:3306/wzrtest?queryInterceptors=brave.mysql8.TracingQueryInterceptor&exceptionInterceptors=brave.mysql8.TracingExceptionInterceptor&zipkinServiceName=yourdb&serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=false&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&rewriteBatchedStatements=true driver-class-name: com.mysql.cj.jdbc.Driver username: root password: TFSQL987 type: com.alibaba.druid.pool.DruidDataSource druid: initial-size: 5 # 初始化大小 min-idle: 5 # 最小 max-active: 100 # 最大 max-wait: 60000 # 配置获取连接等待超时的时间 time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 min-evictable-idle-time-millis: 300000 # 指定一个空闲连接最少空闲多久后可被清除,单位是毫秒 validationQuery: select 'x' test-while-idle: true # 当连接空闲时,是否执行连接测试 test-on-borrow: false # 当从连接池借用连接时,是否测试该连接 test-on-return: false # 在连接归还到连接池时是否测试该连接 filters: config,wall,stat # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙 poolPreparedStatements: true # 打开PSCache,并且指定每个连接上PSCache的大小 maxPoolPreparedStatementPerConnectionSize: 20 maxOpenPreparedStatements: 20 # druid web config web-stat-filter: enabled: true url-pattern: /* exclusions: "*.js , *.gif ,*.jpg ,*.png ,*.css ,*.ico , /druid/*" session-stat-max-count: 1000 profile-enable: true session-stat-enable: false stat-view-servlet: enabled: true url-pattern: /druid/* reset-enable: true login-username: knifeboot login-password: knifeboot redis: host: 47.92.230.143 password: UATTiFangEDU123 port: 6379 database: 1 # 使用库 1 timeout: 60s lettuce: # lettuce基于netty,线程安全,支持并发 pool: max-active: 50 max-wait: -1ms max-idle: 8 min-idle: 0 # zipkin重要代码 zipkin: base-url: http://47.92.230.143:9411/ enabled: true discovery-client-enabled: false sender: type: web service: name: ${spring.application.name} compression: enabled: true sleuth: sampler: probability: 1 # mybatis-plus配置 mybatis-plus: configuration: #开启驼峰命名法 map-underscore-to-camel-case: true # Mapper.xml路径,注意pom.xml中需要开启xml文件的编译 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl mapper-locations: classpath*:com/it235/cloud/example/**/mapper/xml/*Mapper.xml # xml中alias的匹配 type-aliases-package: com.it235.cloud.example.**.entity # 图标关闭 global-config: banner: false
我这里再次声明下zipkin重要配置
spring: zipkin: base-url: http://47.92.230.143:9411/ enabled: true discovery-client-enabled: false sender: type: web service: name: ${spring.application.name} compression: enabled: true sleuth: sampler: probability: 1
其中mysql连接后面的url参数
queryInterceptors=brave.mysql8.TracingQueryInterceptor&exceptionInterceptors=brave.mysql8.TracingExceptionInterceptor&zipkinServiceName=yourdb
也非常重要-- MySQL8驱动写法,自动兼容MySQL5.x版本实例 queryInterceptors=brave.mysql8.TracingQueryInterceptor&exceptionInterceptors=brave.mysql8.TracingExceptionInterceptor&zipkinServiceName=yourdb -- MySQL5驱动写法 statementInterceptors=brave.mysql.TracingStatementInterceptor&zipkinServiceName=yourdb
-
服务端编写完成后,接下来我们编写消费者,用来调用服务端程序,模拟微服务下的接口调用
服务消费者
-
新建
maven
项目,编写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> <artifactId>05-zipkin</artifactId> <groupId>com.it235.cloud.example</groupId> <version>1.0.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <groupId>com.it235.cloud.example</groupId> <artifactId>05-zipkin-consumer</artifactId> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.5.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <!--SpringCloud--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Hoxton.SR3</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!--zipkin链路追踪--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-sleuth</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-sleuth-zipkin</artifactId> </dependency> </dependencies> </project>
-
新建
Application
启动程序和Controller
@SpringBootApplication public class ZipkinConsumerApplication { @Bean @LoadBalanced RestTemplate restTemplate() { return new RestTemplate(); } public static void main(String[] args) { SpringApplication.run(ZipkinConsumerApplication.class, args); } }
@RestController @RequestMapping("/consumer") public class ConsumerController { @Autowired private RestTemplate restTemplate; @GetMapping public String test(){ String result = restTemplate.getForObject("http://localhost:7050/province/get/1", String.class); return result; } }
-
编写
application.yml
添加关键依赖server: port: 7055 spring: application: name: it235-boot-zipkin-consumer zipkin: base-url: http://47.92.230.143:9411/ enabled: true discovery-client-enabled: false sender: type: web service: name: ${spring.application.name} compression: enabled: true sleuth: sampler: probability: 1
-
消费者端这里我就不再集成mysql和redis了,做一个简单的链路调用,用来展示
-
在浏览器中输入
http://localhost:7055/consumer
,然后去zipkin的主页面搜索查询效果
查看zipkin监控
到这里,zipkin我们就集成完了,接下来我们看下zipkin的第二个功能,将上述列表以依赖树的方式进行展示
添加zipkin依赖树
zipkin
默认不提供依赖树视图数据的获取,这里我们需要下载zipkin-dependencies
的依赖树插件,将该插件编译成jar包后放到zipkin.jar
的同级目录下,zipkin的源码可以在github上获取,这里我给大家提供一份已经编译好的jar包,供大家使用。
链接:https://pan.baidu.com/s/1pQzcyBUSdBIoMcSw5AFWzQ
提取码:rr5l
同时也将zipkin-dependencise.jar启动下,下面是我编写好的启动脚本
#!/bin/bash
nohup java -jar zipkin-dependencies-2.4.4.jar 2>&1 &
但是比较蛋疼的是,依赖树获取一次后就停止服务了,下次要查看是需要重新启动一次,所以大家可以将启动脚本加入到conrab中去,10分钟一次的方式进行自启动和停止