开启springcloud全家桶9:springcloud的分布式链路追踪利器 Sleuth

Posted 黄小斜

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了开启springcloud全家桶9:springcloud的分布式链路追踪利器 Sleuth相关的知识,希望对你有一定的参考价值。

一、概述

软件项目随着业务发展,一个单体的应用的问题会暴露出来,各个开发人员开发不同的功能模块,造成代码冲突,单体应用上线必须所有功能一起上线,风险较大。这时项目必然需要被拆分,拆分为一个个独立的应用服务,拆分后会导致系统服务间调用链路愈发复杂。

此时,一个前端请求可能最终需要调用多个后端服务才能完成实现,当整个请求不可用出现问题时,我们是没有办法判断请求是由哪个后端服务引发问题,这时我们需要快速定位故障点,找到调用异常的服务,跟进一个请求到底有哪些服务参与,参与顺序是怎样,从而达到每个请求的步骤清晰可见。于是就有了分布式系统调用跟踪的需求。

 

目前,链路追踪组件有Google的Dapper,Twitter 的Zipkin,以及阿里的Eagleeye (鹰眼)等,它们都是非常优秀的链路追踪开源组件。

这些开源组件都是基于Google的Dapper。 Google在2010年发表了论文《Dapper, a Large-Scale Distributed Systems Tracing Infrastructure》,这篇文章是业内实现链路追踪的标杆和理论基础,具有非常大的参考价值。

 

二、Spring Cloud Sleuth

1、基本概念

微服务跟踪(sleuth)其实是一个工具,它在整个分布式系统中能跟踪一个用户请求的过程(包括数据采集,数据传输,数据存储,数据分析,数据可视化),捕获这些跟踪数据,就能构建微服务的整个调用链的视图,这是调试和监控微服务的关键工具。

Spring Cloud Sleuth有4个特点

 

 

 

 

对于开发者来说,如果想要封装其他的框架,就需要对跟踪的数据模型有一个清晰的认识:

Span:基本工作单元,发送一个远程调度任务 就会产生一个Span,就是每个方法调用的id。

 

Trace :一组代表一次用户请求所包含的spans,其中根span只有一个。

 

Annotation:包括一个值,时间戳,主机名。用来及时记录一个事件的,一些核心注解用来定义一个请求的开始和结束 。这些注解包括以下:

cs - Client Sent -客户端发送一个请求,这个注解描述了这个Span的开始

sr - Server Received -服务端获得请求并准备开始处理它,如果将其sr减去cs时间戳便可得到网络传输的时间。

ss - Server Sent (服务端发送响应)–该注解表明请求处理的完成(当请求返回客户端),如果ss的时间戳减去sr时间戳,就可以得到服务器请求的时间。

cr - Client Received (客户端接收响应)-此时Span的结束,如果cr的时间戳减去cs时间戳便可以得到整个请求所消耗的时间。

 

2、详细说明

一般情况下,分布式服务跟踪系统,主要包括有三部分:数据收集、数据存储和数据展示。根据系统大小不同,每一部分的结构又有一定变化。譬如,对于大规模分布式系统,数据存储可分为实时数据和全量数据两部分,实时数据用于故障排查(troubleshooting),全量数据用于系统优化;数据收集除了支持平台无关和开发语言无关系统的数据收集,还包括异步数据收集(需要跟踪队列中的消息,保证调用的连贯性),以及确保更小的侵入性;数据展示又涉及到数据挖掘和分析。虽然每一部分都可能变得很复杂,但基本原理都类似。

 

 

 

服务追踪的追踪单元是从客户发起请求(request)抵达被追踪系统的边界开始,到被追踪系统向客户返回响应(response)为止的过程,称为一个“trace”。每个 trace 中会调用若干个服务,为了记录调用了哪些服务,以及每次调用的消耗时间等信息,在每次调用服务时,埋入一个调用记录,称为一个“span”。这样,若干个有序的 span 就组成了一个 trace。在系统向外界提供服务的过程中,会不断地有请求和响应发生,也就会不断生成 trace,把这些带有span 的 trace 记录下来,就可以描绘出一幅系统的服务拓扑图。附带上 span 中的响应时间,以及请求成功与否等信息,就可以在发生问题的时候,找到异常的服务;根据历史数据,还可以从系统整体层面分析出哪里性能差,定位性能优化的目标。

 

