天天看點

SpringCloud(十五)springCloud sleuth 分布式鍊路跟蹤

前言:

    在微服務中,各個微服務之間存在着調用關系,spring cloud sleuth就是追蹤整條調用鍊的。

一些感念:

  • 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時間戳便可得到用戶端從服務端擷取回複的所有所需時間
代碼:

在springboot2.0,springcloud Finchley版本,不允許自己建zipkin server了,可以用jar包自己跑,也可以直接用docker運作,https://github.com/openzipkin/zipkin#quick-start 位址。

我就用docker了

docker run -d -p 9411:9411 --name zipkin openzipkin/zipkin      

啟動後通路 http://192.168.94.151:9411/zipkin/

SpringCloud(十五)springCloud sleuth 分布式鍊路跟蹤

然後建立一個eureka,和兩個有調用關系的微服務

eureka  pom.xml

<?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">
    <parent>
        <artifactId>springcloud16-zipkin</artifactId>
        <groupId>com.xhx.springcloud</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>eureka-server</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>

</project>      

application.yml

spring:
  application:
    name: eureka-server
server:
  port: 8761
eureka:
  instance:
    hostname: localhost
  client:
    register-with-eureka: false
    fetch-registry: false
    service-url:
      default-zone: http://${eureka.instance.hostname}:${server.port}/eureka      

啟動類:

package com.xhx.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

/**
 * xuhaixing
 * 2018/6/16 16:34
 */
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class,args);
    }
}      

服務提供者  user-service:

pom.xml,增加sleuth和zipkin兩個包

<?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">
    <parent>
        <artifactId>springcloud16-zipkin</artifactId>
        <groupId>com.xhx.springcloud</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>user-service</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-sleuth</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
        </dependency>
    </dependencies>

</project>      

application.yml,base-url指定zipkin的位址

spring:
  application:
    name: user-service
  zipkin:
    base-url: http://192.168.94.151:9411
    #discovery-client-enabled: true
   # service:
      #name: zipkin-service
    enabled: true
server:
  port: 8080
eureka:
  client:
    service-url:
      default-zone: http://locahost:8761/eureka
feign:
  hystrix:
    enabled: true      

啟動類:

package com.xhx.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;


/**
 * xuhaixing
 * 2018/6/16 17:04
 */
@SpringCloudApplication
@EnableFeignClients
public class UserServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class,args);
    }
}      

提供接口的controller

package com.xhx.springcloud.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 * xuhaixing
 * 2018/6/16 17:09
 */
@RestController
@RequestMapping(value = "user")
public class UserController {


    @RequestMapping(value = "getUserInfo",method = RequestMethod.POST)
    public Map<String, String> getUserInfo(){
        Map<String,String> user = new HashMap<>();
        user.put("name","xuhaixing");
        user.put("gender","man");
        return user;
    }
}      

服務消費者

pom.xml和前面一樣加入sleuth和zipkin

<?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">
    <parent>
        <artifactId>springcloud16-zipkin</artifactId>
        <groupId>com.xhx.springcloud</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>order-service</artifactId>

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

</project>      

application.yml

probability是被zipkin收集的機率,1為全部收集,因為現在是直接用http方式發送資料并且放在記憶體中,是以會影響性能。可以用消息隊列或者mysql收集服務鍊路資訊。

spring:
  application:
    name: order-service
  zipkin:
      #discovery-client-enabled: true
      #service:
        #name: zipkin-service
      enabled: true
      base-url: http://192.168.94.151:9411
  sleuth:
    sampler:
      probability: 1
server:
  port: 8086
eureka:
  client:
    service-url:
      default-zone: http://locahost:8761/eureka
feign:
  hystrix:
    enabled: true      

feign

package com.xhx.springcloud.api;

import com.alibaba.fastjson.JSONObject;
import com.xhx.springcloud.hystrix.UserInfoApiHytrix;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import java.util.Map;

/**
 * xuhaixing
 * 2018/6/16 17:19
 */
@FeignClient(value = "user-service",path = "user",fallback = UserInfoApiHytrix.class)
public interface UserInfoApi {
    @RequestMapping(value = "getUserInfo",method = RequestMethod.POST)
    JSONObject getUserInfo();
}      

controller

package com.xhx.springcloud.controller;

import com.alibaba.fastjson.JSONObject;
import com.xhx.springcloud.api.UserInfoApi;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.Optional;

/**
 * xuhaixing
 * 2018/6/16 17:19
 */
@RestController
@RequestMapping(value = "order")
public class OrderController {

    @Autowired
    private UserInfoApi userInfoApi;

    @RequestMapping(value = "getUserOrder",method = RequestMethod.POST)
    public JSONObject getUserOrder(){
        JSONObject userInfo = userInfoApi.getUserInfo();
        Optional.ofNullable(userInfo).ifPresent(user->user.put("orderMoney",999));
        return userInfo;
    }
}      

hystrix

package com.xhx.springcloud.hystrix;

import com.alibaba.fastjson.JSONObject;
import com.xhx.springcloud.api.UserInfoApi;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * xuhaixing
 * 2018/6/16 17:20
 */
@Component
public class UserInfoApiHytrix implements UserInfoApi {
    @Override
    public JSONObject getUserInfo() {
        return null;
    }
}      

請求一下

SpringCloud(十五)springCloud sleuth 分布式鍊路跟蹤

打開zipkin

SpringCloud(十五)springCloud sleuth 分布式鍊路跟蹤
SpringCloud(十五)springCloud sleuth 分布式鍊路跟蹤