SpringCloud教程九:服务链路追踪(SpringCloud Sleuth)

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

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

zipkin为分布式链路调用监控系统,聚合各业务系统调用延迟数据,达到链路调用监控跟踪。

architecture:
SpringCloud教程九:服务链路追踪(SpringCloud Sleuth)_第1张图片
如图,在复杂的调用链路中假设存在一条调用链路响应缓慢,如何定位其中延迟高的服务呢?

日志: 通过分析调用链路上的每个服务日志得到结果
zipkin:使用zipkin的web UI可以一眼看出延迟高的服务
SpringCloud教程九:服务链路追踪(SpringCloud Sleuth)_第2张图片
如图所示,各业务系统在彼此调用时,将特定的跟踪消息传递至zipkin,zipkin在收集到跟踪信息后将其聚合处理、存储、展示等,用户可通过web UI方便
获得网络延迟、调用链路、系统依赖等等。
zipkin
zipkin主要涉及四个组件 collector storage search web UI

  • Collector接收各service传输的数据
  • Cassandra作为Storage的一种,也可以是mysql等,默认存储在内存中,配置cassandra可以参考这里
  • Query负责查询Storage中存储的数据,提供简单的JSON API获取数据,主要提供给web UI使用
  • Web 提供简单的web界面

概念:

  1. Span:基本工作单元,一次链路调用(可以是RPC,DB等没有特定的限制)创建一个span,通过一个64位ID标识它,
    span通过还有其他的数据,例如描述信息,时间戳,key-value对的(Annotation)tag信息,parent-id等,其中parent-id
    可以表示span调用链路来源,通俗的理解span就是一次请求信息
  2. Trace:类似于树结构的Span集合,表示一条调用链路,存在唯一标识
  3. Annotation: 注解,用来记录请求特定事件相关信息(例如时间),通常包含四个注解信息
cs - Client Start,表示客户端发起请求

sr - Server Receive,表示服务端收到请求

ss - Server Send,表示服务端完成处理,并将结果发送给客户端

cr - Client Received,表示客户端获取到服务端返回信息
  1. BinaryAnnotation:提供一些额外信息,一般已key-value对出现

完整的调用链路图:
SpringCloud教程九:服务链路追踪(SpringCloud Sleuth)_第3张图片
上图表示一请求链路,一条链路通过Trace Id唯一标识,Span标识发起的请求信息,各span通过parent id 关联起来,如图 :
SpringCloud教程九:服务链路追踪(SpringCloud Sleuth)_第4张图片
完成链路调用的记录后,如何来计算调用的延迟呢,这就需要利用Annotation信息:
SpringCloud教程九:服务链路追踪(SpringCloud Sleuth)_第5张图片

sr-cs 得到请求发出延迟

ss-sr 得到服务端处理延迟

cr-cs 得到真个链路完成延迟

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

创建server-zipkin工程,pom依赖如下:


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0modelVersion>

    <groupId>com.springcloudgroupId>
    <artifactId>server-zipkinartifactId>
    <version>0.0.1-SNAPSHOTversion>
    <packaging>jarpackaging>

    <name>server-zipkinname>
    <description>Demo project for Spring Bootdescription>

    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>1.5.9.RELEASEversion>
        <relativePath/> 
    parent>

    <properties>
        <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
        <java.version>1.8java.version>
        <spring-cloud.version>Edgware.RELEASEspring-cloud.version>
    properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starterartifactId>
        dependency>

        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
        dependency>

        <dependency>
            <groupId>io.zipkin.javagroupId>
            <artifactId>zipkin-serverartifactId>
        dependency>

        <dependency>
            <groupId>io.zipkin.javagroupId>
            <artifactId>zipkin-autoconfigure-uiartifactId>
        dependency>
    dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-dependenciesartifactId>
                <version>${spring-cloud.version}version>
                <type>pomtype>
                <scope>importscope>
            dependency>
        dependencies>
    dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
            plugin>
        plugins>
    build>


project>

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


@SpringBootApplication
@EnableZipkinServer
public class ServerZipkinApplication {

    public static void main(String[] args) {

        SpringApplication.run(ServerZipkinApplication.class, args);
    }
}

修改配置文件:

server.port=8887

创建service-hi工程,pom文件如下:


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0modelVersion>

    <groupId>com.springcloudgroupId>
    <artifactId>service-hiartifactId>
    <version>0.0.1-SNAPSHOTversion>
    <packaging>jarpackaging>

    <name>service-hiname>
    <description>Demo project for Spring Bootdescription>

    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>1.5.9.RELEASEversion>
        <relativePath/> 
    parent>

    <properties>
        <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
        <java.version>1.8java.version>
        <spring-cloud.version>Edgware.RELEASEspring-cloud.version>
    properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-zipkinartifactId>
        dependency>

        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
        dependency>
    dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-dependenciesartifactId>
                <version>${spring-cloud.version}version>
                <type>pomtype>
                <scope>importscope>
            dependency>
        dependencies>
    dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
            plugin>
        plugins>
    build>


project>

程序入口类如下:

@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:8890/hi", 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();
    }
}

修改配置文件如下:

server.port=8889
#指定zipkin server的地址
spring.zipkin.base-url=http://localhost:8887
spring.application.name=service-hi

创建service-hi2,pom如下:


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0modelVersion>

    <groupId>com.springcloudgroupId>
    <artifactId>service-hi2artifactId>
    <version>0.0.1-SNAPSHOTversion>
    <packaging>jarpackaging>

    <name>service-hi2name>
    <description>Demo project for Spring Bootdescription>

    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>1.5.9.RELEASEversion>
        <relativePath/> 
    parent>

    <properties>
        <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
        <java.version>1.8java.version>
        <spring-cloud.version>Edgware.RELEASEspring-cloud.version>
    properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-zipkinartifactId>
        dependency>

        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
        dependency>
    dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-dependenciesartifactId>
                <version>${spring-cloud.version}version>
                <type>pomtype>
                <scope>importscope>
            dependency>
        dependencies>
    dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
            plugin>
        plugins>
    build>


project>

修改程序入口类如下:

@SpringBootApplication
@RestController
public class ServiceHi2Application {

    public static void main(String[] args)
    {
        SpringApplication.run(ServiceHi2Application.class, args);
    }
    private static final Logger LOG = Logger.getLogger(ServiceHi2Application.class.getName());

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

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

    @Autowired
    private RestTemplate restTemplate;

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

修改配置环境文件如下:

server.port=8890
#指定zipkin server的地址
spring.zipkin.base-url=http://localhost:8887
spring.application.name=service-hi2

依次启动上面的三个程序:
浏览器请求:http://localhost:8887/zipkin/
SpringCloud教程九:服务链路追踪(SpringCloud Sleuth)_第6张图片

访问http://localhost:8890/test
返回:

i’m service-hi

再打开http://localhost:8887/zipkin/的界面,点击Dependencies,可以发现服务的依赖关系:
SpringCloud教程九:服务链路追踪(SpringCloud Sleuth)_第7张图片
点击find traces,可以看到具体服务相互调用的数据:
SpringCloud教程九:服务链路追踪(SpringCloud Sleuth)_第8张图片

你可能感兴趣的:(SpringCloud)