天天看點

springcloud-sleuth & zipkin 初步配置Sleuth & zipkin

Sleuth & zipkin

分布式鍊路追蹤(Distributed Tracing),就是将一次分布式請求還原成調用鍊路,進行日志記錄,性能監控并将 一次分布式請求的調用情況集中展示。比如各個服務節點上的耗時、請求具體到達哪台機器上、每個服務節點的請求狀态等等。

Sleuth

Spring Cloud Sleuth 主要功能就是在分布式系統中提供追蹤解決方案,并且相容支援了 zipkin,你隻需要在pom檔案中引入相應的依賴即可。

  • 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時間戳便可得到用戶端從服務端擷取回複的所有所需時間
  1. 配置依賴
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-sleuth</artifactId>
    </dependency>
               
  2. 配置檔案application.yml
    logging:
      level:
        root: INFO
       org.springframework.web.servlet.DispatcherServlet: DEBUG
       org.springframework.cloud.sleuth: DEBUG
               
    需要收集日志的微服務(本項目就是gateway服務,product服務,service服務)都需要添加如上的配置和依賴pom檔案。啟動微服務,調用之後,我們可以在對應微服務的控制台觀察到sleuth的日志輸出。
    // gateway控制台列印的
    DEBUG [api-gateway-server,79ff7de257120731,79ff7de257120731,true] 8928 --- [ctor-http-nio-2......
    
    // service-order控制台列印的
    DEBUG [service-order, 79ff7de257120731, df75b5eaaa9c99b0,true] 2944 --- [nio-9002-exec-6] ......
    
    // service-product控制台列印的
    DEBUG [service-product, 79ff7de257120731, c891708ade291c9f,true] 8324 --- [nio-9001-exec-2]......
    
               

    可以看到,上面都是DEBUG開頭,中括号裡第一個參數是服務名,第二個是TraceId(同一個調用鍊的id是相同的),後面跟着的是SpanId,依次調用有一個全局的TraceId,将調用鍊路串起來。仔細分析每個微服務的日志,不難看出請求的具體過程。

    控制台檢視不夠清晰,Zipkin可以将日志聚合,并進行可視化展示和全文檢索。

ZipKin

主要由 4 個核心元件構成:

  • Collector:收集器元件,它主要用于處理從外部系統發送過來的跟蹤資訊,将這些資訊轉換為Zipkin 内部處理的 Span 格式,以支援後續的存儲、分析、展示等功能。
  • Storage:存儲元件,它主要對處理收集器接收到的跟蹤資訊,預設會将這些資訊存儲在記憶體中,我們也可以修改此存儲政策,通過使用其他存儲元件将跟蹤資訊存儲到資料庫中。
  • RESTful API:API 元件,它主要用來提供外部通路接口。比如給用戶端展示跟蹤資訊,或是外接系統通路以實作監控等。
  • Web UI:UI 元件,基于 API 元件實作的上層應用。通過 UI 元件使用者可以友善而有直覺地查詢和分析跟蹤資訊。

Zipkin 分為兩端,一個是 Zipkin 服務端,一個是 Zipkin 用戶端,用戶端也就是微服務的應用。

用戶端會配置服務端的 URL 位址,一旦發生服務間的調用的時候,會被配置在微服務裡面的 Sleuth 的監聽器監聽,并生成相應的 Trace 和 Span 資訊發送給服務端。

發送的方式主要有兩種,一種是 HTTP 封包的方式,還有一種是消息總線的方式如 RabbitMQ。

不論哪種方式,我們都需要:

- 一個 Eureka 服務注冊中心。
- 一個 Zipkin 服務端。
- 多個微服務,這些微服務中配置Zipkin 用戶端。
           
  1. 下載下傳zipkin server(服務端)的啟動jar包

    下載下傳位址:https://search.maven.org/search?q=a:zipkin-server

    選擇版本,一定要選擇exec.jar進行下載下傳(40-60M大小)【建議2.12.9】**

    下載下傳下來後,在cmd指令行輸入

    java -jar zipkin-server-2.12.9-exec.jar

    啟動 Zipkin Server

    【其中的2.12.9是你下載下傳的jar包版本,記得更改】

    啟動參數配置官方文檔:https://github.com/openzipkin/zipkin/blob/master/zipkin-server/src/main/resources/zipkin-server-shared.yml

    浏覽器輸入http://localhost:9411進入Zipkin Server的管理背景

  2. 在需要記錄日志的微服務導入依賴
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zipkin</artifactId>
    </dependency>
               
  3. 修改application.yml (需要收集日志的微服務)
    spring: 
      zipkin:
        base-url: http://127.0.0.1:9411/ #zipkin server的請求位址
        sender:
          type: web #請求方式,預設以http的方式向zipkin server發送追蹤資料
      sleuth:
        sampler:
          probability: 1.0 #采樣的百分比,可以設定0-1的小數,比如設定0.1就是隻收集1/10的資料
               

    重新整理http://localhost:9411 可以看到請求的鍊路,及響應時長等。

    這是通過web方式進行檢視,鍊路資料儲存在記憶體中,重新開機zipkin服務資料會消失。

持久化zipkin資料,存儲在mysql資料庫中

  1. 準備mysql庫及表
CREATE DATABASE /*!32312 IF NOT EXISTS*/`zipkin` /*!40100 DEFAULT CHARACTER SET utf8 */;

USE `zipkin`;

/*Table structure for table `zipkin_annotations` */

DROP TABLE IF EXISTS `zipkin_annotations`;

CREATE TABLE `zipkin_annotations` (
  `trace_id_high` bigint(20) NOT NULL DEFAULT '0' COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit',
  `trace_id` bigint(20) NOT NULL COMMENT 'coincides with zipkin_spans.trace_id',
  `span_id` bigint(20) 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(11) NOT NULL COMMENT 'BinaryAnnotation.type() or -1 if Annotation',
  `a_timestamp` bigint(20) DEFAULT NULL COMMENT 'Used to implement TTL; Annotation.timestamp or zipkin_spans.timestamp',
  `endpoint_ipv4` int(11) DEFAULT NULL COMMENT 'Null when Binary/Annotation.endpoint is null',
  `endpoint_ipv6` binary(16) DEFAULT NULL COMMENT 'Null when Binary/Annotation.endpoint is null, or no IPv6 address',
  `endpoint_port` smallint(6) DEFAULT NULL COMMENT 'Null when Binary/Annotation.endpoint is null',
  `endpoint_service_name` varchar(255) DEFAULT NULL COMMENT 'Null when Binary/Annotation.endpoint is null',
  UNIQUE KEY `trace_id_high` (`trace_id_high`,`trace_id`,`span_id`,`a_key`,`a_timestamp`) COMMENT 'Ignore insert on duplicate',
  KEY `trace_id_high_2` (`trace_id_high`,`trace_id`,`span_id`) COMMENT 'for joining with zipkin_spans',
  KEY `trace_id_high_3` (`trace_id_high`,`trace_id`) COMMENT 'for getTraces/ByIds',
  KEY `endpoint_service_name` (`endpoint_service_name`) COMMENT 'for getTraces and getServiceNames',
  KEY `a_type` (`a_type`) COMMENT 'for getTraces',
  KEY `a_key` (`a_key`) COMMENT 'for getTraces',
  KEY `trace_id` (`trace_id`,`span_id`,`a_key`) COMMENT 'for dependencies job'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPRESSED;

/*Data for the table `zipkin_annotations` */

/*Table structure for table `zipkin_dependencies` */

DROP TABLE IF EXISTS `zipkin_dependencies`;

CREATE TABLE `zipkin_dependencies` (
  `day` date NOT NULL,
  `parent` varchar(255) NOT NULL,
  `child` varchar(255) NOT NULL,
  `call_count` bigint(20) DEFAULT NULL,
  UNIQUE KEY `day` (`day`,`parent`,`child`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPRESSED;

/*Data for the table `zipkin_dependencies` */

/*Table structure for table `zipkin_spans` */

DROP TABLE IF EXISTS `zipkin_spans`;

CREATE TABLE `zipkin_spans` (
  `trace_id_high` bigint(20) NOT NULL DEFAULT '0' COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit',
  `trace_id` bigint(20) NOT NULL,
  `id` bigint(20) NOT NULL,
  `name` varchar(255) NOT NULL,
  `parent_id` bigint(20) DEFAULT NULL,
  `debug` bit(1) DEFAULT NULL,
  `start_ts` bigint(20) DEFAULT NULL COMMENT 'Span.timestamp(): epoch micros used for endTs query and to implement TTL',
  `duration` bigint(20) DEFAULT NULL COMMENT 'Span.duration(): micros used for minDuration and maxDuration query',
  UNIQUE KEY `trace_id_high` (`trace_id_high`,`trace_id`,`id`) COMMENT 'ignore insert on duplicate',
  KEY `trace_id_high_2` (`trace_id_high`,`trace_id`,`id`) COMMENT 'for joining with zipkin_annotations',
  KEY `trace_id_high_3` (`trace_id_high`,`trace_id`) COMMENT 'for getTracesByIds',
  KEY `name` (`name`) COMMENT 'for getTraces and getSpanNames',
  KEY `start_ts` (`start_ts`) COMMENT 'for getTraces ordering and range'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPRESSED;

/*Data for the table `zipkin_spans` */

/*!40101 SET [email protected]_SQL_MODE */;
/*!40014 SET [email protected]_FOREIGN_KEY_CHECKS */;
/*!40014 SET [email protected]_UNIQUE_CHECKS */;
/*!40111 SET [email protected]_SQL_NOTES */;

           
  1. 修改server啟動指令

    ​ 官方文檔 :https://github.com/openzipkin/zipkin/blob/master/zipkin-server/src/main/resources/zipkin-server-shared.yml

    cmd啟動指令:

    java -jar zipkin-server-2.12.9-exec.jar --STORAGE_TYPE=mysql --MYSQL_HOST=127.0.0.1 --MYSQL_TCP_PORT=3306 --MYSQL_DB=zipkin --MYSQL_USER=root --MYSQL_PASS=111111

    上面的指令記得修改mysql的登陸密碼。

    啟動之後,自動連接配接資料庫,資料儲存在mysql中,重新開機也支援檢視之前資料。

使用消息中間件RabbitMQ收集資料

Zipkin用戶端和Server之間是使用HTTP請求的方式進行通信(即同步的請求方式)影響響應效率。Zipkin支援與rabbitMQ整合完成異步消息傳輸。

  1. 準備RabbitMQ

    安裝RabbitMQ ,可檢視部落格https://blog.csdn.net/qq_43220949/article/details/113134782

    輸入指令 進行啟動:

    rabbitmq-server.bat

    浏覽器輸入http://localhost:15672,預設密碼賬号都是

    guest

  2. 修改zipkin服務端從rabbit拉取消息

    重新啟動zipkin服務端,指令為:

    java -jar zipkin-server-2.12.9-exec.jar --RABBIT_ADDRESSES=127.0.0.1:5672

    (RabbitMQ的TCP端口為5672,web管理工具端口為15672)
  3. 修改zipkin用戶端,将消息以rabbit形式發送到mq伺服器

    a. 依賴

    給需要給RabbitMQ發送請求的服務都配置上依賴

    <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>
    
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-sleuth-zipkin</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.amqp</groupId>
        <artifactId>spring-rabbit</artifactId>
    </dependency>
               

    ​ b. 修改application.yml

    給需要給RabbitMQ發送請求的服務都修改application.yml,然後重新開機服務。

    • 修改zipkin的配置
    • 添加rabbitmq
    spring:
      zipkin:
    #base-url: http://127.0.0.1:9411/ #zipkin server的請求位址
      sender:
        type: rabbit
    #type: web #請求方式,預設以http的方式向zipkin server發送追蹤資料
      sleuth:
        sampler:
          probability: 1.0 #采樣的百分比
      rabbitmq:
        host: localhost
        port: 5672
        username: guest
        password: guest
        listener: # 這裡配置了重試政策
          direct:
            retry:
              enabled: true
          simple:
            retry:
              enabled: true
               

    當ZipkinServer不可用時(比如關閉、網絡不通等),追蹤資訊不會丢失,因為這些資訊會儲存在Rabbitmq伺服器上,直到Zipkin伺服器可用時,再從Rabbitmq中取出這段時間的資訊。

    rabbitmq配置好後:sleuth來收集鍊路資料,傳輸到rabbitmq,zipkin從rabbitmq讀取資料。

order服務通路路徑:http://localhost:8080/order/buy/1

product服務通路路徑:http://localhost:8080/order/buy/1

order服務和product服務除了springcloud-zuul項目中,其他項目路徑不變。

eureka通路路徑;http://localhost:9000/

rabbitmq通路路徑:http://localhost:15672/#/

zipkin通路路徑:http://localhost:9411

項目源碼:https://gitee.com/hxmkd/spring-cloud/tree/master/study_springcloud9_sleuth&zipkin