Spring Cloud Sleuth原理簡(jiǎn)介和使用

為什么需要Spring Cloud Sleuth

微服務(wù)架構(gòu)是一個(gè)分布式架構(gòu),它按業(yè)務(wù)劃分服務(wù)單元,一個(gè)分布式系統(tǒng)往往有很多個(gè)服務(wù)單元。

由于服務(wù)單元數(shù)量眾多,業(yè)務(wù)的復(fù)雜性,如果出現(xiàn)了錯(cuò)誤和異常,很難去定位。

主要體現(xiàn)在,一個(gè)請(qǐng)求可能需要調(diào)用很多個(gè)服務(wù),而內(nèi)部服務(wù)的調(diào)用復(fù)雜性,決定了問(wèn)題難以定位。

所以微服務(wù)架構(gòu)中,必須實(shí)現(xiàn)分布式鏈路追蹤,去跟進(jìn)一個(gè)請(qǐng)求到底有哪些服務(wù)參與,參與的順序又是怎樣的,從而達(dá)到每個(gè)請(qǐng)求的步驟清晰可見(jiàn),出了問(wèn)題,很快定位。

舉個(gè)例子,在微服務(wù)系統(tǒng)中,一個(gè)來(lái)自用戶(hù)的請(qǐng)求,請(qǐng)求先達(dá)到前端A(如前端界面),然后通過(guò)遠(yuǎn)程調(diào)用,達(dá)到系統(tǒng)的中間件B、C(如負(fù)載均衡、網(wǎng)關(guān)等),最后達(dá)到后端服務(wù)D、E,后端經(jīng)過(guò)一系列的業(yè)務(wù)邏輯計(jì)算最后將數(shù)據(jù)返回給用戶(hù)。對(duì)于這樣一個(gè)請(qǐng)求,經(jīng)歷了這么多個(gè)服務(wù),怎么樣將它的請(qǐng)求過(guò)程的數(shù)據(jù)記錄下來(lái)呢?這就需要用到服務(wù)鏈路追蹤。

基本術(shù)語(yǔ)

Spring Cloud Sleuth采用的是Google的開(kāi)源項(xiàng)目Dapper的專(zhuān)業(yè)術(shù)語(yǔ)。

Span:基本工作單元,發(fā)送一個(gè)遠(yuǎn)程調(diào)度任務(wù) 就會(huì)產(chǎn)生一個(gè)Span,Span是一個(gè)64位ID唯一標(biāo)識(shí)的,Trace是用另一個(gè)64位ID唯一標(biāo)識(shí)的,Span還有其他數(shù)據(jù)信息,比如摘要、時(shí)間戳事件、Span的ID、以及進(jìn)度ID。

Trace:一系列Span組成的一個(gè)樹(shù)狀結(jié)構(gòu)。請(qǐng)求一個(gè)微服務(wù)系統(tǒng)的API接口,這個(gè)API接口,需要調(diào)用多個(gè)微服務(wù),調(diào)用每個(gè)微服務(wù)都會(huì)產(chǎn)生一個(gè)新的Span,所有由這個(gè)請(qǐng)求產(chǎn)生的Span組成了這個(gè)Trace。

Annotation:用來(lái)及時(shí)記錄一個(gè)事件的,一些核心注解用來(lái)定義一個(gè)請(qǐng)求的開(kāi)始和結(jié)束 。這些注解包括以下:

1?? cs - Client Sent -客戶(hù)端發(fā)送一個(gè)請(qǐng)求,這個(gè)注解描述了這個(gè)Span的開(kāi)始

2?? sr - Server Received -服務(wù)端獲得請(qǐng)求并準(zhǔn)備開(kāi)始處理它,如果將其sr減去cs時(shí)間戳便可得到網(wǎng)絡(luò)傳輸?shù)臅r(shí)間。

3?? ss - Server Sent (服務(wù)端發(fā)送響應(yīng))–該注解表明請(qǐng)求處理的完成(當(dāng)請(qǐng)求返回客戶(hù)端),如果ss的時(shí)間戳減去sr時(shí)間戳,就可以得到服務(wù)器請(qǐng)求的時(shí)間。

4?? cr - Client Received (客戶(hù)端接收響應(yīng))-此時(shí)Span的結(jié)束,如果cr的時(shí)間戳減去cs時(shí)間戳便可以得到整個(gè)請(qǐng)求所消耗的時(shí)間。

案例實(shí)戰(zhàn)

本文案例一共四個(gè)工程采用多Module形式

目錄結(jié)構(gòu)

需要新建一個(gè)主Maven工程,主要指定了Spring Boot的版本為1.5.3,Spring Cloud版本為Dalston.RELEASE

1?? 包含了eureka-server工程,作為服務(wù)注冊(cè)中心 eureka-server的創(chuàng)建過(guò)程這里不重復(fù)

2?? zipkin-server作為鏈路追蹤服務(wù)中心,負(fù)責(zé)存儲(chǔ)鏈路數(shù)據(jù)

3?? gateway-service作為服務(wù)網(wǎng)關(guān)工程,負(fù)責(zé)請(qǐng)求的轉(zhuǎn)發(fā),同時(shí)它也作為鏈路追蹤客戶(hù)端,負(fù)責(zé)產(chǎn)生數(shù)據(jù),并上傳給zipkin-service

4?? user-service為一個(gè)應(yīng)用服務(wù),對(duì)外暴露API接口,同時(shí)它也作為鏈路追蹤客戶(hù)端,負(fù)責(zé)產(chǎn)生數(shù)據(jù)

主maven pom文件

構(gòu)建zipkin-server工程

目錄結(jié)構(gòu)

pom文件

配置文件

代碼

構(gòu)建user-service

目錄結(jié)構(gòu)

pom文件

代碼

配置文件

