springCloud的使用08-----服務鏈路追蹤(sleuth+zipkin)


sleuth主要功能是在分布式系統中提供追蹤解決方案,並且兼容支持了zipkin(提供了鏈路追蹤的可視化功能)

zipkin原理:在服務調用的請求和響應中加入ID,表明上下游請求的關系。

    利用這些信息,可以可視化地分析服務調用鏈路和服務間的依賴關系。

sleuth是對zipkin的封裝,對應Span,Trace等信息的生成、接入http request,以及向Zipkin server發送采集信息等全部自動化完成。

目前主流的鏈路追蹤組件有:google的Dapper,Twitter的zipkin和阿里的Eagleeye(鷹眼)。

1. 搭建zipkin服務器

  1.1 創建springboot項目,引入相應的jar依賴(其他依賴參考前面的教材)

<!-- 引入zipkin-server -->
<dependency>
    <groupId>io.zipkin.java</groupId>
    <artifactId>zipkin-server</artifactId>
</dependency>

<!-- 引入zipkin-server 圖形化界面 --> <dependency> <groupId>io.zipkin.java</groupId> <artifactId>zipkin-autoconfigure-ui</artifactId> </dependency>

  1.2 添加配置文件

server: 
 port: 8769
spring: 
 application: 
  name: zipkin-server
eureka: 
 client: 
  serviceUrl: 
   defaultZone: http://localhost:8761/eureka/ #注冊服務器地址
management: 
 security: 
  enabled: false #關閉驗證
info: #/info請求的顯示信息
 app: 
  name: ${spring.application.name}
  version: 1.0.0
 build: 
  artifactId: @project.artifactId@
  version: @project.version@
    

  1.3 在啟動類中聲明為zipkin服務器

@SpringBootApplication
@EnableDiscoveryClient
@EnableZipkinServer  //zipkin服務器 默認使用http進行通信
public class ZipkinServerApp {
    public static void main(String[] args) {
        SpringApplication.run(ZipkinServerApp.class, args);
    }
}

  1.4 啟動查看效果

    

2  分別在cloud-consumer-ribbon和cloud-consumer-feign中引入zipkin

  2.1 引入zipkin依賴

<!-- 配置服務鏈路追蹤 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>

   或

<!-- 配置服務鏈路追蹤 -->
<dependency>  
    <groupId>org.springframework.cloud</groupId>  
    <artifactId>spring-cloud-sleuth-zipkin</artifactId>  
</dependency>  
<dependency>  
    <groupId>org.springframework.cloud</groupId>  
    <artifactId>spring-cloud-starter-sleuth</artifactId>  
</dependency> 

  2.2 在配置文件中聲明zipkin服務器的地址

spring:
 zipkin: 
  base-url: http://localhost:8769

  2.3 在項目中調用需要的服務

@RequestMapping("hello")
public String helloConsumer() {
        //使用restTemplate調用消費服務提供者的SERVICE-HI的info服務
        //String response=restTemplate.getForObject("http://cloud-consumer-feign/hi", String.class);
        String response=hiService.sayHello()+" ribbon";
        logger.info(response);
        return response;
}

   2.4 啟動項目查看

    

    

    

  有時候可能在zipkin服務器中看不到數據,那是因為默認sleuth收集信息的比率是0.1 ,針對於這個問題有兩種解決方法:

    a 在配置文件中配置 spring.sleuth.sampler.percentage=1

    b 在代碼中聲明

//100%的來采集日志,和在配置文件中配置spring.sleuth.sampler.percentage=1是一樣的
@Bean
public AlwaysSampler defaultSampler(){
  return new AlwaysSampler();
}

  但這樣每個請求都會向zipkin server發送http請求,通信效率低,造成網絡延遲。

  而且所用的追蹤信息都在內存中保存,重啟zipkin server后信息丟失

  針對以上的問題的解決方法:

    a 采用socket或高效率的通信方式

    b 采用異步方式發送信息數據

    c 在客戶端和zipkin之間增加緩存類的中間件,如redis,mq等,即時zipkin server重啟過程中,客戶端依然可以將數據發送成功

3 將http通信改為mq異步通信方式

  3.1 修改zipkin server

    3.1.1 將原來的依賴io.zipkin.java:zipkin-server換成spring-cloud-sleuth-zipkin-stream和spring-cloud-starter-stream-rabbit  

<!-- 引入zipkin-server -->
<!-- <dependency>
    <groupId>io.zipkin.java</groupId>
    <artifactId>zipkin-server</artifactId>
</dependency> -->

<!-- 將http請求修改為mq請求 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-sleuth-zipkin-stream</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>

<dependency>
    <groupId>io.zipkin.java</groupId>
    <artifactId>zipkin-autoconfigure-ui</artifactId>
</dependency>

    3.1.2 在配置文件中配置ribbitmq地址

spring: 
 application: 
  name: zipkin-server
 rabbitmq: #配置mq消息隊列
  host: localhost 
  port: 5672 
  username: guest 
  password: guest

    3.1.3 在啟動類中使用@EnableZipkinStreamServer替換@EnableZipkinServer

@SpringBootApplication
@EnableDiscoveryClient
//@EnableZipkinServer  //zipkin服務器 默認使用http進行通信
@EnableZipkinStreamServer //采用stream方式啟動zipkin server ,也支持http通信 包含了@EnableZipkinServer,同時創建了rabbit-mq消息隊列監聽器
public class ZipkinServerApp {
    public static void main(String[] args) {
        SpringApplication.run(ZipkinServerApp.class, args);
    }
}

  3.2 配置客戶端(這里只配置一個客戶端,其他的客戶端配置一樣配置即可)

    3.2.1 將原來的spring-cloud-starter-zipkin依賴,使用以下依賴進行替換

