SpringCloud 之 Zipkin + Sleuth 服務鏈路追蹤搭建與講解
前言
Zipkin: 負責接收 Sleuth
發來的跟蹤數據,進行存儲,UI 可視化。
Sleuth: 微服務跟蹤(Sleuth)其實是一個工具,它在整個分佈式系統中能跟蹤一個用戶請求的過程(包括數據採集,數據傳輸,數據存儲,數據分析,數據可視化),捕獲這些跟蹤數據,就能構建微服務的整個調用鏈的視圖,這是調試和監控微服務的關鍵工具。
基本概念
Span(跨度): 基本工作單元。我將它理解成一個個的事件節點,它還包含:描述,時間戳等。
Trace(跟蹤): Span
組成的樹狀結構稱爲 Trace
,Trace
中的所有 Span
都共享該 Trace
的ID。
Annotation(標註): Annotation
用來記錄事件的存在,其中核心 Annotation
用來定義請求的開始和結束。
- cs(Client Sent): 客戶端發起一個請求,這個註釋指示了一個
Span
的開始。 - sr(Server Received): 服務端接收請求並開始處理它,如果用
sr
時間戳減去cs
時間戳便能看出有多少網絡延遲。 - ss(Server Sent): 註釋請求處理完成(響應已發送給客戶端),如果用
ss
時間戳減去sr
時間戳便可得出服務端處理請求耗費的時間。 - cr(Client Received): 預示了一個
Span
的結束,客戶端成功地接收到了服務端的響應,如果用cr
時間戳減去cs
時間戳便可得出客戶端從服務端獲得響應所需耗費的整個時間。
Zipkin 安裝
下載 Zipkin-Server.jar
wget -O zipkin.jar 'https://search.maven.org/remote_content?g=io.zipkin.java&a=zipkin-server&v=LATEST&c=exec'
或者手動下載:Zipkin-Server
啓動 Zipkin 並持久化數據到數據庫
PS:Zipkin 默認存儲在內存裏的,即浪費內存又存在宕機丟失數據的隱患。如果知識跑着玩下,可以直接 java -jar zipkin.jar 直接啓動即可
建表
官方:mysql.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;
啓動
參考:官方文檔
下面我給出我啓動的示例:
--STORAGE_TYPE=mysql
:類別爲 mysql--MYSQL_HOST=127.0.0.1
:設置數據庫 Host--MYSQL_TCP_PORT=7000
:設置數據庫端口號--MYSQL_DB=zipkin
:設置庫名--MYSQL_USER=root
:數據庫賬號--MYSQL_PASS=123456
:數據庫密碼
java -jar zipkin.jar \
--STORAGE_TYPE=mysql \
--MYSQL_HOST=127.0.0.1 \
--MYSQL_TCP_PORT=7000 \
--MYSQL_DB=zipkin \
--MYSQL_USER=root \
--MYSQL_PASS=123456
訪問 Zipkin
默認端口爲 9411
http://localhost:9411/zipkin/
客戶端配置
即需要被追蹤的服務新增配置,使得他的調用信息能夠發送到 Zipkin Server
加註解
<!-- sleuth + zipkin -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>
加配置
spring:
# zipkin 配置
zipkin:
base-url: http://localhost:9411/ # zipkin服務器的地址
sender:
type: web # 設置使用http的方式傳輸數據
# sleuth 配置
sleuth:
sampler:
probability: 1 # 設置抽樣採集爲100%,默認爲0.1,即10%
基本使用
查找
UI 界面:
點擊一個請求:
可以看到中間經歷了哪些的事件,比如:可以看到 feign-demo
在發送請求到 service-a
前還經歷了一層斷路器 Hystrix
,因此我們知道,從這裏開始斷路器開始監控發送給 service-a
的請求,如果這個請求掛了,就進行斷路。
點擊一個 Span 詳情:
可以看到更加詳細的調用相求,內容都看得懂,就不多介紹了
依賴
可以看到調用的鏈路
點擊其中一個節點,比如 feign-demo
點擊 Zuul
看看裏面的信息
可以看到我調用了 4 次,還沒有失敗的
請求失敗
來看看如果調用失敗的情況,這裏我把 service-a
服務停止了,因此調用失敗,feign
進行了降級處理
Zipkin-Server
這也可以看到服務調用出現了問題
這裏由於調用失敗,所以異常由自己來處理
點擊進去,可以看到失敗的次數,我剛調用了兩次,因此失敗了兩次