原文:https://www.jianshu.com/p/6ef0b76b9c26
分布式服務跟蹤需求
隨着分布式服務越來越多,調用關系越來越復雜,組合接口越來越多,要進行分布式服務跟蹤監控的需求也越來越強烈,對於項目負責人當生產環境出現問題的時候需要第一時間知道哪個服務節點出現了問題,這就需要我們能夠通過監控系統第一時間發現。
分布式服務跟蹤現狀
目前主流的分布式服務跟蹤開源框架主要有3個,大家用的比較多的是點評的CAT、pinpoint和sleuth+zipkin,下面分別介紹下這幾個框架的優缺點,之前我們公司內部也都使用過。
CAT:大眾點評開源的內部服務跟蹤框架,可以監控服務的關聯關系,每個服務節點的耗時情況,數據庫的耗時、網絡的故障等等,監控的內容還是很全面的,但是需要注意的是CAT對代碼存在一定的侵入性,需要對杯監控的方法增加注解才能完成服務監控;
pinpoint:是一個韓國人寫的開源服務跟蹤框架,pinpoint的好處就是對被監控的工程代碼沒有侵入性,只需要集成pinpoint的jar包就可以完成基本的服務性能監控了,上手非常簡單;
sleuth+zipkin:適合於公司使用springcloud框架的工程,集成起來更加方便,能和springcloud相關套件配合使用,能夠監控到服務依賴關聯、服務耗時等基本信息,也提供了豐富的查詢功能,方便快速定位問題。
這3個開源框架,各有優缺點,CAT的優點是有更強的定制性,不僅僅局限在APM信息監控,還可以進行更多的功能拓展;pinpoint的優點就是容易上手,但是很難進行后續的功能擴展;sleuth的優點是在springcloud工程中集成非常簡單,但也是后續很難進行功能擴展。
springcloud中的服務跟蹤解決方案
springcloud作為主流的微服務框架中比較成熟的服務跟蹤解決方案那就是sleuth+zipkin,如果公司內部是實用springcloud作為基礎搭建微服務的,建議直接使用sleuth和zipkin,sleuth作為服務跟蹤框架,zipkin作為服務跟蹤展示框架,能夠方便的查看出每個服務節點的耗時情況,並能夠將組合服務的調用關系鏈直觀的展示出來,方便發現問題,並且對微服務工程的侵入性比較小。
sleuth+zipkin原理
sleuth+zipkin的分布式服務跟蹤方案和pinpoint一樣都是根據google早年間發布的Dapper論文來實現的,這里簡單描述下分布式服務跟蹤的核心原理,要實現一個業務的全流程跟蹤,那么每個全流程交易首先必須要有一個貫穿於全鏈路的TraceID用於標記出各個服務節點中哪些交易是歸屬於這筆業務交易的,但是我們篩選出了所有相關交易后還是無法知道每個服務節點之間的依賴關系和先后順序關系,那么就還需要有一個表示這筆子交易的ID,因此在Dapper論文中又定義了一個SpanID,SpanID可以理解為在每個服務節點的最小工作單元,例如一個基本交易包含了請求和響應兩個動作,那么就可以請求和響應各分配一個SpanID來唯一標示這個動作,請看下圖,標示了3個串聯調用的服務,每個服務都有一個請求動作和一個響應動作,在每個動作開始的時候都會分配一個唯一的SpanID,同時會將同一個TraceId一直傳遞下去。

