SpringCloudAlibaba整合Sleuth+Zipkin
有關Sleuth之前有寫過兩篇文章
Spring Cloud Alibaba(13)---Sleuth概述
Spring Cloud Alibaba(14)---SpringCloudAlibaba整合Sleuth
上篇文章我們通過列印日誌的方式,看到一個請求的完整鏈路。但是當微服務越來越多日誌檔案也會越來越多,查詢工作會變得越來越麻煩,所以這篇我們通過 Zipkin 進行
鏈路跟蹤。Zipkin 可以將日誌聚合,並進行視覺化展示和全文檢索。
一、Zipkin客戶端搭建
1、快速開始
Zipkin是通過jar的方式執行的,所以我們去官方下載相應的jar包
https://github.com/openzipkin/zipkin
在 Quick-start 下面的連結直接下載官方提供的jar包,當前的版本是 zipkin-server-2.23.2-exec.jar,通過java命令執行。
java -jar zipkin-server-2.23.2-exec.jar
啟動之後訪問zipkin地址
http://127.0.0.1:9411/zipkin/
可以看出,Zipkin的客戶端已經搭建好了。
接下來我們在我們專案中新增相關zipkin配置。
二、SpringCloudAlibaba整合Zipkin
注意
這篇也是在上篇SpringCloudAlibaba已經整合Sleuth的基礎上在整合Zipkin,所以這裡也不把所有程式碼都複製在這裡,完整專案程式碼會放到github上。
1、pom.xml
在需要進行鏈路追蹤的專案中(服務閘道器、商品服務、訂單服務)新增 spring-cloud-starter-zipkin 依賴。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
2、application.yml
spring:
zipkin:
base-url: http://127.0.0.1:9411/ #zipkin地址
discovery-client-enabled: false #不用開啟服務發現
sleuth:
sampler:
probability: 1.0 #取樣百分比
這裡取樣百分比說下: 如果服務的流量很大,全部採集對傳輸、儲存壓力比較大。這個時候可以設定取樣率(如配置為1.0,則取樣率為100%,採集服務的全部追蹤資料),
若不配置預設取樣率是0.1(即10%)。這裡為了等下演示更明顯,所以設定100%抽取。
3、測試
這裡整個請求鏈路如下圖:
這裡一個完整的鏈路是 一個請求通過閘道器服務
,然後轉發到 訂單微服務
,然後訂單微服務中會去調商品服務
。
訪問地址如下:
#通過閘道器訪問訂單服務
http://localhost:8001/mall-order/api/v1/goods_order/getGoodsByFeign?goodsId=1
請求已經成功,接下來我們來看zipkin客戶端
發現客戶端已經有一條鏈路,而且順序是 mall-gateway (3) -> mall-order (2) -> mall-goods (1) 跟我們實際請求的順序吻合。
同時我們還可以看具體每個微服務的執行時間
從這個圖可以看出整個請求鏈路總共花多少時間,每個微服務的執行花費時間。這樣在實際生產場景中如果當前請求響應很慢,那我們可以通過zipkin客戶端就就可以看出哪個服務
執行時間較慢,進而優化。
三、 Zipkin+Mysql持久化
Zipkin Server 預設儲存追蹤資料至記憶體中
,這種方式並不適合生產環境,一旦 Server 關閉重啟或者服務崩潰,就會導致歷史資料消失。Zipkin 支援修改儲存策略使用其他
儲存元件,支援 MySQL,Elasticsearch 等。
1、Mysql資料庫指令碼
開啟 MySQL 資料庫,建立 zipkin
庫,執行以下 SQL 指令碼。
官網地址:https://github.com/openzipkin/zipkin/blob/master/zipkin-storage/mysql-v1/src/main/resources/mysql.sql
所有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,
`remote_service_name` VARCHAR(255),
`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(`remote_service_name`) COMMENT 'for getTraces and getRemoteServiceNames';
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;
2、部署Zipkin
上面是我們是通過直接 java -jar zipkin-server-2.23.2-exec.jar 啟動的,這裡我們在啟動的時候去指定Mysql配置資訊
java -jar zipkin-server-2.23.2-exec.jar --STORAGE_TYPE=mysql --MYSQL_HOST=localhost --MYSQL_TCP_PORT=3306 --MYSQL_USER=root --MYSQL_PASS=root --MYSQL_DB=zipkin
啟動之後我們再訪問上面的介面
#通過閘道器訪問訂單服務
http://localhost:8001/mall-order/api/v1/goods_order/getGoodsByFeign?goodsId=1
請求成功後,我們在來看資料庫
很明顯資料庫已經把資料固化下來了,這樣的話就算我們重啟zipkin,資料都不會丟失,客戶端一直可以查詢到。
總結
Spring Cloud Alibaba 系列文章到這裡先告一段落了,後期在開發中遇到實際生產問題,在來總結。
github地址
nacos-feign-sentinel-gatway-sleuth
少說多做,句句都會得到別人的重視;多說少做,句句都會受到別人的忽視。(15)