Spring Cloud Sleuth为服务之间调用提供链路追踪。通过Sleuth可以很清楚的了解到一个服务请求经过了哪些服务,每个服务处理花费了多长。从而让我们可以很方便的理清各微服务间的调用关系。此外Sleuth可以帮助我们:

 

耗时分析: 通过Sleuth可以很方便的了解到每个采样请求的耗时,从而分析出哪些服务调用比较耗时;

可视化错误: 对于程序未捕捉的异常,可以通过集成Zipkin服务界面上看到;

链路优化: 对于调用比较频繁的服务,可以针对这些服务实施一些优化措施。

spring cloud sleuth可以结合zipkin,将信息发送到zipkin,利用zipkin的存储来存储信息,利用zipkin ui来展示数据。

 
1.介绍
Spring Cloud Sleuth为Spring Cloud实现了分布式跟踪解决方案。

1.1术语
Spring Cloud Sleuth借用了Google

Dapper的术语。

Span:工作的基本单位。例如,发送RPC是一个新的跨度,就像发送响应到RPC一样。Span是由一个唯一的64位ID来标识的,而另一个64位ID用于跟踪。span还具有其他数据,如描述、时间戳事件、键值标注(标记)、导致它们的span的ID和进程ID(通常是IP地址)。

可以启动和停止跨度,并跟踪其时间信息。 创建跨度后,必须在将来的某个时刻停止它。

启动跟踪的初始范围称为根跨度。 该范围的ID值等于跟踪ID。

Trace:一组span形成树状结构。 例如,如果运行分布式大数据存储,则可能由PUT请求形成跟踪。

注解:用于及时记录事件的存在。 使用Brave工具,我们不再需要为Zipkin设置特殊事件,以了解客户端和服务器是谁,请求开始的位置以及结束位置。

cs:客户已发送。 客户提出了请求。 此注释表示跨度的开始。
sr:Server Received:服务器端获得请求并开始处理它。 从此时间戳中减去cs时间戳会显示网络延迟。
ss:服务器已发送。 在完成请求处理时(当响应被发送回客户端时)注释。 从此时间戳中减去sr时间戳会显示服务器端处理请求所需的时间。
cr:客户收到了。 表示跨度的结束。 客户端已成功收到服务器端的响应。 从此时间戳中减去cs时间戳会显示客户端从服务器接收响应所需的全部时间。

下图显示了Span和Trace在系统中的外观以及Zipkin注解:

注释的每种颜色表示跨度(有七个跨度 - 从A到G)。 请考虑以下注释:

此注释表示当前跨度的Trace Id设置为X,Span Id设置为D.此外,还发生了Client Sent事件。

Trace Id = X
Span Id = D
Client Sent
下图显示了跨度的父子关系:

1.2目的
以下部分参考上图中显示的示例。

1.2.1使用Zipkin进行分布式跟踪
这个例子有七个跨度。如果你在Zipkin中查看跟踪,你可以在第二个跟踪中看到这个数字,如下图所示:

 

但是,如果选择特定跟踪,则可以看到四个跨度,如下图所示:

选择特定跟踪时,您会看到合并的跨度。 这意味着,如果通过Server Received和Server Sent或Client Received和Client Sent annotations向Zipkin发送了两个跨度,则它们将显示为单个跨度。

在这种情况下,为什么七个和四个跨度之间存在差异?

