Spring-Cloud-Sleuth是Spring Cloud的組成部分之一,為SpringCloud應用實現了一種分布式追蹤解決方案,其兼容了Zipkin, HTrace和log-based追蹤,追蹤微服務rest服務調用鏈路的問題,接觸到zipkin,而spring cloud也提供了spring-cloud-sleuth來方便集成zipkin實現。
為什么需要進行分布式鏈路追蹤springcloud-sleuth呢?
隨着分布式系統越來越復雜,你的一個請求發過發過去,各個微服務之間的跳轉,有可能某個請求某一天壓力太大了,一個請求過去沒響應,一個請求下去依賴了三四個服務,但是你去不知道哪一個服務出來問題,這時候我是不是需要對微服務進行追蹤呀?監控一個請求的發起,從服務之間傳遞之間的過程,我最好記錄一下,記錄每一個的耗時多久,一旦出了問題,我們就可以針對性的進行優化,是要增加節點,減輕壓力,還是服務繼續拆分,讓邏輯更加簡單點呢?這時候springcloud-sleuth集成zipkin能幫我們解決這些服務追蹤問題。
以下是來自springcloud官方文檔對springcloud-sleuth部分名字的解釋:
Span:基本工作單元,例如,在一個新建的span中發送一個RPC等同於發送一個回應請求給RPC,span通過一個64位ID唯一標識,trace以另一個64位ID表示,span還有其他數據信息,比如摘要、時間戳事件、關鍵值注釋(tags)、span的ID、以及進度ID(通常是IP地址)
span在不斷的啟動和停止,同時記錄了時間信息,當你創建了一個span,你必須在未來的某個時刻停止它。
Trace:一系列spans組成的一個樹狀結構,例如,如果你正在跑一個分布式大數據工程,你可能需要創建一個trace。
Annotation:用來及時記錄一個事件的存在,用於定義請求的開始和停止的一些核心注釋是:
1.cs- Client Sent -客戶端發起一個請求,這個annotion描述了這個span的開始
2.sr- Server Received -服務端獲得請求並准備開始處理它,如果將其sr減去cs時間戳便可得到網絡延遲
3.ss- Server Sent -注解表明請求處理的完成(當請求返回客戶端),如果ss減去sr時間戳便可得到服務端需要的處理請求時間
4.cr- Client Received -表明span的結束,客戶端成功接收到服務端的回復,如果cr減去cs時間戳便可得到客戶端從服務端獲取回復的所有所需時間
可視化Span和Trace將與Zipkin注釋一起查看系統如下圖:

