1. 程式人生 > 其它 >隨時用隨時翻:微服務鏈路追蹤之zipkin搭建

隨時用隨時翻:微服務鏈路追蹤之zipkin搭建

前言

微服務治理方案中,鏈路追蹤是必修課,SpringCloud的元件其實使用很簡單,生產環境中真正令人頭疼的往往是軟體維護,介面在微服務間的呼叫究竟哪個環節出現了問題,哪個環節耗時較長,這都是專案上線後一定會遇到的問題,為了解決這些問題鏈路追蹤便應運而生了。

主流方案

1)、SkyWalking:這應該是目前最主流的方案了,我所在公司今年的新專案就開始使用這個,效果確實很顯著,功能強大,最重要還是國產的,後面不用看了我們支援國產吧!開個玩笑哈哈,其實這個框架也有缺點,就是稍微有點重,比較適合稍大一點的專案,但可預見後面幾年都是最受歡迎的方案;

2)、Zipkin

:這個是老牌鏈路追蹤方案,已經被非常多專案驗證過實用性,相比較於SkyWalking,我個人更喜歡這個框架,因為更輕量級,安裝也非常簡單,是中小規模的微服務專案首選方案。

用法

1、zipkin環境搭建

官方提供了docker版本,十分簡單。也可以下載編譯好的zipkin.jar來執行,是springboot專案。

官網:https://zipkin.io/pages/quickstart.html

1)、啟動

預設埠號啟動zipkin服務,預設埠9411.

java -jar zipkin.jar

2)、指定埠號

java -jar zipkin.jar --server.port=8080

3)、指定訪問RabbitMQ

java -jar zipkin.jar --zipkin.collector.rabbitmq.addresses=127.0.0.1

4)、啟動效果

2、SpringCloud整合zipkin

springcloud其它基礎依賴包引入這裡省略,直接模擬場景。

會員服務:zipkin_member

訂單服務:zipkin_order

訊息服務:zipkin_msg

過程:會員服務呼叫訂單服務,訂單服務呼叫訊息服務。

1)、引入依賴

<!-- zipkin --><dependency>    <groupId>org.springframework.cloud</groupId>    <artifactId>spring-cloud-starter-zipkin</artifactId></dependency>

2)、application.yml配置

注意事項:

a)、加上服務名,RestTemplate呼叫時會用到;

b)、加上zipkin服務端地址;

c)、加上probability採集率設定,預設0.1,測試環境改為1.0保證每次都採集,生產環境適當抽樣即可。(因為10000個請求抽樣1000個也能發現問題了,沒必要全部都採集)

3)、引入RestTemplate

這裡restTemplate主要用來進行介面呼叫檢視鏈路追蹤是否生效

@Componentpublic class RestTemplateConfig {        @Bean    @LoadBalanced    public RestTemplate restTemplate() {        return new RestTemplate();    }}

4)、controller呼叫

會員呼叫訂單

訂單呼叫訊息

訊息處理具體業務

5)、檢視效果

啟動Zipkin服務端,訪問:http://127.0.0.1:9411

執行controller介面

檢視鏈路追蹤,可以看到,介面呼叫的鏈路已經在zipkin顯現了。

3、zipkin整合RabbitMQ非同步採集

springboot2.0之後,官方不再推薦使用自建的zipkin server,而是直接使用編譯好的zipkin.jar來給我們使用。

zipkin.jar中的yml配置可以參考:https://github.com/openzipkin/zipkin/blob/master/zipkin-server/src/main/resources/zipkin-server-shared.yml

1)、指定RabbitMQ為伺服器

啟動zipkin服務時指定rabbitmq為伺服器即可,得先啟動rabbitmq伺服器。

java -jar zipkin.jar --zipkin.collector.rabbitmq.addresses=192.168.239.132

啟動之後,可以發現rabbitmq中會自動新增一個zipkin佇列,表示繫結成功。

2)、引入中間依賴

給每個微服務引入stream和rabbitmq的中介軟體依賴

<!-- 引入和rabbitmq的中間依賴 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-stream-binder-rabbit</artifactId></dependency>

3)、yml配置

修改每個微服務的application.yml,加上rabbitmq的配置。

rabbitmq:     host: 192.168.239.132    port: 5672    username: guest    password: guest

4)、啟動和呼叫

啟動微服務,執行呼叫。

5)、MQ是否收到訊息

看rabbitmq是否有收訊息,佇列有反應說明rabbitmq收到訊息了。

6)、Zipkin是否採集資訊

看zipkin是否採集了鏈路資訊

7)、驗證積壓訊息

關掉zipkin服務,看訊息是否會積壓在rabbitmq,再啟動zipkin服務,看訊息是否會被消費並且獲取到鏈路資訊。

獲取訊息檢視,發現獲取到的就是traceId相關的json資料,證明整個過程都是正常的。

重新再啟動zipkin服務,發現rabbitmq積壓的訊息就被消費了。

並且也能獲取到鏈路資訊

4、zipkin使用MySQL儲存

zipkin.jar中的yml配置可以參考,裡面有關於mysql的配置或者其他如elasticsearch的配置:

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

這節我們在上一節MQ的基礎上增加MySQL的啟動配置項

1)、指定MySQL

命令看著很長,其實仔細看發現很簡單,都是見名知義,不必死記硬背。

java -jar zipkin.jar

--zipkin.collector.rabbitmq.addresses=192.168.239.132

--zipkin.storage.type=mysql

--zipkin.storage.mysql.host=127.0.0.1

--zipkin.storage.mysql.port=3306

--zipkin.storage.mysql.username=root

--zipkin.storage.mysql.password=123456

--zipkin.storage.mysql.db=zipkin

2)、建立zipkin資料庫

根據1中命令配置的資訊,建立zipkin資料庫,並執行語句建立zipkin採集記錄的三張表。

參考官網:https://github.com/apache/incubator-zipkin/blob/master/zipkin-storage/mysql-v1/src/main/resources/mysql.sql

這裡我也貼出來 zipkin-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;

3)、效果

啟動微服務,執行controller請求,看是否成功。

RabbitMQ

zipkin

MySQL

至此,springcloud sleuth + zipkin + rabbitmq + mysql 就全部整合成功了!

總結

微服務的治理方案有很多,學習方向根據個人喜好決定,我的經驗就是不必盲目跟從這種用於輔助的方案,比如現在有SkyWalking,以後可能還有SkyFlying、SkySwimming。

走向高階軟體工程師都要有一個意識,就是在層出不窮的開源框架如雨後春筍般出現的時候,你得有信心用到哪個花點時間就能自己搭建起來,這才是提升自己的最有效方法。

一個專案使用什麼治理方案最重要的絕不是跟風,而是哪款最適合就用哪款,就像你找女朋友一樣,不單單是找漂亮的,而是找最能一起過日子的,否則就是貌合神離。

分享

本篇實際上是我8年多工作及學習過程中在雲筆記中記錄的內容之一,其實還有很多我閒暇之餘都做了下整理,有感興趣的朋友可以私信我獲取,什麼時候用到了翻開說不定就能節省很多時間。