两个跨度来自http:/start span。它具有Server Received(sr)和Server Sent(ss)注释。
从Service1到service2到http:/foo端点的RPC调用有两个跨度。客户端发送(cs)和客户端接收(cr)事件发生在service1端。 Server Received(sr)和Server Sent(ss)事件发生在service2端。这两个跨度形成一个与RPC调用相关的逻辑跨度。
两个跨度来自从service2到service3的RPC调用到http:/bar端点。客户端发送(cs)和客户端接收(cr)事件发生在service2端。 Server Received(sr)和Server Sent(ss)事件发生在service3端。这两个跨度形成一个与RPC调用相关的逻辑跨度。
两个跨度来自从service2到service4的RPC调用到http:/baz端点。客户端发送(cs)和客户端接收(cr)事件发生在service2端。服务器已接收(sr)和服务器已发送(ss)事件发生在service4端。这两个跨度形成一个与RPC调用相关的逻辑跨度。
因此,如果我们计算物理跨度,我们有一个来自http:/ start,两个来自service1调用service2,两个来自service2调用service3,两个来自service2调用service4。 总之,我们总共有七个跨度。

从逻辑上讲,我们看到了四个总Spans的信息,因为我们有一个与service1的传入请求相关的span和三个与RPC调用相关的spans。

1.2.2 可视化错误
Zipkin允许您可视化Trace中的错误。 当抛出一个异常并且没有被捕获时,我们在跨度上设置了适当的标签,然后Zipkin可以正确地着色。 您可以在Trace列表中看到一条红色的迹线。 这似乎是因为抛出异常。

如果单击该跟踪,您将看到类似的图片,如下所示:

跨度显示错误的原因以及与之相关的整个堆栈跟踪。

1.2.3日志相关
当使用grep扫描一个等于(例如)2485ec27856c56f4的Trace ID来读取这四个应用程序的日志时,您会得到如下输出:

service1.log:2016-02-26 11:15:47.561  INFO [service1,2485ec27856c56f4,2485ec27856c56f4,true] 68058 --- [nio-8081-exec-1] i.s.c.sleuth.docs.service1.Application   : Hello from service1. Calling service2
service2.log:2016-02-26 11:15:47.710  INFO [service2,2485ec27856c56f4,9aa10ee6fbde75fa,true] 68059 --- [nio-8082-exec-1] i.s.c.sleuth.docs.service2.Application   : Hello from service2. Calling service3 and then service4
service3.log:2016-02-26 11:15:47.895  INFO [service3,2485ec27856c56f4,1210be13194bfe5,true] 68060 --- [nio-8083-exec-1] i.s.c.sleuth.docs.service3.Application   : Hello from service3
service2.log:2016-02-26 11:15:47.924  INFO [service2,2485ec27856c56f4,9aa10ee6fbde75fa,true] 68059 --- [nio-8082-exec-1] i.s.c.sleuth.docs.service2.Application   : Got response from service3 [Hello from service3]
service4.log:2016-02-26 11:15:48.134  INFO [service4,2485ec27856c56f4,1b1845262ffba49d,true] 68061 --- [nio-8084-exec-1] i.s.c.sleuth.docs.service4.Application   : Hello from service4
service2.log:2016-02-26 11:15:48.156  INFO [service2,2485ec27856c56f4,9aa10ee6fbde75fa,true] 68059 --- [nio-8082-exec-1] i.s.c.sleuth.docs.service2.Application   : Got response from service4 [Hello from service4]
service1.log:2016-02-26 11:15:48.182  INFO [service1,2485ec27856c56f4,2485ec27856c56f4,true] 68058 --- [nio-8081-exec-1] i.s.c.sleuth.docs.service1.Application   : Got response from service2 [Hello from service2, response from service3 [Hello from service3] and from service4 [Hello from service4]]
如果使用日志聚合工具(例如Kibana,Splunk等),则可以对发生的事件进行排序。 Kibana的一个例子类似于下图:

如果要使用Logstash,以下列表显示了Logstash的Grok模式:

Logstash是一个具有实时流水线功能的开源数据收集引擎。 Logstash可以动态统一来自不同来源的数据,并将数据标准化为您选择的目的地。 为各种高级下游分析和可视化用例清理和民主化所有数据。

虽然Logstash最初推动了日志收集的创新,但其功能远远超出了该用例。 任何类型的事件都可以通过广泛的输入,过滤和输出插件进行丰富和转换,许多本机编解码器进一步简化了摄取过程。 Logstash通过利用更大容量和更多数据来加速您的见解。

