Zipkin分布式服务链路追踪系统,排查日志


Zipkin分布式服务链路追踪系统,排查日志

Zipkin

Zipkin 是一个分布式追踪系统。它有助于收集对服务架构中的延迟问题进行故障排除所需的计时数据。功能包括收集和查找这些数据。
官方网址

为什么使用Zipkin

随着业务越来越复杂,系统也随之进行各种拆分,特别是随着微服务架构和容器技术的兴起,看似简单的一个应用,后台可能有几十个甚至几百个服务在支撑;一个前端的请求可能需要多次的服务调用最后才能完成;当请求变慢或者不可用时,我们无法得知是哪个后台服务引起的,这时就需要解决如何快速定位服务故障点,Zipkin分布式跟踪系统就能很好的解决这样的问题。

三种启动方式(Java启动的实现)

java 启动

    curl -sSL https://zipkin.io/quickstart.sh | bash -s
    java -jar zipkin.jar

springboot :依赖

<dependency>
   <groupId>io.zipkin.java</groupId>
   <artifactId>zipkin-server</artifactId>
</dependency>
<dependency>
   <groupId>io.zipkin.java</groupId>
   <artifactId>zipkin-autoconfigure-ui</artifactId>
</dependency>

默认内存存储

添加mysql 存储

<dependency>
   <groupId>io.zipkin.java</groupId>
   <artifactId>zipkin-autoconfigure-storage-mysql</artifactId>
</dependency>
<dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
   <groupId>com.zaxxer</groupId>
   <artifactId>HikariCP</artifactId>
</dependency>

配置 数据库

#数据库脚本创建地址,当有多个是可使用[x]表示集合第几个元素
spring.datasource.schema[0]=classpath:/sql/zipkin.sql
spring.datasource.name=zipkin
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://local-pc-node1:3306/snjx?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false
spring.datasource.username=snjx
spring.datasource.password=kRqKjGw1s;RH
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.maximum-pool-size=15
spring.datasource.hikari.auto-commit=true
spring.datasource.hikari.idle-timeout=30000
spring.datasource.hikari.pool-name=DatebookHikariCP
spring.datasource.hikari.max-lifetime=1800000
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.connection-test-query=SELECT 1

