微服務整合Spring Cloud Zipkin實現鏈路追蹤並整合Dubbo

sowler發表於2024-04-07

1、什麼是ZipKin

Zipkin 是一個根據 Google 發表的論文“ Dapper” 進行開源實現的分散式跟蹤系統。 Dapper是Google 公司內部的分散式追蹤系統,用於生產環境中的系統分散式跟蹤。 Google在其論文中對此進行了解釋,他們“構建了Dapper,以向Google開發人員提供有關複雜分散式系統行為的更多資訊。”從不同角度觀察系統對於故障排除至關重要,在系統複雜且分散式的情況下更是如此。Zipkin可幫助您準確確定對應用程式的請求在哪裡花費了更多時間。無論是程式碼內部的呼叫,還是對另一服務的內部或外部API呼叫,您都可以對系統進行檢測以共享上下文。微服務通常透過將請求與唯一ID相關聯來共享上下文。此外,在系統太複雜的情況下,可以選擇僅使用樣本追蹤 (sample trace ,一種佔用資源比例更低的追蹤方式) 來減少系統開銷。

官網地址: https://zipkin.io/

Github地址:https://github.com/openzipkin/zipkin

2、安裝Zipkin

在 SpringBoot 2.x 版本後就不推薦自定義 zipkin server 了,推薦使用官網下載的 jar 包方式也就是說我們不需要編寫一個zipkin服務了,而改成直接啟動jar包即可。

老版本jar下載地址:

https://search.maven.org/remote_content?g=io.zipkin.java&a=zipkin-server&v=LATEST&c=exec

老版本檢視其他版本資訊下載
https://central.sonatype.com/artifact/io.zipkin.java/zipkin-server/versions

最新版本的服務jar下載地址:

https://search.maven.org/remote_content?g=io.zipkin&a=zipkin-server&v=LATEST&c=exec

最新版本檢視其他版本資訊下載
https://central.sonatype.com/artifact/io.zipkin/zipkin-server/versions

下載快速啟動指令碼:

https://zipkin.io/quickstart.sh

這裡使用ZipKin老版本:zipkin-server-2.12.9-exec.jar

執行:

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

# 或整合RabbitMQ

java -jar zipkin-server-2.12.9-exec.jar --zipkin.collector.rabbitmq.addresses=127.0.0.1

3、資訊持久化啟動

鏈路資訊預設是存在記憶體中,下一次ZipKin重啟後資訊就會消失,所以需要資訊持久化。官方提供了Elasticsearch方式與Mysql兩種儲存方式。本篇使用Mysql進行持久化,在正式環境推薦使用Elasticsearch進行持久化。首先建立一個zipkin資料庫,然後下載資料庫指令碼: https://github.com/openzipkin/zipkin/blob/2.12.9/zipkin-storage/mysql-v1/src/main/resources/mysql.sql 或者複製以下sql語句在zipkin資料庫中執行。

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',
  PRIMARY KEY (`trace_id_high`, `trace_id`, `id`)
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;

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 and autocomplete values';
ALTER TABLE zipkin_annotations ADD INDEX(`a_key`) COMMENT 'for getTraces and autocomplete values';
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,
  `error_count` BIGINT,
  PRIMARY KEY (`day`, `parent`, `child`)
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;

啟動命令

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=1234qwer

啟動成功訪問服務:http://127.0.0.1:9411/zipkin/

4、微服務整合Zipkin

4.1、 引入Maven依賴
        <!--依賴包含了sleuth,所以不需要再單獨引入sleuth-->
        <!-- sleuth :鏈路追蹤器  zipkin :鏈路分析器-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
        </dependency>
        <!--如果上面依賴飄紅引不進來,那麼原因可能是你使用的cloud版本已經移除了spring-cloud-starter-zipkin 則需要引入以下依賴-->
<!--        <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>-->
4.2、 配置ZipKin資訊

使用者模組配置:

spring:
  profiles:
    active: dev
  application:
    # 服務名稱
    name: user-service-model
  zipkin:
    enabled: true #是否啟用
    #zipkin服務所在地址
    base-url: http://127.0.0.1:9411/
    sender:
      type: web #使用http的方式傳輸資料到, Zipkin請求量比較大,可以透過訊息中介軟體來傳送,比如 RabbitMQ
    #配置取樣百分比
    sleuth:
      sampler:
        probability: 1 # 將取樣比例設定為 1.0,也就是全部都需要。預設是0.1也就是10%,一般情況下,10%就夠用了

訂單模組配置:

spring:
  profiles:
    active: dev
  application:
    # 服務名稱
    name: order-service-model
  zipkin:
    enabled: true
    #zipkin服務所在地址
    base-url: http://localhost:9411/
    sender:
      type: web #使用http的方式傳輸資料到, Zipkin請求量比較大,可以透過訊息中介軟體來傳送,比如 RabbitMQ
    #配置取樣百分比
    sleuth:
      sampler:
        probability: 1 # 將取樣比例設定為 1.0,也就是全部都需要。預設是0.1也就是10%,一般情況下,10%就夠用了

配置成功後,啟動gateway-module、user-module、order-module模組相關服務。啟動成功訪問後臺服務介面,可以看到在zipkin中已經載入了相關請求資訊。

然後我們可以在看看資料庫,檢查下zipkin在資料庫中資訊是否持久化成功。檢視下圖可以發現資料也已經持久化成功了,這樣不管zipkin重啟多少次都不影響資料的展示。

5、ZipKin整合Dubbo

由於專案使用的是dubbo做為各服務模組之間的通訊呼叫,要想zipkin採集到各服務模組的呼叫資訊,所以需要自己去整合。操作也很方便zipkin為我們提供了整合dubbo相關依賴。首先在dubbo提供者和消費者模組中引入maven依賴:

		<!--適用於 Dubbo 2.7.X 版本-->
        <dependency>
            <groupId>io.zipkin.brave</groupId>
            <artifactId>brave-instrumentation-dubbo</artifactId>
        </dependency>
		<!--適用於 Dubbo 2.6.x-->
        <dependency>
            <groupId>io.zipkin.brave</groupId>
            <artifactId>brave-instrumentation-dubbo-rpc</artifactId>
        </dependency>

然後在dubbo配置中新增filter屬性設定tracing引數,呼叫方:

dubbo:
  application:
    name: order-service-model-consumer
  consumer:
    group: DEFAULT_GROUP
    version: 2.0
    check: false
    filter: tracing  #tracingfilter過濾器對dubbo進行追蹤
  provider:
    filter: tracing  #tracingfilter過濾器對dubbo進行追蹤

提供方:

dubbo:
  application:
    name: user-service-model-provider
  protocol:
    name: dubbo
    port: -1
  consumer:
    check: false
    filter: tracing #tracingfilter過濾器對dubbo進行追蹤
  provider:
    filter: tracing #tracingfilter過濾器對dubbo進行追蹤
    group: DEFAULT_GROUP
    version: 2.0

配置成功後,重新啟動專案服務介面可以看出zipkin實現了對dubbo的鏈路追蹤。檢視下圖可以發現該介面呼叫了訂單和使用者兩個服務模組。

點選user-service-model可以檢視出採集資訊詳情。

在zipkin導航選單中,點選依賴可以檢視每個服務模組的依賴資訊。

相關文章