Grok是Logstash过滤器的基础,可以无处不在地用于从非结构化数据中获取结构。 享受丰富的集成模式,旨在帮助快速解决Web,系统,网络和其他类型的事件格式。

filter {
       # pattern matching logback pattern
       grok {
              match => { "message" => "%{TIMESTAMP_ISO8601:timestamp}\\s+%{LOGLEVEL:severity}\\s+\\[%{DATA:service},%{DATA:trace},%{DATA:span},%{DATA:exportable}\\]\\s+%{DATA:pid}\\s+---\\s+\\[%{DATA:thread}\\]\\s+%{DATA:class}\\s+:\\s+%{GREEDYDATA:rest}" }
       }
}
 注意:如果要将Grok与Cloud Foundry中的日志一起使用,则必须使用以下模式:

filter {
       # pattern matching logback pattern
       grok {
              match => { "message" => "(?m)OUT\\s+%{TIMESTAMP_ISO8601:timestamp}\\s+%{LOGLEVEL:severity}\\s+\\[%{DATA:service},%{DATA:trace},%{DATA:span},%{DATA:exportable}\\]\\s+%{DATA:pid}\\s+---\\s+\\[%{DATA:thread}\\]\\s+%{DATA:class}\\s+:\\s+%{GREEDYDATA:rest}" }
       }
}
使用Logstash的JSON Logback

通常,您不希望将日志存储在一个文本文件中,而是存储在一个JSON文件中,logstash可以立即选择该文件。为此,您必须执行以下操作(为了可读性,我们传递groupId:artifactId:version notation中的依赖关系)。

依赖关系设置

1.确保Logback位于类路径上(ch.qos.logback:logback-core)。

    <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>${logback.version}</version>
        </dependency>
2.添加Logstash Logback编码。 例如,要使用版本4.6,请添加net.logstash.logback:logstash-logback-encoder:4.6。

        <dependency>
            <groupId>net.logstash.logback</groupId>
            <artifactId>logstash-logback-encoder</artifactId>
            <version>4.6</version>
        </dependency>
3.增加Logback

请考虑以下Logback配置文件示例(名为logback-spring.xml)。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
    ​
    <springProperty scope="context" name="springAppName" source="spring.application.name"/>
    <!-- Example for logging into the build folder of your project -->
    <property name="LOG_FILE" value="${BUILD_FOLDER:-build}/${springAppName}"/>​
 
    <!-- You can override this to have a custom pattern -->
    <property name="CONSOLE_LOG_PATTERN"
              value="%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
 
    <!-- Appender to log to console -->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <!-- Minimum logging level to be presented in the console logs-->
            <level>DEBUG</level>
        </filter>
        <encoder>
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
            <charset>utf8</charset>
        </encoder>
    </appender>
 
    <!-- Appender to log to file -->​
    <appender name="flatfile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_FILE}</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.gz</fileNamePattern>
            <maxHistory>7</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
            <charset>utf8</charset>
        </encoder>
    </appender>
    ​
    <!-- Appender to log to file in a JSON format -->
    <appender name="logstash" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_FILE}.json</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_FILE}.json.%d{yyyy-MM-dd}.gz</fileNamePattern>
            <maxHistory>7</maxHistory>
        </rollingPolicy>
        <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
            <providers>
                <timestamp>
                    <timeZone>UTC</timeZone>
                </timestamp>
                <pattern>
                    <pattern>
                        {
                        "severity": "%level",
                        "service": "${springAppName:-}",
                        "trace": "%X{X-B3-TraceId:-}",
                        "span": "%X{X-B3-SpanId:-}",
                        "parent": "%X{X-B3-ParentSpanId:-}",
                        "exportable": "%X{X-Span-Export:-}",
                        "pid": "${PID:-}",
                        "thread": "%thread",
                        "class": "%logger{40}",
                        "rest": "%message"
                        }
                    </pattern>
                </pattern>
            </providers>
        </encoder>
    </appender>
    ​
    <root level="INFO">
        <appender-ref ref="console"/>
        <!-- uncomment this to have also JSON logs -->
        <!--<appender-ref ref="logstash"/>-->
        <!--<appender-ref ref="flatfile"/>-->
    </root>
