SpringCloud Sleuth主要功能就是在分布式系统中提供追踪解决方案。它大量借用了GoogleDapper的设计, 先来了解一下Sleuth中的术语和相关概念。
我们可以使用它来收集各个服务器上请求链路的跟踪数据,并通过它提供的REST API接口来辅助我们查询跟踪数据以实现对分布式系统的监控程序,从而及时地发现系统中出现的延迟升高问题并找出系统性能瓶颈的根源。
除了面向开发的 API 接口之外,它也提供了方便的UI组件来帮助我们直观的搜索跟踪信息和分析请求链路明细,比如:可以查询某段时间内各用户请求的处理时间等。
Zipkin 提供了可插拔数据存储方式:In-Memory、MySql、Cassandra 以及 Elasticsearch。但是默认是存储在内存中,这样服务一挂,不就没了,所以还是需要持久化。
GitHub 地址:https://github.com/openzipkin/zipkin
点击下载最新版本的 jar 包: latest released server
在使用 Spring Boot 2.x 版本后,官方就不推荐自行定制编译了,让我们直接使用编译好的 jar 包.也就是说原来通过@EnableZipkinServer或@EnableZipkinStreamServer的路子,启动SpringBootApplication自建Zipkin Server是不行了
我们可以直接 shift + 鼠标右键,打开 powershell,直接运行 jar 包
# 第一种:(直接启动,不需要持久化)
java -jar .\zipkin-server-2.23.16-exec.jar
# 第二种:(需要持久化,我此处对接的是 MySQL,需要自己手动创建数据库,数据表,下面有对应 SQL 代码)
java -jar .\zipkin-server-2.23.16-exec.jar --STORAGE_TYPE=mysql --MYSQL_HOST=192.168.159.133 --MYSQL_TCP_PORT=3306 --MYSQL_USER=liuyunfei --MYSQL_PASS=Lyf123456! --MYSQL_DB=zipkin
# 第三种:(Docker 形式启动)
docker run -d -p 9411:9411 openzipkin/zipkin
# 第四种:(ElasticSearch 形式持久化)
java -jar .\zipkin-server-2.23.16-exec.jar --STORAGE_TYPE=elasticsearch --ESHOST=localhost:9200
CREATE DATABASE zipkin CHARACTER SET utf8;
# DROP DATABASE zipkin;
USE zipkin;
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;
我是要在网关中添加 链路追踪,大家当然也可以添加到其他的微服务中
<!--链路追踪-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
server:
port: 80
# 日志
logging:
level:
org.springframework.web.servlet.DispatcherServlet: DEBUG #一定要开启,否则推送不了日志给zipkin
org.springframework.cloud.sleuth: DEBUG
spring:
application:
name: GatewayDemo
cloud:
gateway:
# 配置路由
routes:
- id: ProductPageDemo
uri: lb://ProductPageDemo
predicates:
# 断言,以 /page/ 开头进行匹配
- Path=/page/**
filters:
# 过滤器,会去除第一级路径然后进行路由
- StripPrefix=1
- id: ProductDemo
uri: lb://ProductDemo
predicates:
# 断言,以 /page/ 开头进行匹配
- Path=/products/**
# 调用链 Sleuth + ZipKin
sleuth:
web:
client:
# 是否启用 webClient
enabled: true
sampler:
probability: 1.0 # 采用比例,默认 0.1 全部采样 1.0
zipkin:
enabled: true
base-url: http://127.0.0.1:9411/ # 指定了Zipkin服务器的地址
# 不注册成一个服务
discoveryClientEnabled: false
sender:
# 数据传输方式,web 表示以 HTTP 报文的形式向服务端发送数据,还有kafka,ACTIVEMQ,rabbit 等
type: web
重新启动 网关微服务,然后通过网关微服务访问 ProductPageDemo 微服务
访问 zipkin 的 web页面:http://127.0.0.1:9411/
查看数据库对应的表,看是否有数据生成
上图的消耗时间正好和web上面显示的对应
<!--链路追踪-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
<!--通过消息中间件实现链路追踪-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
</dependency>
# 调用链 Sleuth + ZipKin
sleuth:
web:
client:
# 是否启用 webClient
enabled: true
sampler:
probability: 1.0 # 采用比例,默认 0.1 全部采样 1.0
zipkin:
enabled: true
base-url: http://127.0.0.1:9411/ # 指定了Zipkin服务器的地址
# 不注册成一个服务
discoveryClientEnabled: false
sender:
# 数据传输方式,web 表示以 HTTP报文的形式向服务端发送数据,还有kafka,rabbit等
#type: web
type: rabbit
# RabbitMQ 搭配消息总线 Bus
rabbitmq:
host: 192.168.159.133
port: 5672
username: liuyunfei
password: 123456
java -jar .\zipkin-server-2.23.16-exec.jar --STORAGE_TYPE=mysql --MYSQL_HOST=192.168.159.133 --MYSQL_TCP_PORT=3306 --MYSQL_USER=liuyunfei --MYSQL_PASS=Lyf123456! --MYSQL_DB=zipkin --zipkin.collector.rabbitmq.addresses=192.168.159.133 --zipkin.collector.rabbitmq.username=liuyunfei --zipkin.collector.rabbitmq.password=123456
我们下载的 jar 包就是一个 服务端,而我们本地的微服务就是一个 客户端,通过 slenth 和 zipkin 就可以对链路的信息进行记录和处理,然后进行持久化存储,展示,分析等功能