基礎知識儲備
分布式跟蹤的目标
一個分布式系統由若幹分布式服務構成,每一個請求會經過多個業務系統并留下足迹,但是這些分散的資料對于問題排查,或是流程優化都很有限,要能做到追蹤每個請求的完整鍊路調用,收集鍊路調用上每個服務的性能資料,計算性能資料和比對性能名額(SLA),甚至能夠再回報到服務治理中,那麼這就是分布式跟蹤的目标。
分布式跟蹤的目的
zipkin分布式跟蹤系統的目的:
- zipkin為分布式鍊路調用監控系統,聚合各業務系統調用延遲資料,達到鍊路調用監控跟蹤;
- zipkin通過采集跟蹤資料可以幫助開發者深入了解在分布式系統中某一個特定的請求時如何執行的;
- 假如我們現在有一個使用者請求逾時,我們就可以将這個逾時的請求調用鍊展示在UI當中;我們可以很快度的定位到導緻響應很慢的服務究竟是什麼。如果對這個服務細節也很很清晰,那麼我們還可以定位是服務中的哪個問題導緻逾時;
- zipkin系統讓開發者可通過一個Web前端輕松的收集和分析資料,例如使用者每次請求服務的處理時間等,可友善的監測系統中存在的瓶頸。
ZipKin介紹
- Zipkin是一個緻力于收集分布式服務的時間資料的分布式跟蹤系統。
- Zipkin 主要涉及四個元件:collector(資料采集),storage(資料存儲),search(資料查詢),UI(資料展示)。
- github源碼位址: https://github.com/openzipkin/zipkin 。
- Zipkin提供了可插拔資料存儲方式:In-Memory,MySql, Cassandra, Elasticsearch
brave 介紹
Brave 是用來裝備 Java 程式的類庫,提供了面向标準Servlet、Spring MVC、Http Client、JAX RS、Jersey、Resteasy 和 MySQL 等接口的裝備能力,可以通過編寫簡單的配置和代碼,讓基于這些架構建構的應用可以向 Zipkin 報告資料。同時 Brave 也提供了非常簡單且标準化的接口,在以上封裝無法滿足要求的時候可以友善擴充與定制。
本文主要介紹springmvc+dubbo下的brave使用。
dubbo項目下快速搭建zipkin、brave追蹤系統
1、zipkin安裝使用
此處主要介紹linux下的安裝使用,zipkin官網位址
http://zipkin.io/pages/quickstart.htmlwget -O zipkin.jar 'https://search.maven.org/remote_content?g=io.zipkin.java&a=zipkin-server&v=LATEST&c=exec'
說明:zipkin是springboot項目,該jar包可直接通過java -jar zipkin.jar啟動。啟動完成後可通路
http://ip:9411檢視。
2、zipkin存儲與啟動
詳情參考官網:
https://github.com/openzipkin/zipkin/tree/master/zipkin-server(1)In-Memory方式
nohup java -jar zipkin.jar &
注意:記憶體存儲,zipkin重新開機後資料會丢失,建議測試環境使用
(2)MySql方式
目前隻與MySQL的5.6-7。它的設計是易于了解,使用簡單。但是,當資料量大時,查詢很慢。性能不是很好。
- 建立資料庫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'
) 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指令
$ STORAGE_TYPE=mysql MYSQL_HOST=IP MYSQL_TCP_PORT=3306 MYSQL_DB=zipkin MYSQL_USER=username MYSQL_PASS=password nohup java -jar zipkin.jar &
(3)Elasticsearch方式
本文建議使用此方法。
- Elasticsearch官網
- 建立elasticsearch使用者,安裝啟動Elasticsearch服務
- 官方文檔: https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html
- zipkin啟動指令
$ STORAGE_TYPE=elasticsearch ES_HOSTS=http://IP:9200 nohup java -jar zipkin.jar &
3、dubbo項目快速接入
(1)、項目pom中添加brave-dubbo.jar的依賴, brave-dubbo 簡化dubbo項目接入zipkin的步驟。
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-dubbo</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
(2)、在spring-application.xml中配置brave
<bean id="brave" class="com.github.kristofa.brave.dubbo.BraveFactoryBean" p:serviceName="serviceName" p:zipkinHost="http://zipkin-server-ip:9411/" p:rate="1.0" />
說明:
- zipkin-server-ip 是zipkin伺服器ip位址。
- p:serviceName 項目名稱。
- 隻要是dubbo項目,無論是普通服務,還是web項目,都需要添加此包,并配置brave Bean。
4、大功告成
此時,你可以看到如下效果。

Paste_Image.png
各個服務之間的調用關系及響應時間