構(gòu)建gateway-service

目錄結(jié)構(gòu)

配置文件

代碼

pom文件

項(xiàng)目演示

依次啟動(dòng)eureka-server、zipkin-server、user-service、gateway-service

瀏覽器訪(fǎng)問(wèn) http://localhost:5000/user-api/user/hi

http://localhost:9411,即訪(fǎng)問(wèn)Zipkin的展示界面

這個(gè)界面主要用來(lái)查找服務(wù)的調(diào)用情況,可以根據(jù)服務(wù)名、開(kāi)始時(shí)間、結(jié)束時(shí)間、請(qǐng)求消耗的時(shí)間等條件來(lái)查找。點(diǎn)擊“Find Trackes”按鈕,界面如圖所示。從圖可知服務(wù)的調(diào)用情況,比如服務(wù)調(diào)用時(shí)間、服務(wù)的消耗時(shí)間,服務(wù)調(diào)用的鏈路情況。

點(diǎn)擊Dependences按鈕,可以查看服務(wù)的依賴(lài)關(guān)系,在本案例中,gateway-service將請(qǐng)求轉(zhuǎn)發(fā)到了user-service,它們的依賴(lài)關(guān)系如圖:

怎么在鏈路數(shù)據(jù)中添加自定義數(shù)據(jù)

需要在gateway-service上實(shí)現(xiàn)。建一個(gè)ZuulFilter過(guò)濾器,它的類(lèi)型為“post”,order為900,開(kāi)啟攔截。在攔截邏輯方法里,通過(guò)Tracer的addTag方法加上自定義的數(shù)據(jù),比如本案例中加入了鏈路的操作人。另外也可以在這個(gè)過(guò)濾器中獲取當(dāng)前鏈路的traceId信息,traceId作為鏈路數(shù)據(jù)的唯一標(biāo)識(shí),可以存儲(chǔ)在log日志中,方便后續(xù)查找。

使用spring-cloud-starter-stream-rabbit進(jìn)行鏈路通訊

在上述的案例中,最終gateway-service收集的數(shù)據(jù),是通過(guò)Http上傳給zip-server的,在Spring Cloud Sleuth中支持消息組件來(lái)通訊的

首先安裝rabbitmq

docker run -d --name myrabbitmq -p 5672:5672 -p 15672:15672 docker.io/rabbitmq:management

訪(fǎng)問(wèn) http://127.0.0.1:15672/#/

改造zipkin-server

pom改造

配置文件

啟動(dòng)類(lèi)

改造 Zipkin Client(包括gateway-service、user-service)

啟動(dòng)方式和訪(fǎng)問(wèn)方式如上

訪(fǎng)問(wèn)rabbitmq頁(yè)面

這樣,就將鏈路的上傳數(shù)據(jù)從Http改了為用消息代組件RabbitMQ。

將鏈路數(shù)據(jù)存儲(chǔ)在Mysql數(shù)據(jù)庫(kù)

在上述的例子中,Zipkin Server是將數(shù)據(jù)存儲(chǔ)在內(nèi)存中,一旦程序重啟,之前的鏈路數(shù)據(jù)全部丟失,那么怎么將鏈路數(shù)據(jù)存儲(chǔ)起來(lái)呢?Zipkin支持Mysql、Elasticsearch、Cassandra存儲(chǔ)

改造 zipkin-server

pom 文件

``

備注:mysql-connector-java 依賴(lài)版本號(hào)要和數(shù)據(jù)庫(kù)保持一致

比如數(shù)據(jù)庫(kù)版本號(hào)是8.0.19 那么依賴(lài) mysql-connector-java的版本號(hào)也需要是8.0.19

``

配置文件

數(shù)據(jù)庫(kù)

啟動(dòng)服務(wù)、訪(fǎng)問(wèn)接口(同上)

查看數(shù)據(jù)庫(kù)記錄

將數(shù)據(jù)存儲(chǔ)在es中

使用Mysql存儲(chǔ)鏈路數(shù)據(jù),在并發(fā)高的情況下,顯然不合理,這時(shí)可以選擇使用ElasticSearch存儲(chǔ)。

安裝 ES、kibana

可參考我之前寫(xiě)的文章《ELK環(huán)境部署》

啟動(dòng) ES

啟動(dòng) Kibana

訪(fǎng)問(wèn) Kibana

1?? 查看本地IP ifconfig

2?? 訪(fǎng)問(wèn) http://172.16.2.197:5601

它默認(rèn)會(huì)向本地的9200端口的ElasticSearch讀取數(shù)據(jù),它默認(rèn)的端口為5601

在zipkin中配置 ES

添加依賴(lài)

配置

啟動(dòng)服務(wù) 訪(fǎng)問(wèn)接口 (同上)

啟動(dòng)zipkin報(bào)錯(cuò)

異常:IllegalStateException(Elasticsearch 2.x and 5.x are supported, was: 7.5.1)

原因 我安裝的ES版本太高7.5.1 需要安裝低版本的ES

查看es版本

版本說(shuō)明

換成這個(gè)版本啟動(dòng)不會(huì)報(bào)錯(cuò) 但還是使用不了ES 所以不要使用新版本的ES 因?yàn)閦ipkin還未做兼容

安裝好了ES 6.X或更低版本

訪(fǎng)問(wèn) kibana 添加index zipkin

在Kibana中查看鏈路數(shù)據(jù)和使用圖標(biāo)顯示數(shù)據(jù)

這里不在重復(fù)了 感興趣的童鞋可以看我之前寫(xiě)的ELK部署的文章有詳細(xì)的介紹

源碼資源

https://gitee.com/pingfanrenbiji/SpringCloudLearning.git

參考文獻(xiàn)

https://juejin.im/post/59872ba96fb9a03c400ea11c

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容