Spring Cloud 鏈路追蹤

Ybb_studyRecord發表於2020-10-05

一、概念

1.1 鏈路追蹤

使用者->閘道器->A->B->C->D

分散式系統中一次呼叫會非常的複雜。我們需要更好的發現問題,定位問題是在哪個微服務中出現的。分析在各個定義節點的耗時確認效能瓶頸等。

分散式鏈路追蹤,就是將一次分散式請求還原成呼叫鏈路,進行日誌記錄效能監控並將 一次分散式請求的呼叫情況集中展示。比如各個服務節點上的耗時、請求具體到達哪臺機器上、每個服務節點的請求狀態等等。

1.2 各種系統

目前業界比較流行的鏈路追蹤系統如:Twitter的Zipkin,阿里的鷹眼,美團的Mtrace,大眾點評的
cat等,大部分都是基於google發表的Dapper。Dapper闡述了分散式系統,特別是微服務架構中鏈路
追蹤的概念、資料表示、埋點、傳遞、收集、儲存與展示等技術細節。

二、重要概念

trace 整個呼叫鏈路

完整的一次呼叫,比如使用者A->閘道器->B->C 可以定義為 traceid:1

span 最小的工作單元(鏈路中的一個節點的呼叫)

使用者A->閘道器 spanid:1

閘道器->B spanid:2

B->C spanid:3

三、實現(sleuth+zipkin)

sleuth

1.概念

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

2.依賴和配置

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-sleuth</artifactId>
        </dependency>
logging:
  level:
    root: INFO
    org.springframework.web.servlet.DispatcherServlet: DEBUG
    org.springframework.cloud.sleuth: DEBUG

zipkin

1.概念

Zipkin 是 Twitter 的一個開源專案,它基於 Google Dapper 實現,它致力於收集服務的定時資料,以
解決微服務架構中的延遲問題,包括資料的收集、儲存、查詢和展現。 我們可以使用它來收集各個服務
器上請求鏈路的跟蹤資料,並通過它提供的 REST API 介面來輔助我們查詢跟蹤資料以實現對分散式系
統的監控程式,從而及時地發現系統中出現的延遲升高問題並找出系統效能瓶頸的根源。除了面向開發
的 API 介面之外,它也提供了方便的 UI 元件來幫助我們直觀的搜尋跟蹤資訊和分析請求鏈路明細,比
如:可以查詢某段時間內各使用者請求的處理時間等。 Zipkin 提供了可插拔資料儲存方式:InMemory、MySql、Cassandra 以及 Elasticsearch。

主要是收集鏈路追蹤的日誌然後進行儲存展示等功能

2.zipkin架構圖

Collector:收集器元件,它主要用於處理從外部系統傳送過來的跟蹤資訊,將這些資訊轉換為

Zipkin 內部處理的 Span 格式,以支援後續的儲存、分析、展示等功能。

Storage:儲存元件,它主要對處理收集器接收到的跟蹤資訊,預設會將這些資訊儲存在記憶體中,

我們也可以修改此儲存策略,通過使用其他儲存元件將跟蹤資訊儲存到資料庫中。

RESTful API:API 元件,它主要用來提供外部訪問介面。比如給客戶端展示跟蹤資訊,或是外接

系統訪問以實現監控等。

Web UI:UI 元件,基於 API 元件實現的上層應用。通過 UI 元件使用者可以方便而有直觀地查詢和

分析跟蹤資訊。
在這裡插入圖片描述
每個被追蹤的微服務作為zipkin客戶端,收集資料處理資料的是zipkin的服務端

2.使用

Zipkin Server

從spring boot 2.0開始,官方就不再支援使用自建Zipkin Server的方式進行服務鏈路追蹤,而是直接提
供了編譯好的 jar 包來給我們使用。可以從官方網站下載先下載Zipkin的web UI,我們這裡下載的是
zipkin-server-2.12.9-exec.jar

啟動命令

在命令列輸入 java -jar zipkin-server-2.12.9-exec.jar 啟動 Zipkin Server

預設Zipkin Server的請求埠為 9411

下載地址

https://github.com/openzipkin/zipkin/blob/master/zipkin-server/src/main/resources/zipkin-server-shared.yml

Zipkin Client

依賴

        <dependency>
           <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
        </dependency>
spring:
  zipkin:
    base-url: http://127.0.0.1:9411/ #zipkin server的請求地址
    sender:
      type: web #請求方式,預設以http的方式向zipkin server傳送追蹤資料
  sleuth:
    sampler:
      probability: 1.0 #取樣的百分比 生產環境中不用1.0

問題和優化

問題

1.http請求和fegin呼叫的時候,會出現問題(原始碼級別)

2.放入記憶體中,關閉了就沒了

優化

使用rabbitmq發生和接收日誌

Server

啟動 Zipkin Server時指定rabbitmq地址和使用者密碼資訊

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

java -jar zipkin-server-2.12.9-exec.jar --RABBIT_ADDRESSES=192.168.200.128:5672 --RABBIT_USER=guest --RABBIT_PASSWORD=guest

Client

依賴

<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>

配置rabbitmq相關資訊

spring:
  zipkin:
    base-url: http://127.0.0.1:9411/ #zipkin server的請求地址
    sender:
      type: rabbit #請求方式,預設以http的方式向zipkin server傳送追蹤資料
  rabbitmq:
    host: 192.168.200.128 #自己rabbitmq的ip地址
    port: 5672
    username: guest 
    password: guest
    listener:
      direct:
        retry:
          enabled: true
      simple:
        retry:
          enabled: true

資料儲存到mysql

建立資料庫表

建立資料庫zipkin 然後執行下面的sql

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`);

啟動 Zipkin Server時指定mysql相關資訊

只吧資料儲存到mysql的啟動命令,裡面沒有配置rabbit的資訊

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
STORAGE_TYPE : 儲存型別
MYSQL_HOST: mysql主機地址
MYSQL_TCP_PORT:mysql埠
MYSQL_DB: mysql資料庫名稱
MYSQL_USER:mysql使用者名稱
MYSQL_PASS :mysql密碼

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=root --RABBIT_ADDRESSES=192.168.200.128:5672 --RABBIT_USER=guest --RABBIT_PASSWORD=guest

相關文章