一個音符的每個顏色表示跨度(7 spans - 從A到G)。如果你看到有這樣的信息:
Trace Id = X Span Id = D Client Sent
這意味着,當前的跨度痕量-ID設置為X,Span -編號設置為D。它也發出了 客戶端發送的事件。
這樣,spans的父/子關系的可視化將如下所示:
目的
在以下部分中,將考慮上述圖像中的示例。
分布式跟蹤與Zipkin
共有7個spans。如果您在Zipkin中查看痕跡,您將在第二個曲目中看到這個數字:
但是,如果您選擇特定的跟蹤,那么您將看到4 spans:
為什么在這種情況下,7和4 spans之間有區別?
-
2 spans來自
http:/start
范圍。它具有服務器接收(SR)和服務器發送(SS)注釋。 -
2 spans來自
service1
到service2
到http:/foo
端點的RPC呼叫。它在service1
方面具有客戶端發送(CS)和客戶端接收(CR)注釋。它還在service2
方面具有服務器接收(SR)和服務器發送(SS)注釋。在物理上有2個spans,但它們形成與RPC調用相關的1個邏輯跨度。 -
2 spans來自
service2
到service3
到http:/bar
端點的RPC呼叫。它在service2
方面具有客戶端發送(CS)和客戶接收(CR)注釋。它還具有service3
端的服務器接收(SR)和服務器發送(SS)注釋。在物理上有2個spans,但它們形成與RPC調用相關的1個邏輯跨度。 -
2 spans來自
service2
到service4
到http:/baz
端點的RPC呼叫。它在service2
方面具有客戶端發送(CS)和客戶接收(CR)注釋。它還在service4
側具有服務器接收(SR)和服務器發送(SS)注釋。在物理上有2個spans,但它們形成與RPC調用相關的1個邏輯跨度。
因此,如果我們計算spans ,http:/start
中有1 個來自service1
的呼叫service2
,2(service2
)呼叫service3
和2(service2
) service4
。共7個 spans。
邏輯上,我們看到Total Spans的信息:4,因為我們有1個跨度與傳入請求相關的service1
和3 spans與RPC調用相關。
接下來,進行spring-cloud-sleuth來方便集成zipkin實現的演示如下:
首先我們在先前文章的兩個服務提供者provider1,provider2模塊,還有Feign模塊都需要引入如下依賴:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-sleuth-zipkin</artifactId> <version>1.3.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-sleuth</artifactId> <version>1.3.0.RELEASE</version> </dependency>
這里還要說明一下,這里要provider1和provider2模塊和Feign模塊更換一下springcloud的版本號,如果不跟換的話,會啟動不起來的,更換后的版本如下
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston SR4</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
接着進行進行provider1的配置進行修改,如下:
#端口號 server: port: 8080 #Eureka實例名,集群中根據這里相互識別 spring: application: name: hello-service zipkin: base-url: http://localhost:9400 enabled: true #服務跟蹤消息收集率,1代表每一條都收集,0.1代表收集百分之10,如果不配置,有個默認的百分比的 # sleuth: # sampler: # percentage: 0.3 eureka: #客戶端 client: #注冊中心地址 service-url: defaultZone: http://localhost:8888/eureka/,http://localhost:8889/eureka/
接着進行provider2模塊的配置文件進行修改,代碼如下:
#端口號 server: port: 8081 #Eureka實例名,集群中根據這里相互識別 spring: application: name: hello-service zipkin: base-url: http://localhost:9400 #服務跟蹤消息收集率,1代表每一條都收集,0.1代表收集百分之10,如果不配置,有個默認的百分比的 # sleuth: # sampler: # percentage: 0.3 eureka: #客戶端 client: #注冊中心地址 service-url: defaultZone: http://localhost:8888/eureka/,http://localhost:8889/eureka/
Feign模塊的配置修改如下:
server: port: 8083 spring: application: name: feign-consumer zipkin: base-url: http://localhost:9400 eureka: client: service-url: defaultZone: http://localhost:8888/eureka/,http://localhost:8889/eureka/ hystrix: command: default: execution: isolation: thread: timeoutinMilliseconds: 5000 ribbon: connectTimeout: 500 #如果想對單獨的某個服務進行詳細配置,如下 hello-service: ribbon: connectTimeout: 500
接着在到原來的聚合工程下面新建一個子模塊叫做springcloud-sleuth模塊,如下圖:
要引入的依賴如下:
<dependency> <groupId>io.zipkin.java</groupId> <artifactId>zipkin-server</artifactId> <version>2.4.0</version> </dependency> <dependency> <groupId>io.zipkin.java</groupId> <artifactId>zipkin-autoconfigure-ui</artifactId> <version>2.4.0</version> </dependency>
Sleuth模塊的配置文件如下:
server: port: 9400 spring: application: name: zipkin-server
Sleuth模塊啟動類如下:
@SpringBootApplication @EnableZipkinServer public class SleuthApplication { public static void main(String[] args) { SpringApplication.run(SleuthApplication.class, args); } }
接着分別啟動兩個Eureka注冊中心,兩個provider1,provider2模塊,1個Feign模塊,1個Sleuth模塊,如下圖:
首先進入Sleuth和zipkin整合后的鏈路跟蹤圖形化界面如下圖所視:
接着在通過Feign去顯示調用兩個provider1和provider2模塊的服務,http://localhost:8083/consumer 多按幾次F5,進行多次請求,因為服務跟蹤消息是有收集率,1代表每一條都收集,0.1代表收集百分之10,如果不配置,有個默認的百分比的,因此需要多次請求,確保被跟蹤消息能被收集到。如下:
接着去ZipKin控制台進行查看鏈路調用,如下:
這里我選擇Feign-Consumer進行演示,再點擊查找,如下:
這里在圖中漏說了一點就是,比如feign-consumer 100%而且有藍色的橫條包裹表示調用成功率,紅色橫條包裹表示失敗,出現異常錯誤。
再點擊其中一個調用服務,進入可以看到詳細信息,如下:
以下是錯誤信息的演示我直接拿官方文檔的截圖來說明,如下:
Zipkin允許您可視化跟蹤中的錯誤。當異常被拋出並且沒有被捕獲時,我們在Zipkin可以正確着色的跨度上設置適當的標簽。您可以在痕跡列表中看到一條是紅色的痕跡。這是因為拋出了一個異常。
如果您點擊該軌跡,您將看到類似的圖片
然后,如果您點擊其中一個spans,您將看到以下內容