Spring Cloud Sleuth原理解析

1、什么是Spring Cloud Sleuth?

Spring Cloud Sleuth 主要功能就是在分布式系统中提供追踪解决方案。Spring Cloud Sleuth是对Zipkin的一个封装,对于Span、Trace等信息的生成、接入HTTP Request,以及向Zipkin Server发送采集信息等全部自动完成。

spring cloud提供了spring-cloud-sleuth-zipkin来方便集成zipkin实现(指的是Zipkin Client,而不是Zipkin服务器),该jar包可以通过spring-cloud-starter-zipkin依赖来引入。

Zipkin分布式跟踪系统;它可以帮助收集时间数据,解决在microservice架构下的延迟问题;它管理这些数据的收集和查找;Zipkin的设计是基于谷歌的Google Dapper论文。
每个应用程序向Zipkin报告定时数据,Zipkin UI呈现了一个依赖图表来展示多少跟踪请求经过了每个应用程序;如果想解决延迟问题,可以过滤或者排序所有的跟踪请求,并且可以查看每个跟踪请求占总跟踪时间的百分比。
其基本思路是在服务调用的请求和响应中加入ID,标明上下游请求的关系。利用这些信息,可以可视化地分析服务调用链路和服务间的依赖关系。

分布式系统加微服务架构已成为目前最流行的框架,在此之上,设想一个请求从服务A到服务B,经过负载均衡在不同node上调用,一旦出现错误,如何快速的定位问题发生的node和服务成为最麻烦得问题,所以最终微服务的链路显得尤为重要,Spring cloud 提供了 Sleuth完成分布式系统的链路追踪解决方案。

复杂的微服务调用

此外,设想这么一种情况,如果你的微服务数量逐渐增大,服务间的依赖关系越来越复杂,怎么分析它们之间的调用关系及相互的影响?spring boot对zipkin的自动配置可以使得所有RequestMapping匹配到的endpoints得到监控,以及强化了RestTemplate,对其加了一层拦截器,使得由它发起的http请求也同样被监控。Zipkin可以结合压力测试工具一起使用,分析系统在大压力下的可用性和性能。而Spring cloud sleuth可以很简单与Zipkin集成。

目前市场上的链路追踪组件有Google的Dapper,Twitter 的Zipkin,以及阿里的Eagleeye (鹰眼)等

2、术语

Spring Cloud Sleuth采用的是Google的开源项目Dapper的专业术语。

  • Span:基本工作单元,例如,在一个新建的span中发送一个RPC等同于发送一个回应请求给RPC,span通过一个64位ID唯一标识,trace以另一个64位ID表示,span还有其他数据信息,比如摘要、时间戳事件、关键值注释(tags)、span的ID、以及进度ID(通常是IP地址)
    span在不断的启动和停止,同时记录了时间信息,当你创建了一个span,你必须在未来的某个时刻停止它。

  • Trace:一系列spans组成的一个树状结构,例如,如果你正在跑一个分布式大数据工程,你可能需要创建一个trace。

  • Annotation:用来及时记录一个事件的存在,一些核心annotations用来定义一个请求的开始和结束

    • cs - Client Sent -客户端发起一个请求,这个annotion描述了这个span的开始
    • sr - Server Received -服务端获得请求并准备开始处理它,如果将其sr减去cs时间戳便可得到网络延迟
    • ss - Server Sent -注解表明请求处理的完成(当请求返回客户端),如果ss减去sr时间戳便可得到服务端需要的处理请求时间
    • cr - Client Received -表明span的结束,客户端成功接收到服务端的回复,如果cr减去cs时间戳便可得到客户端从服务端获取回复的所有所需时间

Zipkin原理

跟踪器(Tracer)位于你的应用程序中,并记录发生的操作的时间和元数据,提供了相应的类库,对用户的使用来说是透明的,收集的跟踪数据称为Span;将数据发送到Zipkin的仪器化应用程序中的组件称为Reporter,Reporter通过几种传输方式之一将追踪数据发送到Zipkin收集器(collector),然后将跟踪数据进行存储(storage),由API查询存储以向UI提供数据。

Zipkin原理

1.Trace
Zipkin使用Trace结构表示对一次请求的跟踪,一次请求可能由后台的若干服务负责处理,每个服务的处理是一个Span,Span之间有依赖关系,Trace就是树结构的Span集合;