在每個服務節點都集成sleuth服務,sleuth服務會自動為每筆交易動作第一個服務節點生成一個全局唯一TraceId,這個TraceID會一直跟隨交易傳遞下去,同時sleuth會為當前的動作再生成一個全局唯一的SpanId,在SpanId中可以體現出這個動作的上一個父動作的SpanId,同時也包含了動作發生時間信息,通過這些信息就能夠還原出一棵交易的樹形結構,通過對每個動作的開始、結束時間求差就能知道該筆交易每個動作之間的耗時。
上面介紹了sleuth的大概原理,下面再介紹下zipkin的原理,zipkin在整個服務跟蹤里是用於接收sleuth為每個交易生成的TraceId和SpanId,zipkin對收集到的這些信息進行實時計算后進行一個樹形結構的耗時展示,同時也提供了准實時查詢功能,只需要通過簡單的配置就能夠滿足基本的分布式服務跟蹤需求。
微服務工程支持sleuth客戶端
下面介紹下在sleuth客戶端的開發工作,只需要進行POM的配置,工程引入對sleuth的兩個依賴(最后兩個),就可以自動監控分布式服務了,非常簡單。
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-ribbon</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-sleuth</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-sleuth-zipkin</artifactId> </dependency> </dependencies>
下面這兩條分別是兩個服務在console里打出的日志信息,我們可以發現在日志頭部多了幾個信息。
[sleuth-testservice1,5856e53b441a241a,5856e53b441a241a,false] 1244 --- [nio-9091-exec-2] c.m.t.controller.TestController1 : ===call testController1===
[sleuth-testservice2,5856e53b441a241a,b1573c23f0322ab1,false] 1246 --- [nio-9092-exec-1] testservice.controller.TestController2 : ===call testController2===
- 第一個值:
sleuth-testservice1
,它記錄了應用的名稱,也就是application.yml
中spring.application.name
參數配置的屬性。 - 第二個值:
5856e53b441a241a
,Spring Cloud Sleuth生成的一個ID,稱為Trace ID,它用來標識一條請求鏈路。一條請求鏈路中包含一個Trace ID,多個Span ID。 - 第三個值:
5856e53b441a241a
,Spring Cloud Sleuth生成的另外一個ID,稱為Span ID,它表示一個基本的工作單元,比如:發送一個HTTP請求。 - 第四個值:
false
,表示是否要將該信息輸出到Zipkin等服務中來收集和展示,如果為true
則表示該筆日志信息會傳遞到zipkin服務器進行統計,sleuth不是每筆交易都會上送zipkin,一般5筆交易會有一筆抽樣上送zipkin,這么做是為了保證zipkin的性能。
上面四個值中的TraceID
和SpanID
是Spring Cloud Sleuth實現分布式服務跟蹤的核心。在一次服務請求鏈路的調用過程中,會保持並傳遞同一個TraceID
,從而將整個分布於不同微服務進程中的請求跟蹤信息串聯起來,以上面輸出內容為例,sleuth-testservice1
和sleuth-testservice2
同屬於一個前端服務請求來源,所以他們的TraceID
是相同的,處於同一條請求鏈路中。
同時為了將服務跟蹤日志能發送到zipkin服務端進行統計,還需要在application.yml中配置zipkin的服務端地址。
server:
port: 9092 spring: application: name: sleuth-testservice2 zipkin: base-url: http://XX.XX.XX.XX:9411 eureka: client: serviceUrl: defaultZone: http://XX.XX.XX.XX:8761/eureka/
zipkin服務端
zipkin的服務端配置也非常簡單,只需要兩步配置。
首先在POM中引入zipkin的相關依賴,如下:
<dependencies> <dependency> <groupId>io.zipkin.java</groupId> <artifactId>zipkin-server</artifactId> </dependency> <dependency> <groupId>io.zipkin.java</groupId> <artifactId>zipkin-autoconfigure-ui</artifactId> </dependency> </dependencies>
再創建一個springboot的Applicatoin啟動類,在啟動類中加上 @EnableZipkinServer
zipkin服務器注解,在需要被跟蹤監控的sleuth客戶端的配置文件中加上zipkin服務器地址的配置,上面也介紹過了。
@EnableZipkinServer @SpringBootApplication public class ZipkinApplication { public static void main(String[] args) { SpringApplication.run(ZipkinApplication.class, args); } }
打開http://XX.XX.XX.XX:9411/ 地址就可以查看到zipkin的console頁面,在頁面中輸入需要查詢的關鍵字和起止時間就可以進行查詢了,這里需要注意因為sleuth並不是所有跟蹤日志都會發送到zipkin,所以在zipkin查詢到的只是一個采樣統計。

點開一個組合交易,可以看到這個組合交易由兩個服務組成,圖中也顯示了節點耗時。

點開后還可以看到每一個鏈路動作的明細信息。

總結
這樣就把在springcloud中通過sleuth、zipkin進行監控的過程從原理到實現進行了一個簡單的介紹,總的來說還是比較簡單的,原理也不是很復雜,感興趣的同學還可以翻看下相關源碼,sleuth的核心是唯一發號器和動態代理,zipkin的核心是交易的樹形結構的生成和內存實時統計,本文涉及到的源碼都加到了入門系列的工程中,感興趣的可以下載下來看看,涉及到的模塊有zipkin-server、sleuth-testservice1、sleuth-testservice2。