zipkin.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,
  `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'
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;
 
ALTER TABLE zipkin_spans ADD UNIQUE KEY(`trace_id_high`, `trace_id`, `id`) COMMENT 'ignore insert on duplicate';
ALTER TABLE zipkin_spans ADD INDEX(`trace_id_high`, `trace_id`, `id`) COMMENT 'for joining with zipkin_annotations';
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';
ALTER TABLE zipkin_annotations ADD INDEX(`a_key`) COMMENT 'for getTraces';
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
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;
 
ALTER TABLE zipkin_dependencies ADD UNIQUE KEY(`day`, `parent`, `child`);

###client 端的配置

<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>
#zipkin采样率,默认为0.1,改为1后全采样,但是会降低接口调用效率
spring.sleuth.sampler.percentage=1.0
#服务链路追踪
spring.zipkin.base-url=http://localhost:8867

spring.zipkin.base-url=http://localhost:8867 这个主意不需要添加/zipkin 后缀
在这里插入图片描述
在这里插入图片描述

Zipkin(服务端)包含四个组件:

Zipkin(服务端)包含四个组件,分别是collector,storage,search,Web UI
1)collector信息收集器,作为一个守护进程,它会时刻等待着客户端传递过来的追踪数据,对这些数据进程验证,存储以及创建查询需要的索引
2)storage是存储组件,zipkin默认直接将数据存储在内存中,此外支持使用Cassandra、Elasticsearch和Mysql
3)search是一个查询进程,它提供了简单的JSON API来提供外部调用查询
4)Web UI是zipkin的服务端展示平台,主要调用search提供的接口,用图标将链路信息清晰的展示

基本概念

Trace:一个请求达到应用后所调用的所有服务组成的调用链就像一个树结构(如图),我们追踪这个调用链路得到的这个数结构可以称之为Trace
Span:在一次Trace中,每个服务的每一次调用,就是一个基本工作单元(如图中的每一个树节点),称之为span
每一个span都有一个id作为唯一标识,同样每一次Trace都会生成一个traceID在span中作为追踪评标识,另外再通过一个parentId标明本次调用的发起者(就是发起者的span-id)。当span有了上面三个标识后,就可以很清晰的将多个span进行梳理串联,最终归纳出一条完整的跟踪链路。

工作流程

一个应用的代码发起HTTP get请求,经过Trace框架拦截,然后
把当前调用链的Trace信息添加到HTTP Header里面
记录当前调用的时间戳
发送HTTP请求,把trace相关的header信息携带上
调用结束之后,记录当前调用话费的时间
然后把上面流程产生的 信息汇集成一个span,把这个span信息上传到zipkin的Collector模块

官网的重要信息

跟踪标识符

为了将一组跨度重新组合成一个完整的跟踪,需要三段信息。跟踪标识符可以是 128 位,但跟踪内的跨度标识符始终是 64 位。

跟踪 ID

跟踪的整体 64 或 128 位 ID。跟踪中的每个跨度共享此 ID。

跨度 ID

特定跨度的 ID。这可能与跟踪 ID 相同,也可能不同。

父 ID

这是一个可选的 ID,只会出现在子跨度上。也就是说,没有父 id 的跨度被认为是跟踪的根。

生成标识符

让我们来看看如何识别 Span。
当传入的请求没有附加跟踪信息时,我们会生成一个随机的跟踪 ID 和跨度 ID。跨度 ID 可以重复用作跟踪 ID 的低 64 位,但也可以完全不同。
如果请求已经附加了跟踪信息,则服务应使用该信息作为服务器接收和服务器发送事件与客户端发送和客户端接收事件属于同一范围的一部分
如果服务调用下游服务,则会创建一个新的跨度作为前一个跨度的子项。它由相同的trace id、一个新的span id 来标识,父id 设置为前一个span 的span id。新的跨度 ID 应该是 64 个随机位。
注意如果服务进行多次下游调用,则必须重复此过程。也就是说,每个后续跨度将具有相同的跟踪 ID 和父 id,但是一个新的和不同的跨度 id。

通信跟踪信息

跟踪信息需要在上游和下游服务之间传递,以便重新组装完整的跟踪。需要五项资料:
跟踪 ID
跨度 ID
父 ID
采样 - 让下游服务知道它是否应该记录请求的跟踪信息。
标志 - 提供创建和交流功能标志的能力。这就是我们如何告诉下游服务这是一个“调试”请求。

HTTP 跟踪

HTTP 标头用于传递跟踪信息。
标题的 B3 部分以 Zipkin 的原始名称命名:BigBrotherBird。
Id 被编码为十六进制字符串:
X-B3-TraceId:128 或 64 个低十六进制编码位(必需)
X-B3-SpanId:64 个低十六进制编码位(必需)
X-B3-ParentSpanId:64 个低十六进制编码位(根跨度中不存在)
X-B3-Sampled:布尔值(“1”或“0”,可以不存在)
X-B3-Flags:“1”表示调试(可以不存在)
有关 B3 的更多信息,请参阅其规格。

时间戳和持续时间

跨度记录是将时间信息或元数据结构化并报告给 zipkin。此过程中最重要的部分之一是适当记录时间戳和持续时间。

时间戳是微秒

所有 Zipkin 时间戳都以纪元微秒(而不是毫秒)为单位。此值应使用可用的最精确测量值。例如,clock_gettime 或者简单地将纪元毫秒乘以 1000。时间戳字段存储为 64 位有符号整数,即使负数无效。

微秒精度主要支持“本地跨度”,即进程内操作。例如,通过更高的精度,您可以分辨出其他事情之前发生的事情的细微差别。

所有时间戳都有错误,包括主机之间的时钟偏差以及时间服务向后重置时钟的可能性。因此,跨度应尽可能记录其持续时间。

跨度持续时间也是微秒

虽然可以获得纳秒级精度的计时信息,但 Zipkin 使用微秒级粒度。以下是一些原因:

首先,使用与时间戳相同的单位使数学更容易。例如,如果您正在对跨度进行故障排除,则更容易识别同一单位中的术语。

其次,记录跨度的开销通常是可变的,可能是微秒或更多:建议比开销更高的分辨率可能会分散注意力。

Zipkin 的未来版本可能会重新讨论这个话题,但就目前而言,一切都是微秒。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值