一:基本介绍
分布式链路追踪,听起来很高大上,其实也没什么。 说简单点,分布式系统中,一个请求可能会经过很多个服务。使用sleuth可以在这些服务上打一些日志(不是我们自己打印的业务日志),把这个请求串起来,然后将数据给zipkin进行展示,方面我们查询。 那么,这些日志主要包含什么?
比如:一个请求经过了服务A->B->C,那么这次请求中主要记录的内容有:
- spanId:一个服务就可以算一个span(单元),spanId就是这个单元的唯一标识。 那么,A,B,C都有自己的spanId。
- traceId:请求的全局唯一id, 在每个span上面都是一样的。
- parentId:请求来源的服务id,B的parentId是A的spanId,C的是B的spanId。
- 此外,还有一些其他重要的信息:
- CS :client send/start 客户端/消费者发出⼀个请求,描述的是⼀个span开始时间
- SR: server received/start 服务端/⽣产者接收请求的时间,SR-CS属于请求发送的⽹络延迟
- SS: server send/fifinish 服务端/⽣产者发送应答 ,SS-SR属于服务端消耗时间
- CR:client received/fifinished 客户端/消费者接收应答, CR-SS表示回复需要的时间(响应的⽹络延迟)
Sleuth可以记录⼀个服务请求经过哪些服务、服务处理时⻓等,根据这些,我们能够理清各微服务
间的调⽤关系及进⾏问题追踪分析。
二:搭建使用
sleuth:
1、每个项目都引入sleuth的依赖
<!--链路追踪--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-sleuth</artifactId> </dependency>
2、每个服务的yml中配置日志级别
#分布式链路追踪 logging: level: org.springframework.web.servlet.DispatcherServlet: debug org.springframework.cloud.sleuth: debug
这样,就算接入sleuth完成。 只不过不好观察日志,还需要接入zipkin。Zipkin 包括Zipkin Server和 Zipkin Client两部分,Zipkin Server是⼀个单独的服务,Zipkin Client就是具体的业务微服务。
zipkin-server:
1、创建新项目并引入依赖(数据要存到mysql做持久化,否则重启后数据就没了):
<!--zipkin-server的依赖坐标--> <dependency> <groupId>io.zipkin.java</groupId> <artifactId>zipkin-server</artifactId> <version>2.12.3</version> <exclusions> <!--排除掉log4j2的传递依赖,避免和springboot依赖的⽇ 志组件冲突--> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starterlog4j2</artifactId> </exclusion> </exclusions> </dependency> <!--zipkin-server ui界⾯依赖坐标--> <dependency> <groupId>io.zipkin.java</groupId> <artifactId>zipkin-autoconfigure-ui</artifactId> <version>2.12.3</version> </dependency> <dependency> <groupId>io.zipkin.java</groupId> <artifactId>zipkin-autoconfigure-storage-mysql</artifactId> <version>2.12.3</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.10</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> </dependency>
2、启动类开启:@EnableZipkinServer。 并注入事务管理器:
@Bean public PlatformTransactionManager txManager(DataSource dataSource) { return new DataSourceTransactionManager(dataSource); }
3、yml文件中关闭自动检测,并添加zipkin-server的配置,另外我们需要将信息持久化到db,所以还要添加数据库配置
spring: datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/zipkin?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true&serverTimezone=UTC username: root password: root druid: initialSize: 10 minIdle: 10 maxActive: 30 maxWait: 50000 # 指定zipkin持久化介质为mysql zipkin: storage: type: mysql
4、创建db的表: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-client:1、引入依赖:<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zipkin</artifactId> </dependency>
2、yml添加对zipkin-server的引用# zipkin链路追踪配置 spring: zipkin: base-url: http://localhost:9411 sender: type: web sleuth: sampler: probability: 1 #采样率 1代表100%全采集,默认0.1 10%
最后,启动各服务,就可以访问了: http://localhost:9411/zipkin/