多个微服务之间的调用关系记录,称为服务链路追踪,这样可以很清楚的查看到,各服务之间的相互调用。比较流行的技术有 springcloud 的zipkin组件,skywalking,logstash等,今天主要讲解zipkin 的实战使用。
1、zipkin 服务端在springcloud 的F版本之后,官方给提供标准的服务jar包,下载地址是:
https://dl.bintray.com/openzipkin/maven/io/zipkin/java/zipkin-server/
启动命令如:java -jar zipkin-server-2.10.4-exec.jar
这里重点强调一下 以上启动命令是没有连接数据库的,zipkin 默认是不连接数据库的,数据默认是存在内存中的,服务重启后数据会完全丢失。如果连接数据库通常是连接mysql 数据库、es数据库。一会我也会提供一下启动时连接mysql数据库的命令。
先启动 不连数据库命令如图所示:
启动后访问默认端口地址:http://localhost:9411 显示如下页面
这时候没有客户端的数据,点击Find Traces 显示记录为空。
2、配置启动客户端,nandao-web、nandao-order
pom文件引入jar
org.springframework.cloud
spring-cloud-starter-zipkin
bootstrap.properties 中配置
#采集记录的百分比
spring.sleuth.sampler.percentage=1.0
# 若在同一个注册中心的话可以启用自动发现,省略base-url
#spring.zipkin.locator.discovery.enabled=true
#配置服务端的地址
spring.zipkin.base-url=http://localhost:9411/
分别启动两个客户端:启动成功标志:
这时候我们从nandao-web 调用nandao-order 服务;
刷新zipkin web端,显示调用记录:
客户端控制台:
这里 解释一下日志中的 [appname,traceId,spanId,exportable] 各部分所代表的含义:
appname:记录日志的应用的名称,即spring.application.name的值;
traceId:Sleuth为一次请求链路生成的唯一ID,一个Trace中可以包含多个Span;
spanId:请求链路基本的工作单元,代表发生一次特定的操作,例如:发送一个Http请求;
exportable:是否需要将日志导出到 Zipkin;
这说明服务链路功能演示成功,但是重启服务后,数据消失,原因是没有连接数据库。
3、现在我们演示连接mysql数据库的操作:
首先zipkin 数据库,并在数据库中初始化三张表结构
相关sql 可以从这下载:https://github.com/openzipkin/zipkin/blob/master/zipkin-storage/mysql-v1/src/main/resources/mysql.sql
这里也给大家贴出来:
CREATE 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,
`remote_service_name` VARCHAR(255),
`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(`remote_service_name`) COMMENT 'for getTraces and getRemoteServiceNames';
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服务器,命令如下:
java -jar zipkin-server-2.10.4-exec.jar --STORAGE_TYPE=mysql --MYSQL_HOST=localhost --MYSQL_TCP_PORT=3306 --MYSQL_DB=zipkin --MYSQL_USER=root --MYSQL_PASS=123456
再次访问zipkin 客户端:这是页面数据变成空的,
现在我们请求一下微服务客户端:zipkin web页面显示
最后,我们重启zipkin (同时连接数据库)命令,访问http://localhost:9411 ,显示以前的历史数据了,说明日志链路数据以及持久化到mysql 数据库里了。另外这样web端的功能也比较简单大家可以先熟悉一下,后期我们也会详细讲解,
到这里zipkin 实战我们讲完了,不明白的地方欢迎随时留言,下篇我们详细分析 skywalking 技术;敬请期待!!!