2.Span
每个服务的处理跟踪是一个Span,可以理解为一个基本的工作单元,包含了一些描述信息:id,parentId,name,timestamp,duration,annotations等,例如:

{
      "traceId": "bd7a977555f6b982",
      "name": "get-traces",
      "id": "ebf33e1a81dc6f71",
      "parentId": "bd7a977555f6b982",
      "timestamp": 1458702548478000,
      "duration": 354374,
      "annotations": [
        {
          "endpoint": {
            "serviceName": "zipkin-query",
            "ipv4": "192.168.1.2",
            "port": 9411
          },
          "timestamp": 1458702548786000,
          "value": "cs"
        }
      ],
      "binaryAnnotations": [
        {
          "key": "lc",
          "value": "JDBCSpanStore",
          "endpoint": {
            "serviceName": "zipkin-query",
            "ipv4": "192.168.1.2",
            "port": 9411
          }
        }
      ]
}
  • traceId:标记一次请求的跟踪,相关的Spans都有相同的traceId;
  • id:span id;
  • name:span的名称,一般是接口方法的名称;
  • parentId:可选的id,当前Span的父Span id,通过parentId来保证Span之间的依赖关系,如果没有parentId,表示当前* Span为根Span;
  • timestamp:Span创建时的时间戳,使用的单位是微秒(而不是毫秒),所有时间戳都有错误,包括主机之间的时钟偏差* 以及时间服务重新设置时钟的可能性,出于这个原因,Span应尽可能记录其duration;
  • duration:持续时间使用的单位是微秒(而不是毫秒);
  • annotations:注释用于及时记录事件;有一组核心注释用于定义RPC请求的开始和结束;
    1、cs:Client Send,客户端发起请求;
    2、sr:Server Receive,服务器接受请求,开始处理;
    3、ss:Server Send,服务器完成处理,给客户端应答;
    4、cr:Client Receive,客户端接受应答从服务器;
  • binaryAnnotations:二进制注释,旨在提供有关RPC的额外信息。
3、入门示例

下载

1、容器
Docker Zipkin项目能够建立docker镜像,提供脚本和docker-compose.yml来启动预构建的图像。最快的开始是直接运行最新镜像:

docker run -d -p 9411:9411 openzipkin/zipkin

2、下载jar
如果你有java 8或更高版本,上手最快的方法是把新版本作为一个独立的可执行jar,Zipkin使用springboot来构建的:

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

3、下载源代码运行
Zipkin可以从源运行,如果你正在开发新的功能。要实现这一点,需要获取Zipkin的源代码并构建它。

# get the latest source
git clone https://github.com/openzipkin/zipkin
cd zipkin
# Build the server and also make its dependencies
./mvnw -DskipTests --also-make -pl zipkin-server clean install
# Run the server
java -jar ./zipkin-server/target/zipkin-server-*exec.jar

访问

zipkin使用springboot,并且启动的端口为9411,然后我们通过浏览器访问,效果如下:
Zipkin

详细参考:Quickstart · OpenZipkin

配置
1、新建一个普通的Spring Boot项目,工程取名为server-zipkin,在其pom引入依赖:



    4.0.0

    com.dxz.serverzipkin
    serverzipkin
    0.0.1-SNAPSHOT
    jar

    server-zipkin
    Demo project for Spring Boot

    
        org.springframework.boot
        spring-boot-starter-parent
        1.3.5.RELEASE   
         
    
    
        
        UTF-8
        1.8
    
    
        
        
            io.zipkin.java
            zipkin-server
        

        
            io.zipkin.java
            zipkin-autoconfigure-ui
        
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
    

    
    
        
            
                org.springframework.cloud
                spring-cloud-starter-parent
                Brixton.SR3   
                pom
                import
            
        
    

    
        
            
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    

2在其程序入口类, 加上注解@EnableZipkinServer,开启ZipkinServer的功能:

package com.dxz.serverzipkin;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import zipkin.server.EnableZipkinServer;

@EnableZipkinServer
@SpringBootApplication
public class ServerZipkinApplication {

    public static void main(String[] args) {
        SpringApplication.run(ServerZipkinApplication.class, args);
    }
}