</configuration>
那个Logback配置文件:

将来自应用程序的信息以JSON格式记录到build/${spring.application.name}.json文件中。(在项目中)
已注释掉两个额外的appender:控制台和标准日志文件。
具有与上一节中介绍的相同的日志记录模式。
如果使用自定义logback-spring.xml,则必须在bootstrap.properties(yml)而不是应用application.properties(yml)中传递spring.application.name。 否则,您的自定义logback文件无法正确读取该属性。

1.3为项目添加Sleuth
重要
要确保您的应用程序名称在Zipkin中正确显示,请在bootstrap.yml中设置spring.application.name属性。

1.3.1只有Sleuth
<dependencyManagement> 
      <dependencies>
          <dependency>
              <groupId>org.springframework.cloud</groupId>
              <artifactId>spring-cloud-dependencies</artifactId>
              <version>${release.train.version}</version>
              <type>pom</type>
              <scope>import</scope>
          </dependency>
      </dependencies>
</dependencyManagement>
 
<dependency> 
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
我们建议您通过Spring BOM添加依赖关系管理,这样您就无需自行管理版本。【springboot springcloud推荐的添加方式】

将依赖项添加到spring-cloud-starter-sleuth。

1.3.2通过HTTP与Zipkin的Sleuth
<dependencyManagement> 
      <dependencies>
          <dependency>
              <groupId>org.springframework.cloud</groupId>
              <artifactId>spring-cloud-dependencies</artifactId>
              <version>${release.train.version}</version>
              <type>pom</type>
              <scope>import</scope>
          </dependency>
      </dependencies>
</dependencyManagement>
 
<dependency> 
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
我们建议您通过Spring BOM添加依赖关系管理,这样您就无需自行管理版本。
将依赖项添加到spring-cloud-starter-zipkin。

如果spring-cloud-sleuth-zipkin可用,则该应用程序将通过HTTP生成并收集与Zipkin兼容的跟踪。 默认情况下,它将它们发送到localhost(端口9411)上的Zipkin收集器服务。 使用spring.zipkin.baseUrl配置服务的位置。

注意:您可以设置logging.level.org.springframework.web.servlet.DispatcherServlet = DEBUG,而不是在处理程序中明确记录请求。

注意:如果使用Zipkin,请通过设置(对于2.0.x)spring.sleuth.sampler.probability或(直到2.0.x)spring.sleuth.sampler.percentage(默认值:0.1,这是 10%,Sleuth会忽略掉大量的span)。 否则,您可能会认为侦探无效,因为它忽略了一些跨度。

注意:设置spring.application.name = bar(例如)以查看服务名称以及跟踪和跨度ID。

1.3.3在RabbitMQ或Kafka上使用Zipkin的Sleuth
如果您想使用RabbitMQ或Kafka而不是HTTP,请添加spring-rabbit或spring-kafka依赖项。默认的目的地名是zipkin。
如果使用Kafka,则必须设置属性spring.zipkin.sender。类型相应的属性:

spring.zipkin.sender.type: kafka
警告:spring-cloud-sleuth-stream已弃用且与这些目标不兼容。

如果你想通过RabbitMQ上的Sleuth,添加spring-cloud-starter-zipkin和spring-rabbit依赖项。

Maven

<dependencyManagement> 
      <dependencies>
          <dependency>
              <groupId>org.springframework.cloud</groupId>
              <artifactId>spring-cloud-dependencies</artifactId>
              <version>${release.train.version}</version>
              <type>pom</type>
              <scope>import</scope>
          </dependency>
      </dependencies>
</dependencyManagement>
 
<dependency> 
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
<dependency> 
    <groupId>org.springframework.amqp</groupId>
    <artifactId>spring-rabbit</artifactId>
</dependency>
 