<!-- 配置服務鏈路追蹤 -->
<!-- <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency> -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-sleuth-zipkin-stream</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>

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

    3.2.2 在配置文件中加入ribbitmq的配置

spring: 
 rabbitmq: #配置mq消息隊列
  host: localhost 
  port: 5672 
  username: guest 
  password: guest

  3.3 現在啟動其他項目,不啟動zipkin server,進行項目訪問,會把追蹤信息放入到ribbitmq中,當zipkin server啟動后會直接沖zipkin server中獲取信息

     

      

4 將追蹤信息保存到數據庫(只需修改zipkin server即可)

  4.1 引入mysql數據庫依賴

<!-- 配置mysql -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

  4.2 在配置文件msql連接

spring: 
 sleuth: 
  enabled: false #表示當前程序不使用sleuth
 datasource: #配置msyql 連接
  schema[0]: classpath:/zipkin.sql #數據庫創建腳本,可以到官網下載
  url: jdbc:mysql://localhost:3306/zipkin?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&useSSL=false  
  username: root
  password: root
  driver-class-name: com.mysql.jdbc.Driver 
  initialize: true
  continue-on-error: true
zipkin: 
 storage: 
  type: mysql #mysql存儲zipkin追蹤信息

  4.3 創建數據庫和表

    CREATE TABLE IF NOT EXISTS zipkin_spans (  
      `trace_id_high` BIGINT NOT NULL DEFAULT 0 COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit',  
      `trace_id` BIGINT NOT NULL,  
      `id` BIGINT NOT NULL,  
      `name` VARCHAR(255) NOT NULL,  
      `parent_id` BIGINT,  
      `debug` BIT(1),  
      `start_ts` BIGINT COMMENT 'Span.timestamp(): epoch micros used for endTs query and to implement TTL',  
      `duration` BIGINT COMMENT 'Span.duration(): micros used for minDuration and maxDuration query'  
    ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;  
      
    ALTER TABLE zipkin_spans ADD UNIQUE KEY(`trace_id_high`, `trace_id`, `id`) COMMENT 'ignore insert on duplicate';  
    ALTER TABLE zipkin_spans ADD INDEX(`trace_id_high`, `trace_id`, `id`) COMMENT 'for joining with zipkin_annotations';  
    ALTER TABLE zipkin_spans ADD INDEX(`trace_id_high`, `trace_id`) COMMENT 'for getTracesByIds';  
    ALTER TABLE zipkin_spans ADD INDEX(`name`) COMMENT 'for getTraces and getSpanNames';  
    ALTER TABLE zipkin_spans ADD INDEX(`start_ts`) COMMENT 'for getTraces ordering and range';  
      
    CREATE TABLE IF NOT EXISTS zipkin_annotations (  
      `trace_id_high` BIGINT NOT NULL DEFAULT 0 COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit',  
      `trace_id` BIGINT NOT NULL COMMENT 'coincides with zipkin_spans.trace_id',  
      `span_id` BIGINT NOT NULL COMMENT 'coincides with zipkin_spans.id',  
      `a_key` VARCHAR(255) NOT NULL COMMENT 'BinaryAnnotation.key or Annotation.value if type == -1',  
      `a_value` BLOB COMMENT 'BinaryAnnotation.value(), which must be smaller than 64KB',  
      `a_type` INT NOT NULL COMMENT 'BinaryAnnotation.type() or -1 if Annotation',  
      `a_timestamp` BIGINT COMMENT 'Used to implement TTL; Annotation.timestamp or zipkin_spans.timestamp',  
      `endpoint_ipv4` INT COMMENT 'Null when Binary/Annotation.endpoint is null',  
      `endpoint_ipv6` BINARY(16) COMMENT 'Null when Binary/Annotation.endpoint is null, or no IPv6 address',  
      `endpoint_port` SMALLINT COMMENT 'Null when Binary/Annotation.endpoint is null',  
      `endpoint_service_name` VARCHAR(255) COMMENT 'Null when Binary/Annotation.endpoint is null'  
    ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;  
      
    ALTER TABLE zipkin_annotations ADD UNIQUE KEY(`trace_id_high`, `trace_id`, `span_id`, `a_key`, `a_timestamp`) COMMENT 'Ignore insert on duplicate';  
    ALTER TABLE zipkin_annotations ADD INDEX(`trace_id_high`, `trace_id`, `span_id`) COMMENT 'for joining with zipkin_spans';  
    ALTER TABLE zipkin_annotations ADD INDEX(`trace_id_high`, `trace_id`) COMMENT 'for getTraces/ByIds';  
    ALTER TABLE zipkin_annotations ADD INDEX(`endpoint_service_name`) COMMENT 'for getTraces and getServiceNames';  
    ALTER TABLE zipkin_annotations ADD INDEX(`a_type`) COMMENT 'for getTraces';  
    ALTER TABLE zipkin_annotations ADD INDEX(`a_key`) COMMENT 'for getTraces';  
    ALTER TABLE zipkin_annotations ADD INDEX(`trace_id`, `span_id`, `a_key`) COMMENT 'for dependencies job';  
      
    CREATE TABLE IF NOT EXISTS zipkin_dependencies (  
      `day` DATE NOT NULL,  
      `parent` VARCHAR(255) NOT NULL,  
      `child` VARCHAR(255) NOT NULL,  
      `call_count` BIGINT  
    ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;  
      
    ALTER TABLE zipkin_dependencies ADD UNIQUE KEY(`day`, `parent`, `child`);  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM