誰說Cat不能作鏈路跟蹤的,給我站出來

背景

鏈路跟蹤,咱們有不少可選項。常見的有 zipkin,pinpoint,skywalking,jaeger 等。git

基本上都是根據谷歌的《Dapper 大規模分佈式系統的跟蹤系統》這篇論文發展出來的。github

今天講下 Cat 裏的鏈路跟蹤要如何來實現,沒用過 Cat 的同窗能夠查看個人這篇文章 《熬夜之做:一文帶你瞭解 Cat 分佈式監控》進行了解。數據庫

在 Cat 中能夠很方便的看到每一個請求的總耗時以及業務操做,數據庫操做的耗時狀況。對於服務之間的調用也能夠經過埋點的方式進行監控。微信

以下圖,能夠看出請求內發起了一次 RPC 的調用,callRPC 開頭的那條記錄。耗時 11ms, 可是這個 RPC 服務內部耗時花在哪裏了,在這邊不能直接查看,只能去另外一個服務中查看,不是很方便。app

誰說Cat不能作鏈路跟蹤的,給我站出來
圖片
詳細的我畫了一張圖說明下如今的問題:分佈式

誰說Cat不能作鏈路跟蹤的,給我站出來

誰說Cat不能作鏈路跟蹤的,給我站出來

從上圖能夠看出,一個請求通過了多個服務,每一個服務中對遠程調用或者本地調用都有埋點,這樣就能監控到調用的異常和性能指標。ide

下面一部分是在 Cat 中咱們去查看這些指標的場景,Cat 中的數據展現是以項目維度來展現的,因此每一個服務都有本身的監控數據。微服務

若是我想要知道剛剛那次請求,在整個鏈路中哪裏最慢,耗時在哪裏,我得分別去 4 個服務下面才能看到這些信息,不直觀。性能

實現方式

以下圖所示:
誰說Cat不能作鏈路跟蹤的,給我站出來
誰說Cat不能作鏈路跟蹤的,給我站出來學習

從網關到服務,從服務到服務,都須要將 Trace 信息進行傳遞才能夠將整個鏈路串起來。只有串起來了才能夠在 Cat 中查看到整個鏈路的耗時信息。

本文須要實現的效果就是能夠在請求的入口處(網關),查看到這個請求通過的全部服務,每一個服務中的耗時狀況。

要想將整個請求都串連起來,必需要有一個惟一的請求標識,通常咱們稱之爲 traceId。剩餘的工做就是將鏈路相關的信息層層傳遞下去。

首先在每一個服務的過濾器中進行請求頭信息的接收,好比從網關到服務 A,那麼服務 A 須要接收這些信息而後傳遞給下一個服務。

HTTP 請求的消息樹構建:

// 構建遠程消息樹
if(request.getHeader(CatConstantsExt.CAT_HTTP_HEADER_ROOT_MESSAGE_ID) != null){
        CatContext catContext = new CatContext();
        catContext.addProperty(Cat.Context.ROOT,request.getHeader(CatConstantsExt.CAT_HTTP_HEADER_ROOT_MESSAGE_ID));
        catContext.addProperty(Cat.Context.PARENT,request.getHeader(CatConstantsExt.CAT_HTTP_HEADER_PARENT_MESSAGE_ID));
        catContext.addProperty(Cat.Context.CHILD,request.getHeader(CatConstantsExt.CAT_HTTP_HEADER_CHILD_MESSAGE_ID));
        Cat.logRemoteCallServer(catContext);
}

將消息樹的信息傳遞給下個服務的話就要看你用的調用方式是什麼,若是用 Feign 或者 RestTemplate 均可以利用攔截器來實現傳遞。

public class FeignRequestInterceptor implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate template) {
        CatContext catContext = new CatContext();
        Cat.logRemoteCallClient(catContext,Cat.getManager().getDomain());
        template.header(CatConstantsExt.CAT_HTTP_HEADER_ROOT_MESSAGE_ID, catContext.getProperty(Cat.Context.ROOT));
        template.header(CatConstantsExt.CAT_HTTP_HEADER_PARENT_MESSAGE_ID, catContext.getProperty(Cat.Context.PARENT));
        template.header(CatConstantsExt.CAT_HTTP_HEADER_CHILD_MESSAGE_ID, catContext.getProperty(Cat.Context.CHILD));
    }
}
若是用的是 D
```ubbo 的話能夠用 Dubbo 的 Filter 來實現相同的效果。

最終的效果以下圖,調用了 articles/newest 接口,網關將請求轉發到 article-provider 服務,article-provider 中又調用了 user-provider 的 users/uid 接口獲取用戶信息,最重要的是 user-provider 中有哪些操做的耗時在這裏也能直觀的看到,很是方便。

![](https://s4.51cto.com/images/blog/202008/03/6022de985d2aedb45a4e6ae9dfce385c.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)

完整源碼參考:https://github.com/yinjihuan/kitty[1]

關於做者 :尹吉歡,簡單的技術愛好者,《Spring Cloud 微服務-全棧技術與案例解析》, 《Spring Cloud 微服務 入門 實戰與進階》做者, 公衆號 猿天地 發起人。我的微信 jihuan900 ,歡迎勾搭。

後臺回覆 學習資料 領取學習視頻

![](https://s4.51cto.com/images/blog/202008/03/d97280f531de5cd5dd12bd52e7563f76.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
相關文章
相關標籤/搜索