我们建议您通过Spring BOM添加依赖项管理,这样您就不需要自己管理版本。
将依赖项添加到spring-cloud-starter-zipkin。这样,所有嵌套的依赖项都会被下载。
要自动配置RabbitMQ,请添加spring-rabbit依赖项。
2.发送span到Zipkin
默认情况下,如果将spring-cloud-starter-zipkin添加为项目的依赖项,则当跨度关闭时,它将通过HTTP发送到Zipkin。 通信是异步的。 您可以通过设置spring.zipkin.baseUrl属性来配置URL,如下所示:

spring.zipkin.baseUrl: http://192.168.99.100:9411/
如果您想通过服务发现找到Zipkin,您可以在URL中传递Zipkin的服务ID,如以下zipkinserver服务ID示例所示:

spring.zipkin.baseUrl: http://zipkinserver/
要禁用此功能,只需将spring.zipkin.discoveryClientEnabled设置为false。

启用Discovery Client功能后,Sleuth使用LoadBalancerClient查找Zipkin Server的URL。 这意味着您可以设置负载平衡配置,例如 通过功能区

zipkinserver:
  ribbon:
    ListOfServers: host1,host2
如果您在类路径上一起使用web,rabbit或kafka,则可能需要选择要将spans发送到zipkin的方法。 为此,请将web,rabbit或kafka设置为spring.zipkin.sender.type属性。 以下示例显示为web设置发件人类型:

spring.zipkin.sender.type: web
3.Span数据作为消息
您可以通过将spring-cloud-sleuth-stream jar包含为依赖项来累积和发送Spring Cloud的跨度数据,并添加Channel Binder实现(例如,用于RabbitMQ的spring-cloud-starter-stream-rabbit或Kafka的spring-cloud-starter-stream-kafka)。 这将自动将您的应用程序转换为有效负载类型为Spans的消息的生成者。

Zipkin消费者

有一个特殊的便利注释,用于为Span数据设置消息使用者并将其推送到Zipkin SpanStore。

@SpringBootApplication
@EnableZipkinStreamServer
public class Consumer {
    public static void main(String[] args) {
        SpringApplication.run(Consumer.class, args);
    }
}
将通过Spring Cloud Stream Binder监听您提供的任何传输的Span数据(例如,包括用于RabbitMQ的spring-cloud-starter-stream-rabbit,以及Redis和Kafka的类似启动器)。 如果添加以下UI依赖项

<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-autoconfigure-ui</artifactId>
默认的SpanStore是内存中的(适用于演示和快速入门)。 对于更强大的解决方案,您可以将mysql和spring-boot-starter-jdbc添加到类路径中,并通过配置启用JDBC SpanStore。

spring:
  rabbitmq:
    host: ${RABBIT_HOST:localhost}
  datasource:
    schema: classpath:/mysql.sql
    url: jdbc:mysql://${MYSQL_HOST:localhost}/test
    username: root
    password: root
# Switch this on to create the schema on startup:
    initialize: true
    continueOnError: true
  sleuth:
    enabled: false
zipkin:
  storage:
    type: mysql
mysql脚本 

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`);
@EnableZipkinStreamServer也使用@EnableZipkinServer进行注释,因此该过程还将公开标准的Zipkin服务器端点,以便通过HTTP收集跨度,以及在Zipkin Web UI中进行查询。 

4.Zipkin Stream Span消费者
重要:建议使用Zipkin对基于消息的跨度发送的本机支持。 从Edgware版本开始,不推荐使用Zipkin Stream服务器。 在Finchley发布中,它已被删除。
————————————————
版权声明:本文为CSDN博主「盲目的拾荒者」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/niugang0920/article/details/81259990

以上是关于开启springcloud全家桶9:springcloud的分布式链路追踪利器 Sleuth的主要内容,如果未能解决你的问题,请参考以下文章

开启springcloud全家桶1:springcloud套餐简介

开启springcloud全家桶10:用SpringCloud Admin快速搭建你的监控中心

开启springcloud全家桶3:服务注册中心erueka原理与实践

开启springcloud全家桶2:初探Hystrix原理与实践

开启springcloud全家桶5:探索负载均衡组件 Ribbon实现与原理

开启springcloud全家桶8:配置中心的好搭档 Spring Cloud Bus 消息总线