1. 程式人生 > >spring Cloud Sleuth 分散式服務跟蹤

spring Cloud Sleuth 分散式服務跟蹤

前瞻:

      首先我們知道spring Cloud Sleuth分散式服務跟蹤是幹什麼的,在現如今的系統規模中,隨著系統規模的越來越大,微服務之間的呼叫關係越來越錯綜複雜,通常一個前端的請求在系統中會經過多個微服務之間的呼叫最後才能返回正確的結果,而在這麼多微服務之間的相互呼叫中,每一次微服務之間呼叫的延遲都可能使整個請求出現超時而導致失敗,這時候,對於全鏈路呼叫的跟蹤就顯得尤為重要了,它記錄了整個請求鏈路中每個微服務呼叫的資訊,例如某一個微服務呼叫的處理時間等等,這對後續分析系統的效能瓶頸很有幫助;

實現:

 第一步:

 1、實現服務註冊中心Eureka,這個很簡單,不在贅述,讀者可以看我前面程式碼的例子;

 2、微服務應用trance-1:實現一個REST介面/trance-1,呼叫改介面後實現對微服務應用trance-2的介面呼叫

  2.1:引入pom依賴:

<?xml version="1.0" encoding="UTF-8"?>
<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>spring.cloud</groupId>
    <artifactId>trace-1</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.7.RELEASE</version>
        <relativePath/>
    </parent>


    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-ribbon</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-sleuth</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.10</version>
        </dependency>
        <dependency>
            <groupId>net.logstash.logback</groupId>
            <artifactId>logstash-logback-encoder</artifactId>
            <version>4.6</version>
        </dependency>
    </dependencies>

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



</project>

2.2:配置檔案:

spring:
  application:
    name: trace-1
server:
  port: 9101
eureka:
  client:
    serviceUrl:
        defaultZone: http://localhost:1111/eureka/

2.3:啟動類:

package controller;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;


@SpringBootApplication(scanBasePackages = "controller")
@EnableDiscoveryClient
public class TestApplication {

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    };

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

2.4:REST介面:

package controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
@Slf4j
public class Trace1Controller {

    @Autowired
    private RestTemplate restTemplate;

        @RequestMapping(value = "/trace-1" , method = RequestMethod.GET)
    public String trace(){
        log.info("=====call trace-1====");
        return restTemplate.getForEntity("http://trace-2/trace-2", String.class)
                .getBody();
    }
}

 3、微服務應用trance-2:pom配置、啟動類基本相同,不同的是配置類和一個實現了REST介面/trance-2供trance-1呼叫

spring:
  application:
    name: trace-2
server:
  port: 9102
eureka:
  client:
    serviceUrl:
        defaultZone: http://localhost:1111/eureka/
package controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;

@RestController
@Slf4j
public class Trace2Controller {


    @RequestMapping(value = "/trace-2" , method = RequestMethod.GET)
    public String trace(HttpServletRequest request){
        log.info("call trace-2");
        log.info(request.getHeader("X-B3-TraceId")+" "
                + request.getHeader("X-B3-SpanId"));
        //System.out.println("=====call trace-2=====");
        return "trace2";
    }
}

第二步:分別啟動服務註冊中心Eureka、trance-1和trance-2,請求/trance-1介面http://localhost:9101/trace-1  

此時可以再trance-1和trance-2控制檯看見如下資訊:

trance-1控制檯:

trance-2控制檯:

 下面我們來說下這幾個引數的含義:

第一個值:trance-1,應用的名稱,也就是配置檔案application.yml中的spring.application.name的屬性

第二個值:33c66de84a293041,spring Cloud Sleuth生成的一個ID,也叫tranceID,它用來表示一條請求鏈路,我們可以看到trance-1和trance-2應用中列印的tranceID都相同,這表示他們是一次請求,在一條請求鏈路上;

第三個值:7975c7c9fcf06b51,spring Cloud Sleuth生成的另一個ID,也叫spanID,它表示一個基本的工作單元,比如傳送一個http請求。

第四個值:false,表示資訊是否要輸出到Zipkin等服務來進行後序的收集及展示;

上面四個值中,tranceID和spanID是spring Cloud Sleuth實現分散式服務跟蹤的核心。