史上最简单的SpringCloud教程 | 第九篇: 服务链路追踪(Spring Cloud Sleuth)

这篇文章主要讲述服务追踪组件zipkin,Spring Cloud Sleuth集成了zipkin组件。

一、简介

Add sleuth to the classpath of a Spring Boot application (see below for Maven and Gradle examples), and you will see the correlation data being collected in logs, as long as you are logging requests. —— 摘自官网

Spring Cloud Sleuth 主要功能就是在分布式系统中提供追踪解决方案,并且兼容支持了 zipkin,你只需要在pom文件中引入相应的依赖即可。

二、服务追踪分析

微服务架构上通过业务来划分服务的,通过REST调用,对外暴露的一个接口,可能需要很多个服务协同才能完成这个接口功能,如果链路上任何一个服务出现问题或者网络超时,都会形成导致接口调用失败。随着业务的不断扩张,服务之间互相调用会越来越复杂。

随着服务的越来越多,对调用链的分析会越来越复杂。它们之间的调用关系也许如下:

三、术语

  • 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时间戳便可得到客户端从服务端获取回复的所有所需时间 将Span和Trace在一个系统中使用Zipkin注解的过程图形化:

将Span和Trace在一个系统中使用Zipkin注解的过程图形化:

四、构建工程

基本知识讲解完毕,下面我们来实战,本文的案例主要有三个工程组成:一个server-zipkin,它的主要作用使用ZipkinServer 的功能,收集调用数据,并展示;一个service-hi,对外暴露hi接口;一个service-miya,对外暴露miya接口;这两个service可以相互调用;并且只有调用了,server-zipkin才会收集数据的,这就是为什么叫服务追踪了。

4.1 构建server-zipkin

建一个spring-boot工程取名为server-zipkin,在其pom引入依赖:

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <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>Camden.SR6</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

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

@SpringBootApplication
@EnableZipkinServer
public class ServerZipkinApplication {

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

在配置文件application.yml指定服务端口为:

server.port=9411

4.2 创建service-hi

在其pom引入起步依赖spring-cloud-starter-zipkin,代码如下:

<dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--compile('org.springframework.cloud:spring-cloud-starter-zipkin')-->

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Dalston.RC1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

在其配置文件application.yml指定zipkin server的地址,头通过配置“spring.zipkin.base-url”指定:

server.port=8988
spring.zipkin.base-url=http://localhost:9411
spring.application.name=service-hi

通过引入spring-cloud-starter-zipkin依赖和设置spring.zipkin.base-url就可以了。

对外暴露接口:

@SpringBootApplication
@RestController
public class ServiceHiApplication {

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

    private static final Logger LOG = Logger.getLogger(ServiceHiApplication.class.getName());


    @Autowired
    private RestTemplate restTemplate;

    @Bean
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }

    @RequestMapping("/hi")
    public String callHome(){
        LOG.log(Level.INFO, "calling trace service-hi  ");
        return restTemplate.getForObject("http://localhost:8989/miya", String.class);
    }
    @RequestMapping("/info")
    public String info(){
        LOG.log(Level.INFO, "calling trace service-hi ");

        return "i'm service-hi";

    }

    @Bean
    public AlwaysSampler defaultSampler(){
        return new AlwaysSampler();
    }
}

4.3 创建service-miya

创建过程痛service-hi,引入相同的依赖,配置下spring.zipkin.base-url。

对外暴露接口:

@SpringBootApplication
@RestController
public class ServiceMiyaApplication {

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

    private static final Logger LOG = Logger.getLogger(ServiceMiyaApplication.class.getName());


    @RequestMapping("/hi")
    public String home(){
        LOG.log(Level.INFO, "hi is being called");
        return "hi i'm miya!";
    }

    @RequestMapping("/miya")
    public String info(){
        LOG.log(Level.INFO, "info is being called");
        return restTemplate.getForObject("http://localhost:8988/info",String.class);
    }

    @Autowired
    private RestTemplate restTemplate;

    @Bean
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}

4.4 启动工程,演示追踪

依次启动上面的三个工程,打开浏览器访问:http://localhost:9411/,会出现以下界面:

访问:http://localhost:8989/miya,浏览器出现:

i’m service-hi

再打开http://localhost:9411/的界面,点击Dependencies,可以发现服务的依赖关系:

点击find traces,可以看到具体服务相互调用的数据:

本文源码下载: https://github.com/forezp/SpringCloudLearning/tree/master/chapter9

五、参考资料

spring-cloud-sleuth

利用Zipkin对Spring Cloud应用进行服务追踪分析

Spring Cloud Sleuth使用简介

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏微服务生态

性能分析系列-小命令保证大性能

最近在工作中经常和性能压测工作打交道,积累了一些性能分析经验,我觉得这些经验对每一个开发者都有帮助的,能开发出性能高的代码也是我们的最终目标。

735
来自专栏皮振伟的专栏

​[linux][pthread]qemu的一次pthread create失败的分析

前言: qemu发生了crash。这种类型的问题比较少见,这里说一下这个问题的分析过程。 分析: 1,coredump 生成的coredump,一种是配置了...

3416
来自专栏PhpZendo

MVC 框架中的路由器(Router)是如何跑起来的

MVC 路由器(Router)或分发器(Dispatcher)会检测 HTTP 请求的 URL,并尝试将单个 URL 组件与控制器和控制器中定义的方法匹配,同时...

511
来自专栏idba

Python模块之subprocess

一 简介 在使用Python 开发MySQL自动化相关的运维工具的时候,遇到一些有意思的问题,本文介绍Python的 subprocess 模块以及如何和My...

601
来自专栏Java帮帮-微信公众号-技术文章全总结

10(02)总结形式参数,包,修饰符,内部类

6:内部类(理解) (1)把类定义在另一个类的内部,该类就被称为内部类。 举例:把类B定义在类A中,类B就被称为内部类。 (2)内部类的访问规则 A:可...

2536
来自专栏阿杜的世界

Spring Boot应用的健康监控

在之前的系列文章中我们学习了如何进行Spring Boot应用的功能开发,以及如何写单元测试、集成测试等,然而,在实际的软件开发中需要做的不仅如此:还包括对应用...

1081
来自专栏程序猿DD

Spring Boot 1.5.x新特性:动态修改日志级别

前天Spring Boot 1.5终于迎来了第一个RELEASE版本:1.5.0,但是由于一个编译依赖问题在第二天直接连击到了1.5.1。该版本的发布包含了超过...

2169
来自专栏java一日一条

理解Cookie和Session机制

会话(Session)跟踪是Web程序中常用的技术,用来跟踪用户的整个会话。常用的会话跟踪技术是Cookie与Session。Cookie通过在客户端记录信息确...

381
来自专栏开源优测

[接口测试 - http.client篇] 16 基于http.client之POM实战一下

概述 关注公众号回复: http.client_pom_demo 获取本文示例源码 你需要了解以下知识和技术,以便掌握后续的实例代码: http.client常...

3428
来自专栏开发与安全

linux系统编程之进程(一):进程基本概述

一、什么是进程 从用户的角度来看进程是程序的一次执行过程。 从操作系统的核心来看,进程是操作系统分配的内存、CPU时间片等资源的基本单位。 进程是资源分配的...

19110

扫码关注云+社区