zoukankan      html  css  js  c++  java
  • 第八篇: 服务链路追踪(Spring Cloud Sleuth)

    一、简介

    一个分布式系统由若干分布式服务构成,每一个请求会经过多个业务系统并留下足迹,但是这些分散的数据对于问题排查,或是流程优化都很有限。
     
    要能做到追踪每个请求的完整链路调用,收集链路调用上每个服务的性能数据,计算性能数据和比对性能指标(SLA),甚至能够再反馈到服务治理中,那么这就是分布式跟踪的目标。
     
    在业界:淘宝的鹰眼, 京东的Hydra实现了这个目标,这里要介绍的是twitter 的 zipkin。
     
    Spring Cloud Sleuth集成了zipkin组件。
     
    Spring Cloud Sleuth 主要功能就是在分布式系统中提供追踪解决方案,并且兼容支持了 zipkin,你只需要在pom文件中引入相应的依赖即可。
     

    1.1、ZipKin简介

    1、Zipkin是一个致力于收集分布式服务的时间数据的分布式跟踪系统。

    2、Zipkin 主要涉及四个组件:collector(数据采集),storage(数据存储),search(数据查询),UI(数据展示)。

    3、github源码地址:https://github.com/openzipkin/zipkin

    4、Zipkin提供了可插拔数据存储方式:In-Memory,MySql, Cassandra, Elasticsearch;本文为了测试方便以In-Memory方式进行存储,个人推荐Elasticsearch,关于更多的存储方式可以参考github。

    5、ZipKin运行环境需要Jdk8支持。

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

    随着服务的越来越多,对调用链的分析会越来越复杂。所以有了zipkin,对服务调用链的追踪。

    二、构建工程

    本文的案例主要有三个工程组成:一个eureka-server-zipkin,它的主要作用使用ZipkinServer 的功能,收集调用数据,并展示;

    一个service-hi,对外暴露hi接口;

    一个eureka-service-miya,对外暴露miya接口;

    这两个service可以相互调用,并且只有调用了,eureka-server-zipkin才会收集数据的,这就是为什么叫服务追踪了。

      

    2.1构建server-zipkin

    在spring Cloud为F版本的时候,已经不需要自己构建Zipkin Server了,只需要下载jar即可,下载地址:

    https://dl.bintray.com/openzipkin/maven/io/zipkin/java/zipkin-server/

    也可以在这里下载:

    链接: https://pan.baidu.com/s/1w614Z8gJXHtqLUB6dKWOpQ 密码: 26pf

    下载完成jar 包之后,需要运行jar,如下:

    java -jar zipkin-server-2.10.1-exec.jar

    访问浏览器localhost:9411

    2.2 创建eureka-service-hi

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

      

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

      pom.xml如下:  

    <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.0</modelVersion>
      <groupId>com.sun</groupId>
      <artifactId>eureka-service-hi</artifactId>
      <version>0.0.1-SNAPSHOT</version>
        <packaging>jar</packaging>
        
        <name>service-hi</name>
        <description>Demo project for Spring Boot</description>
    
        <parent>
            <groupId>com.sun</groupId>
            <artifactId>springcloud-parent</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </parent>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-zipkin</artifactId>
            </dependency>
        </dependencies>
    </project>
    View Code

      在resources下建application.yml:

      

    server:
      port: 8988
    spring:
      zipkin:
        base-url: http://localhost:9411 #设置zipkin服务器地址
      application:
        name: service-hi

    可以看到,上面最主要的是设置了zipkin的服务器地址。

    下面我们看看启动类怎么写:

    package com.sun;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.Bean;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.client.RestTemplate;
    
    import brave.sampler.Sampler;
    
    @SpringBootApplication
    @RestController
    public class ServiceHiApplication {
        private static final Logger logger = LoggerFactory.getLogger(ServiceHiApplication.class);
    
        public static void main(String[] args) {
            SpringApplication.run(ServiceHiApplication.class, args);
        }
    
        @Autowired
        private RestTemplate restTemplate;
    
        @Bean
        public RestTemplate getRestTemplate(){
            return new RestTemplate();
        }
    
        @RequestMapping("/hi")
        public String callHome(){
            logger.info("calling trace service-miya");
            return restTemplate.getForObject("http://localhost:8989/miya", String.class);
        }
        
        @RequestMapping("/info")
        public String info(){
            logger.info("calling trace service-hi");
            return "i'm service-hi";
        }
        
        //Brave是一个用于捕捉和报告分布式操作的延迟信息给Zipkin的工具库。 
        //Sampler.ALWAYS_SAMPLE返回一个sampler,设置需要采样
        @Bean
        public Sampler defaultSampler() {
            return Sampler.ALWAYS_SAMPLE;
        }
    }

    启动类里有几个重要方法:

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

    这个方法通过RestTemplate调用了http://localhost:8989/miya服务,就此产生了对miya的依赖。

    而:

    //Brave是一个用于捕捉和报告分布式操作的延迟信息给Zipkin的工具库。 
        //Sampler.ALWAYS_SAMPLE返回一个sampler,设置需要采样
        @Bean
        public Sampler defaultSampler() {
            return Sampler.ALWAYS_SAMPLE;
        }

    该方法返回一个Sampler对象,可以看下源码,意思是这个类需要进行zipkin的依赖采样。当没有这个方法时,zipkin不进行依赖监控。

    2.3 创建eureka-service-miya

    和eureka-service-hi服务一样的依赖,这里pom.xml就省略了。

    application.yml也基本相同,代码如下:

    server:
      port: 8989
    spring:
      zipkin:
        base-url: http://localhost:9411
      application:
        name: service-miya

    启动类ServiceMiyaApplication代码如下:

    package com.sun;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.Bean;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.client.RestTemplate;
    
    import brave.sampler.Sampler;
    
    @SpringBootApplication
    @RestController
    public class ServiceMiyaApplication {
    
        private static final Logger logger = LoggerFactory.getLogger(ServiceMiyaApplication.class);
        
        public static void main(String[] args) {
            SpringApplication.run(ServiceMiyaApplication.class, args);
        }
    
        @RequestMapping("/hi")
        public String home(){
            logger.info("hi is being called");
            return "hi i'm miya!";
        }
    
        @RequestMapping("/miya")
        public String info(){
            logger.info("miya is being called");
            return restTemplate.getForObject("http://localhost:8988/info",String.class);
        }
    
        @Autowired
        private RestTemplate restTemplate;
    
        @Bean
        public RestTemplate getRestTemplate(){
            return new RestTemplate();
        }
        
        @Bean
        public Sampler defaultSampler() {
            return Sampler.ALWAYS_SAMPLE;
        }
    
    }
    View Code

    和eureka-service-hi很相似。

    三、启动工程,演示追踪

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

     

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

    i'm service-hi

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

    这里可以看到service-miya依赖于service-hi。

    访问http://localhost:8988/hi

    i'm service-hi

    这时看zipkin   http://localhost:9411/的界面,看到:

    这时service-hi调用了service-miya,service-miya继续调用service-hi,所以产生了一个回路。

    本篇文章感谢https://www.jianshu.com/p/7cedbbc3d0fa

    还有https://blog.csdn.net/forezp/article/details/81041078

  • 相关阅读:
    Median Value
    237. Delete Node in a Linked List
    206. Reverse Linked List
    160. Intersection of Two Linked Lists
    83. Remove Duplicates from Sorted List
    21. Merge Two Sorted Lists
    477. Total Hamming Distance
    421. Maximum XOR of Two Numbers in an Array
    397. Integer Replacement
    318. Maximum Product of Word Lengths
  • 原文地址:https://www.cnblogs.com/PPBoy/p/9407281.html
Copyright © 2011-2022 走看看