docker–zipkin(分布式链路追踪)实践
前言
- 官网:OpenZipkin https://zipkin.io/pages/quickstart.html
- zipkin是Twitter基于google的分布式监控系统Dapper(论文)的开发源实现,zipkin用于跟踪分布式服务之间的应用数据链路,分析处理延时,帮助我们改进系统的性能和定位故障
- 搭建 Zipkin 最简单的办法是直接使用 Zipkin 官方的 Docker 镜像。
zipkin架构
启动服务
- 启动服务命令如下
#!/bin/sh docker run -d \ --restart always \ -v /etc/localtime:/etc/localtime:ro \ -p 9411:9411 \ --name zipkin \ openzipkin/zipkin
- 以上命令即可启动一个zipkin服务,不过数据是放在内存中,一旦重启就数据就消失了,因此这种只适合在测试时使用,生产环境中需要配置持久化,如mysql
使用mysql数据库
-
如果只是为了测试用,那么以上的服务就够用了,但是一旦到生产环境中,那么数据持久化就非常重要了,官方提供了很多支持,在这里我就用mysql来存储了
-
如果你已经有了mysql数据库,那么可以直接用现有的mysql进行建库建表
-
以下方法适用于mysql数据库跟zipkin不在同一台机器上
-
首先创建数据库zipkin,编码使用utf8
-
创建数据库后执行以下sql创建表,sql语句官方链接地址:
https://github.com/openzipkin/zipkin/blob/master/zipkin-storage/mysql-v1/src/main/resources/mysql.sqlCREATE TABLE IF NOT EXISTS zipkin_spans ( `trace_id_high` BIGINT NOT NULL DEFAULT 0 COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit', `trace_id` BIGINT NOT NULL, `id` BIGINT NOT NULL, `name` VARCHAR(255) NOT NULL, `parent_id` BIGINT, `debug` BIT(1), `start_ts` BIGINT COMMENT 'Span.timestamp(): epoch micros used for endTs query and to implement TTL', `duration` BIGINT COMMENT 'Span.duration(): micros used for minDuration and maxDuration query', PRIMARY KEY (`trace_id_high`, `trace_id`, `id`) ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci; ALTER TABLE zipkin_spans ADD INDEX(`trace_id_high`, `trace_id`) COMMENT 'for getTracesByIds'; ALTER TABLE zipkin_spans ADD INDEX(`name`) COMMENT 'for getTraces and getSpanNames'; ALTER TABLE zipkin_spans ADD INDEX(`start_ts`) COMMENT 'for getTraces ordering and range'; CREATE TABLE IF NOT EXISTS zipkin_annotations ( `trace_id_high` BIGINT NOT NULL DEFAULT 0 COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit', `trace_id` BIGINT NOT NULL COMMENT 'coincides with zipkin_spans.trace_id', `span_id` BIGINT NOT NULL COMMENT 'coincides with zipkin_spans.id', `a_key` VARCHAR(255) NOT NULL COMMENT 'BinaryAnnotation.key or Annotation.value if type == -1', `a_value` BLOB COMMENT 'BinaryAnnotation.value(), which must be smaller than 64KB', `a_type` INT NOT NULL COMMENT 'BinaryAnnotation.type() or -1 if Annotation', `a_timestamp` BIGINT COMMENT 'Used to implement TTL; Annotation.timestamp or zipkin_spans.timestamp', `endpoint_ipv4` INT COMMENT 'Null when Binary/Annotation.endpoint is null', `endpoint_ipv6` BINARY(16) COMMENT 'Null when Binary/Annotation.endpoint is null, or no IPv6 address', `endpoint_port` SMALLINT COMMENT 'Null when Binary/Annotation.endpoint is null', `endpoint_service_name` VARCHAR(255) COMMENT 'Null when Binary/Annotation.endpoint is null' ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci; ALTER TABLE zipkin_annotations ADD UNIQUE KEY(`trace_id_high`, `trace_id`, `span_id`, `a_key`, `a_timestamp`) COMMENT 'Ignore insert on duplicate'; ALTER TABLE zipkin_annotations ADD INDEX(`trace_id_high`, `trace_id`, `span_id`) COMMENT 'for joining with zipkin_spans'; ALTER TABLE zipkin_annotations ADD INDEX(`trace_id_high`, `trace_id`) COMMENT 'for getTraces/ByIds'; ALTER TABLE zipkin_annotations ADD INDEX(`endpoint_service_name`) COMMENT 'for getTraces and getServiceNames'; ALTER TABLE zipkin_annotations ADD INDEX(`a_type`) COMMENT 'for getTraces and autocomplete values'; ALTER TABLE zipkin_annotations ADD INDEX(`a_key`) COMMENT 'for getTraces and autocomplete values'; ALTER TABLE zipkin_annotations ADD INDEX(`trace_id`, `span_id`, `a_key`) COMMENT 'for dependencies job'; CREATE TABLE IF NOT EXISTS zipkin_dependencies ( `day` DATE NOT NULL, `parent` VARCHAR(255) NOT NULL, `child` VARCHAR(255) NOT NULL, `call_count` BIGINT, `error_count` BIGINT, PRIMARY KEY (`day`, `parent`, `child`) ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;
-
创建好数据库后就可以启动zipkin服务了,命令如下
#!/bin/sh docker run -d \ --restart always \ -v /etc/localtime:/etc/localtime:ro \ -e MYSQL_USER=root \ -e MYSQL_PASS=password \ -e MYSQL_HOST=192.168.0.8 \ -e STORAGE_TYPE=mysql \ -e MYSQL_DB=zipkin \ -e MYSQL_TCP_PORT=3306 \ --net host \ --name zipkin \ openzipkin/zipkin
-
以上参数需要根据实际情况修改,这里由于使用到数据库,因此网络模式为host;如果使用桥接方式,那么要用link连接到数据库(理论上可行,但自己没测试过,故不做说明)
以上虽然加了共享宿主机的时区,进入到容器内查看date和宿主机也是一样的,但看打印日志的时间还是快了8小时,百思不得其解,望高人指点
springcloud实践
- 实践环境为:
- springboot:2.1.3.RELEASE
- springcloud:Greenwich.SR1
- gradle:5.2.1
引入依赖
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.cloud:spring-cloud-starter-zipkin'
}
- spring-cloud-starter-zipkin中已包含了spring-cloud-starter-sleuth与spring-cloud-sleuth-zipkin的依赖,所以使用sleuth-zipkin的SpringCloud项目只需添加spring-cloud-starter-zipkin依赖即可
配置
spring:
application:
name: test #在zipkin上显示的服务名,不写则是“default”
zipkin:
base-url: http://192.168.25.169:9411/ #zipkin服务的地址
# sender:
# type: web #网上有人在zipkin上查不到记录,说加上这个即可,但本人亲测不加也是可以查到记录
sleuth:
sampler:
probability: 1.0 #请求的采样率,在测试时为了方便查看可以改为1表示所有请求都记录,但在生产环境中还是建议改为0.1,否则数量太多影响性能
接口实现
- 在程序中简单实现一个接口
@SpringBootApplication
@RestController
public class SleuthApplication {
public static void main(String[] args) {
SpringApplication.run(SleuthApplication.class, args);
}
@GetMapping("/test")
public String abc(){
return "hello";
}
}
运行
- 通过以上两步运行程序即可,此时调用test接口在zipkin服务上并不能马上看到记录,需要等待大约1分钟左右再去刷新
值得注意的是,zipkin的浏览器兼容性还不是很好,在ie和360浏览器上发现显示不了记录,建议使用firefox进行测试,一开始用360浏览器一直看不到记录,害我以为是服务有问题,浪费了大量时间排查
另外,由于时区的问题未解决,因此时间可能要选大一点的才可能查找到
参考
Quickstart · OpenZipkin
https://zipkin.io/pages/quickstart.html
openzipkin/zipkin - Docker Hub
https://hub.docker.com/r/openzipkin/zipkin
openzipkin/docker-zipkin: Docker images for OpenZipkin
https://github.com/openzipkin/docker-zipkin
Zipkin快速开始 - ksfzhaohui技术专栏 - SegmentFault 思否
https://segmentfault.com/a/1190000012342007
分布式服务跟踪及Spring Cloud的实现 - 沧海一滴 - 博客园
https://www.cnblogs.com/softidea/p/6854989.html