3在配置文件application.yml指定,配置Zipkin服务端口、名称等:

server.port=9411
spring.application.name=my-zipkin-server

4完成一次调用,便可以看到链路追踪结果。


find trace

查看依赖

改进

其实,我们仔细想想也可以总结出这种方式的几种缺陷:
缺陷1:zipkin客户端向zipkin-server程序发送数据使用的是http的方式通信,每次发送的时候涉及到连接和发送过程。
缺陷2:当我们的zipkin-server程序关闭或者重启过程中,因为客户端收集信息的发送采用http的方式会被丢失。

针对以上两个明显的缺陷,改进的办法是:
1、通信采用socket或者其他效率更高的通信方式。
2、客户端数据的发送尽量减少业务线程的时间消耗,采用异步等方式发送收集信息。
3、客户端与zipkin-server之间增加缓存类的中间件,例如redis、MQ等,在zipkin-server程序挂掉或重启过程中,客户端依旧可以正常的发送自己收集的信息。

1、将HTTP通信改成MQ异步方式通信

springcloud官方按照传输方式分成了三种启动服务端的方式:

  1. Sleuth with Zipkin via HTTP,
  2. Sleuth with Zipkin via Spring Cloud Stream,
  3. Spring Cloud Sleuth Stream Zipkin Collector。

只需要添加相应的依赖,之后配置相应的注解,如@EnableZipkinStreamServer即可。具体配置参考官方文档:
(http://cloud.spring.io/spring-cloud-static/spring-cloud-sleuth/1.2.1.RELEASE/#_adding_to_the_project)

1、加入依赖
要将http方式改为通过MQ通信,我们要将依赖的原来依赖的io.zipkin.java:zipkin-server换成spring-cloud-sleuth-zipkin-stream和spring-cloud-starter-stream-rabbit
2、在启动类中开启Stream通信功能
3、配置消息中间件rabbit mq地址等信息

至此,ZipkinServer配置完成,下面是Zipkin客户端的配置

1、将原来的spring-cloud-starter-zipkin替换为如下依赖即可


org.springframework.cloud
spring-cloud-sleuth-zipkin-stream


org.springframework.cloud
spring-cloud-starter-stream-rabbit

 

org.springframework.cloud
spring-cloud-starter-sleuth

2、此外,在配置文件中也加上连接MQ的配置

#连接rabbitmq服务器配置
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest

经过上面的配置,我们还需要安装Rabbit MQ,而且sleuth被改造成了,


mq版本zipkin

持久化

Zipkin目前只支持mysql数据库,ZipkinServer服务做如下修改,其它服务不需做任何修改,
1、加入数据库依赖


mysql
mysql-connector-java


org.springframework.boot
spring-boot-starter-jdbc

2、配置数据库属性

#zipkin数据保存到数据库中需要进行如下配置
#表示当前程序不使用sleuth
spring.sleuth.enabled=false
#表示zipkin数据存储方式是mysql
zipkin.storage.type=mysql
 
#数据库脚本创建地址,当有多个时可使用[x]表示集合第几个元素,脚本可到官网下载,需要先手动到数据库执行
spring.datasource.schema[0]=classpath:/zipkin.sql
 
#spring boot数据源配置
spring.datasource.url=jdbc:mysql://localhost:3306/zipkin?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.initialize=true
spring.datasource.continue-on-error=true

3、zipkin.sql,数据库脚本文件放到resources目录下,且需要先手动到数据库执行一次。
至此,ZipkinServer采用数据库存储配置完成。

测试时发现,要用MQ异步方式通信的pom.xml配置及@EnableZipkinStreamServer注解才可以(@EnableZipkinServer貌似只能保存到内存),否则启动报错,不明白为什么。

elasticsearch持久化
存储在mysql,实际生产过程中调用数据量非常的大,mysql存储并不是很好的选择,这时我们可以采用elasticsearch进行存储,配置过程也很简单
1、mysql依赖改成elasticsearch依赖
2、数据库配置改成elasticsearch配置
3、安装elasticsearch

copy 自:服务链路追踪(Spring Cloud Sleuth) - duanxz - 博客园 (cnblogs.com)

你可能感兴趣的:(Spring Cloud Sleuth原理解析)