序言
sleuth是spring cloud的分布式跟蹤工具,主要記錄鏈路調用數據,本身只支持內存存儲,在業務量大的場景下,為拉提升系統性能也可通過http傳輸數據,也可換做rabbit或者kafka來傳輸數據。
zipkin是Twitter開源的分布時追蹤系統,可接收數據,存儲數據(內存/cassandra/mysql/es),檢索數據,展示數據,他本神不會直接在分布式的系統服務種trace追蹤數據,可便捷的使用sleuth來收集傳輸數據。
這樣描述,大家應該很清晰啦。
服務追蹤意義
目前流行的架構現狀,都是站在微服務架構的基礎之上,那么勢必會產生出越來越多的服務,相互依賴調用,那么如果服務調用關系如下圖所示。

越來越多的服務可能,調用關系就如下啦,一團亂麻,如果沒有服務之間的鏈路追蹤的記錄查詢方案,想快速定位問題,翻代碼都不知從何翻起,估計鎖定責任人更要撕逼一翻啦,哈哈。

行業方案
Google開源的 Dapper鏈路追蹤組件,並在2010年發表了論文《Dapper, a Large-Scale Distributed Systems Tracing Infrastructure》,這篇文章是業內實現鏈路追蹤的標桿和理論基礎,具有非常大的參考價值。
鏈路追蹤組件有如下產品,都很贊,很值得學習:
- Google的Dapper
- Twitter的Zipkin
- 阿里的Eagleeye (鷹眼)
- 美團點評的Cat
- 新浪的Watchman
- 京東的Hydra
- 個人吳晟(華為開發者)開源的skywalking (很贊)
- 韓國團隊naver團隊開源pinpoint
有時間大家學習一番啊。
Sleuth鏈路追蹤專業術語
Spring Cloud Sleuth采用的是Google的開源項目Dapper的專業術語。
- 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注解的過程圖形化:

trace id 整個鏈路中是唯一不變的,這樣也方便查詢。
zipkin介紹
zipkin主要有四個組件:collector,storage,API,web UI。collector用於收集各服務發送到zipkin的數據,storage用於存儲這些鏈路數據,目前支持Cassandra,ElasticSearch(推薦使用,易於大規模擴展)和MySQL,API用來查找和檢索跟蹤鏈,提供給界面UI展示。

鏈路的追蹤原理:跟蹤器位於應用程序中,記錄發生的操作的時間和元數據,收集的跟蹤數據稱為Span,將數據發送到Zipkin的儀器化應用程序中的組件稱為Reporter,Reporter通過幾種傳輸方式(http,kafka)之一將追蹤數據發送到Zipkin收集器(collector),然后將跟蹤數據進行存儲(storage),由API查詢存儲以向UI提供數
具體項目搭建

上面是我的示例項目。
1.trade-zipkin-server是zipkinserver,是用來展示,搜索,存儲trade追蹤數據用的。
2.shop-->order-->shouhou & promotion(簡單的調用鏈路,這里是具體需要的業務鏈路追蹤的trace項目哈)。
zipkinserver配置代碼
@EnableZipkinServer public class StartMain { public static void main(String[] args) { SpringApplication.run(StartMain.class, args); } }
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-server</artifactId>
<version>2.11.8</version>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-autoconfigure-ui</artifactId>
<version>2.11.8</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
業務項目配置
spring.sleuth.enabled=true
spring.sleuth.sampler.percentage=1
spring.zipkin.base-url=http://localhost:8087
<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>
note:
spring.sleuth.sampler.percentage參數配置(如果不配置默認0.1),如果我們調大此值為1,可以看到信息收集就更及時。但是當這樣調整后,我們會發現我們的rest接口調用速度比0.1的情況下慢了很多,即使在0.1的采樣率下,我們多次刷新consumer的接口,會發現對同一個請求兩次耗時信息相差非常大,如果取消spring-cloud-sleuth后我們再測試,會發現並沒有這種情況,可以看到這種方式追蹤服務調用鏈路會給我們業務程序性能帶來一定的影響。
zipkin收集展示數據界面如下:



seluth+zipkin數據寫入Elasticsearch,使用kibana展示
配置zipkinserver
<dependency> <groupId>io.zipkin.java</groupId> <artifactId>zipkin-autoconfigure-storage-elasticsearch-http</artifactId> <version>2.8.4</version> </dependency>
zipkin.storage.StorageComponent=elasticsearch
zipkin.storage.type=elasticsearch
#可以做集群,我用的本地測試沒有部署elastic集群
zipkin.storage.elasticsearch.hosts=es.me.com
zipkin.storage.elasticsearch.cluster=iron-man
zipkin.storage.elasticsearch.index=trade-zipkin
zipkin.storage.elasticsearch.index-shards=5
zipkin.storage.elasticsearch.index-replicas=1

總結
其實,我這個案例,只是讓你熟悉了解服務鏈路追蹤,能夠兼顧性能的整體方案如下。


