作者 | lzjasd
springcloud-Sleuth 與 Zipkin 結合圖形化展示
分散式追蹤相關基礎概念Google Dapper 論文和 ZipkinSpring Cloud Sleuth 介紹及使用Spring Cloud Sleuth 與 Zipkin 結合使用進行圖形化展示透過 Spring Cloud Sleuth 來實現呼叫鏈監控以此來幫助我們快速定位系統是哪個環節出了問題。透過呼叫鏈監控服務,我們可以快速定位出是微服務的問題、網路問題或是其他問題。
通常一個系統都是有數十個、上百個服務組成的。服務與服務之間或多或少都會進行相互呼叫通訊。整個請求路徑就構成了一個網狀的呼叫鏈,而在整個呼叫鏈中一旦某個節點發生異常,整個呼叫鏈的穩定性就會受到影響。面對以上情況,我們就需要一些可以幫助理解系統行為、用於分析效能問題的工具,以便發生故障的時候,能夠快速定位和解決問題。
目前大多數的開源或者商業產品都參考了 Google 釋出的一篇論文《Dapper》,裡面描述了可參考的實現分散式追蹤系統(APM)的方式。下圖中描述了基礎模組:
其中包含了用於客戶端採集資訊的探針或者 SDK,收集採集資訊的服務端以及儲存收集結果的儲存引擎。一般用分散式追蹤系統攬括這三大模組。
Spring Cloud 中關於 Sleuth 和 Zipkin 也參考了該實現,更多內容就不在這裡細述。我們還是以動手實踐為主。
使用
引入 Sleuth 依賴:<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-sleuth</artifactId></dependency>
修改 application.yml 配置檔案,增加如下內容:logging: level: root: INFO ...... org.springframework.cloud.sleuth: DEBUG ......
C:\Users\l\javademo\microservice-provider-user>curl http://localhost:8000/users/2{"id":2,"username":"account2","name":"鏉庡洓","age":28,"balance":180.00}
Hibernate: select user0_.id as id1_0_0_, user0_.age as age2_0_0_, user0_.balance as balance3_0_0_, user0_.name as name4_0_0_, user0_.username as username5_0_0_ from user user0_ where user0_.id=?2021-02-20 18:31:55.070 TRACE [microservice-provider-user,79ae2adc64548a89,79ae2adc64548a89,false] 19332 --- [nio-8000-exec-1] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [BIGINT] - [2]2021-02-20 18:31:55.076 TRACE [microservice-provider-user,79ae2adc64548a89,79ae2adc64548a89,false] 19332 --- [nio-8000-exec-1] o.h.type.descriptor.sql.BasicExtractor : extracted value ([age2_0_0_] : [INTEGER]) - [28]2021-02-20 18:31:55.077 TRACE [microservice-provider-user,79ae2adc64548a89,79ae2adc64548a89,false] 19332 --- [nio-8000-exec-1] o.h.type.descriptor.sql.BasicExtractor : extracted value ([balance3_0_0_] : [NUMERIC]) - [180.00]2021-02-20 18:31:55.077 TRACE [microservice-provider-user,79ae2adc64548a89,79ae2adc64548a89,false] 19332 --- [nio-8000-exec-1] o.h.type.descriptor.sql.BasicExtractor : extracted value ([name4_0_0_] : [VARCHAR]) - [李四]2021-02-20 18:31:55.077 TRACE [microservice-provider-user,79ae2adc64548a89,79ae2adc64548a89,false] 19332 --- [nio-8000-exec-1] o.h.type.descriptor.sql.BasicExtractor : extracted value ([username5_0_0_] : [VARCHAR]) - [account2]
是不是覺得看著這個毫無頭緒,也看不出來個究竟。一個良好的監控,應該有一個人類親和的介面,這個介面就是 Zipkin。那麼,我們接下來就結合Zipkin來幫助我們吧Zipkin
Zipkin
1
Zipkin 是 Twitter 開源的分散式跟蹤系統,基於 Dapper 的論文設計而來。它的主要功能是收集系統的時序資料,從而追蹤微服務架構的系統延時等問題。Zipkin 還提供了一個非常友好的介面,幫助我們分析追蹤資料。
Zipkin 是一個開放原始碼分散式的跟蹤系統,每個服務向zipkin報告計時資料,zipkin會根據呼叫關係透過Zipkin UI生成依賴關係圖。
Zipkin提供了可插拔資料儲存方式:In-Memory、MySql、Cassandra以及Elasticsearch。為了方便在開發環境我直接採用了In-Memory方式進行儲存,生產資料量大的情況則推薦使用Elasticsearch。
基本術語
Span:基本工作單元,例如,在一個新建的span中傳送一個RPC等同於傳送一個迴應請求給RPC,span透過一個64位ID唯一標識,trace以另一個64位ID表示,span還有其他資料資訊,比如摘要、時間戳事件、關鍵值註釋(tags)、span的ID、以及進度ID(通常是IP地址)span在不斷的啟動和停止,同時記錄了時間資訊,當你建立了一個span,你必須在未來的某個時刻停止它。Trace:一系列spans組成的一個樹狀結構,例如,如果你正在跑一個分散式大資料工程,你可能需要建立一個trace。Annotation:用來及時記錄一個事件的存在,一些核心annotations用來定義一個請求的開始和結束cs - Client Sent -客戶端發起一個請求,這個annotion描述了這個span的開始sr - Server Received -服務端獲得請求並準備開始處理它,如果將其sr減去cs時間戳便可得到網路延遲ss - Server Sent -註解表明請求處理的完成(當請求返回客戶端),如果ss減去sr時間戳便可得到服務端需要的處理請求時間cr - Client Received -表明span的結束,客戶端成功接收到服務端的回覆,如果cr減去cs時間戳便可得到客戶端從服務端獲取回覆的所有所需時間將Span和Trace在一個系統中使用Zipkin註解的過程圖形化:我們需要將前面 Sleuth 採集到的資料傳送給 Zipkin 服務端。Zipkin 分析之後展示在介面上。 因此,我們需要啟動 Zipkin Server。這裡我們使用編譯好的可執行 Jar 包直接啟動。使用 https://search.maven.org/remote_content?g=io.zipkin.java&a=zipkin-server&v=LATEST&c=exec 下載最新版本的 Zipkin Server,例如 zipkin-server-2.12.9-exec.jar。 或者你也可以直接下載我們準備好的 jar 包: wget https://labfile.oss.aliyuncs.com/courses/1360/zipkin-server-2.12.9-exec.jar 啟動 Zipkin Serverjava -jar zipkin-server-2.12.9-exec.jar 訪問 http://localhost:9411 ,即可看到 Zipkin Server 的首頁。<br><br>
透過以下命令啟動服務,預設INFO級別可以不設定logging
java -jar zipkin-server-2.12.9-exec.jar --logging.level.zipkin2=INFO
STORAGE_TYPE=elasticsearch ES_HOSTS=http://myhost:9200 java -jar zipkin.jar
接著,為我們上面步驟的使用者服務整合 Zipkin,使其能夠把資料傳送給 Zipkin Server。
在使用者服務中新增依賴:<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-sleuth-zipkin</artifactId></dependency>
在 application.yml 中新增配置:spring: ...... zipkin: base-url: http://localhost:9411 sleuth: sampler: probability: 1.0
spring: zipkin: base-url: http://127.0.0.1:9411 sleuth: sampler: percentage: 1.0
這裡的base-url是zipkin服務端的地址,percentage是取樣比例,設定為1.0時代表全部強求都需要取樣。Sleuth預設取樣演算法的實現是Reservoir sampling,具體的實現類是PercentageBasedSampler,預設的取樣比例為: 0.1(即10%)。
測試執行啟動微服務,訪問 http://localhost:8000/users/2,然後瀏覽器訪問 http://localhost:9411,可看到類似如下介面
http://localhost:8000/users/2 // 訪問這個url,看到日誌,trap-executor-0,還需要等待一段時間,才能在zipinweb頁面查詢到執行這個url查詢花費的時間
Hibernate: select user0_.id as id1_0_0_, user0_.age as age2_0_0_, user0_.balance as balance3_0_0_, user0_.name as name4_0_0_, user0_.username as username5_0_0_ from user user0_ where user0_.id=?2021-02-20 18:45:17.221 TRACE [microservice-provider-user,3db39898b7464cc8,3db39898b7464cc8,false] 13812 --- [nio-8000-exec-4] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [BIGINT] - [1]2021-02-20 18:45:17.222 TRACE [microservice-provider-user,3db39898b7464cc8,3db39898b7464cc8,false] 13812 --- [nio-8000-exec-4] o.h.type.descriptor.sql.BasicExtractor : extracted value ([age2_0_0_] : [INTEGER]) - [20]2021-02-20 18:45:17.222 TRACE [microservice-provider-user,3db39898b7464cc8,3db39898b7464cc8,false] 13812 --- [nio-8000-exec-4] o.h.type.descriptor.sql.BasicExtractor : extracted value ([balance3_0_0_] : [NUMERIC]) - [100.00]2021-02-20 18:45:17.222 TRACE [microservice-provider-user,3db39898b7464cc8,3db39898b7464cc8,false] 13812 --- [nio-8000-exec-4] o.h.type.descriptor.sql.BasicExtractor : extracted value ([name4_0_0_] : [VARCHAR]) - [張三]2021-02-20 18:45:17.222 TRACE [microservice-provider-user,3db39898b7464cc8,3db39898b7464cc8,false] 13812 --- [nio-8000-exec-4] o.h.type.descriptor.sql.BasicExtractor : extracted value ([username5_0_0_] : [VARCHAR]) - [account1]2021-02-20 18:49:11.673 INFO [microservice-provider-user,,,] 13812 --- [trap-executor-0] c.n.d.s.r.aws.ConfigClusterResolver : Resolving eureka endpoints via configuration
zipin2https://zipkin.io/pages/quickstart QuickstartIn this section we’ll walk through building and starting an instance of Zipkin for checking out Zipkin locally. There are three options: using Java, Docker or running from source. If you are familiar with Docker, this is the preferred method to start. If you are unfamiliar with Docker, try running via Java or from source. Regardless of how you start Zipkin, browse to http://your_host:9411 to find traces! DockerThe Docker Zipkin project is able to build docker images, provide scripts and a docker-compose.yml for launching pre-built images. The quickest start is to run the latest image directly: docker run -d -p 9411:9411 openzipkin/zipkinJavaIf you have Java 8 or higher installed, the quickest way to get started is to fetch the latest release as a self-contained executable jar: curl -sSL https://zipkin.io/quickstart.sh | bash -sjava -jar zipkin.jarRunning from SourceZipkin can be run from source if you are developing new features. To achieve this, you’ll need to get Zipkin’s source and build it. # get the latest sourcegit clone https://github.com/openzipkin/zipkincd zipkin# Build the server and also make its dependencies./mvnw -DskipTests --also-make -pl zipkin-server clean install# Run the serverjava -jar ./zipkin-server/target/zipkin-server-*exec.jarStop by and socialize with us on gitter, if you end up making something interesting!
從分散式追蹤理論出處講起,接著是改造前面的服務,讓其呼叫資訊能夠被呼叫鏈追蹤服務所記錄。不知道你理清楚沒有,沒關係,實驗結束之後利用空餘時間跟深入的探究吧。這裡另外總結一下,在分散式追蹤系統中,目前主要分為手動埋點和自動埋點的兩種系統。國內也有一款基於 Java 自動埋點的開源分散式追蹤、監控產品—— Apache Skywalking