Spring Cloud Sleuth (1)-入门篇

来源:互联网 发布:mac 新系统打不开u盘 编辑:程序博客网 时间:2024/06/08 18:02

在微服务框架中,一个由客户端发起的请求在后端系统中会经过多个不同的的服务节点调用来协同产生最后的请求结果,每一个前段请求都会形成一条复杂的分布式服务调用链路,链路中的任何一环出现高延时或错误都会引起整个请求最后的失败。

Spring Cloud Sleuth提供了一套完整的服务跟踪的解决方案。

 

跟踪原理:pom中依赖spring-cloud-starter-sleuth包后,每次链路请求都会添加一串追踪信息,格式是[server-name, main-traceId,sub-spanId,boolean]

第一个参数:服务结点名称;

第二个参数:一条链路唯一的ID,叫TraceID

第三个参数:链路中每一环的ID,叫做SpanID

第四个参数:是否将信息输出到Zipkin等服务收集和展示。

 

这种机制是如何实现的呢?我们知道Spring Framework微服务是通过http协议通信的(与之对立的是dubboRPC方式),所以Sleuth的实现也是基于http的,又不能影响正常的业务传递,所以能做文章的只能在httpheader上。

        Sleuth会在每个请求的header上添加跟踪需求的重要信息,例如:

X-B3-TraceId:对应TraceID

X-B3-SpanId:对应SpanID

X-B3-ParentSpanId:前面一环的SpanID

X-B3-Sampled:是否被选中抽样输出;

X-Span-Name:工作单元名称。

更多的内容可以参考Spring中的源码:org.springframework.cloud.sleuth.Span

 

再回头看Spring Cloud Sleuth要解决的问题:

1, 服务追踪,一条链路上的所有处理给统一的TraceID,通过这个唯一标识就可以找到完整的处理链路。

2, 每一环的微服务结点处理时我们再给一个独立的SpanID,这样请求何时到达结点、合适离开结点都有追踪的依据,就可以判断出每一跳的延时情况。

 

 

抽样:

日志采集的越多,追踪越全面,但是消耗也越大;反之日志追踪不够多也就失去了意义。到底追踪多少日志才是平衡点?Spring Cloud Sleuth把这个问题交给了使用者,通过配置spring.sleuth.sampler.percentage=0.1这个参数来决定了日志记录发送给采集器的概率,0-1交给使用者自己配置。开发阶段和运行初期,一般配置成1全量收集日志,到了上线后可以慢慢降低这一概率。

开发者还可以直接在代码中创建AlwaysSampler实例来指定100%输出日志,效果跟spring.sleuth.sampler.percentage=1是一样的。

@Beanpublic AlwaysSampler defaultSampler() {return new AlwaysSampler();}

图形化展示:

日志采集并积累到一定体量后,就会具备可分析的价值。例如一个请求链会经历ABC3个微服务结点,我们通过分析ABC服务结点处理时长的变化可以提前发现某个环节的处理能力不足需要扩展结点。Spring Cloud Zipkin已经提供了这样的图形化分析工具,只需要开启一个Zipkin-server结点,打开收集端口,将此接口添加到所有业务服务结点上就可以基本实现这一需求。

 

示例代码:

Eureka-Serverhttps://github.com/yejingtao/forblog/tree/master/demo-eureka-register

Trace-1https://github.com/yejingtao/forblog/tree/master/demo-trace-1

Trace-2https://github.com/yejingtao/forblog/tree/master/demo-trace-2

Zipkin-Serverhttps://github.com/yejingtao/forblog/tree/master/demo-zipkin-server

 

Zipkin-Server提供日志图形化分析:

Pom依赖

<parent>     <groupId>org.springframework.boot</groupId>     <artifactId>spring-boot-starter-parent</artifactId>     <version>1.5.6.RELEASE</version>     <relativePath/>  </parent>  <properties>    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  </properties>  <dependencies>    <dependency>            <groupId>io.zipkin.java</groupId>            <artifactId>zipkin-server</artifactId>        </dependency>        <dependency>            <groupId>io.zipkin.java</groupId>            <artifactId>zipkin-autoconfigure-ui</artifactId>        </dependency>  </dependencies>    <dependencyManagement>        <dependencies>            <dependency>                <groupId>org.springframework.cloud</groupId>                <artifactId>spring-cloud-dependencies</artifactId>                <version>Dalston.SR1</version>                <type>pom</type>                <scope>import</scope>            </dependency>        </dependencies>    </dependencyManagement>

参数很简单,需要指定端口9411

主程序:

@SpringBootApplication@EnableZipkinServerpublic class ZipkinServerApplication {public static void main(String[] args) {SpringApplication.run(ZipkinServerApplication.class, args);}}


Trace-2提供底层服务:

Pom依赖

<dependencies>    <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-eureka</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>        </dependency>        <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>  </dependencies>

参数配置

server:  port: 7082spring:  application:    name: trace-2  sleuth:    sampler:      percentage: 1  zipkin:    base-url: http://127.0.0.1:9411    eureka:  client:    serviceUrl:      defaultZone: http://peer1:1111/eureka/,http://peer2:1112/eureka/

主要配置了一个50%的概率,还有指定了zipkin的地址。

代码没什么好说明的,简单的提供一个rest服务供trace1调用。

 

Trace-1

Pom依赖:

<dependencies>    <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-eureka</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-ribbon</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>        </dependency>        <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>  </dependencies>


参数配置

server:  port: 7081spring:  application:    name: trace-1  sleuth:    sampler:      percentage: 0.1  zipkin:    base-url: http://127.0.0.1:9411eureka:  client:    serviceUrl:      defaultZone: http://peer1:1111/eureka/,http://peer2:1112/eureka/

代码没什么好说明的,简单的通过Rabbion来请求App-2RestFul

 

启动结点后多次GET请求Trace-1/trace1,验证测试。

日志打印信息如下,复习下前面原理中4个参数各自的意义。


Zipkin中可以看到所有请求链的情况,点击具体请求链还可以看到每个环节的情况。


注意:此处我故意挖了个坑,trace-1的概率是80%trace-2的概率是50%,那么Sleuth对这个概率到底是怎么控制的呢?经过反复测试绝伦是当概率不相同时是由请求链第一环的概率来决定的。可以自己验证下,把trace-1配置成1,把trace-2配置成0,对trace-1做请求时trace-1trace-2100%被收集;trace-1配置成0trace-2配置成1,对trace-1做请求时trace-1trace-2都不会被收集。

以下截图是我将trace-1配置成10%trace-2配置成100%后的测试结果

进一步确认下,Zipkin只收到一次,在详细信息中可以看到它的traceIdSpanId正是日志中为true的那一次。


我们不得不说Sleuth这个概率发送日志的功能真的设计的很精髓,它既可以提供一种通过日志量多少来自我治理和扩容的依据,又可以通过合理地配置用极少的消耗就可以达到这一需求。

实际生产中单通过Zipkin还是不足以满足我们对日志的收集和分析,SleuthELK的配合才可以把日志处理和分析做到另一个高度,这也是后面我们要学习的内容。




原创粉丝点击