通過ZipKin整理調用鏈路


緣由

公司使用的是Docker+微服務,服務拆分差不多41個了,然后過完年來就接到這個需求,把指定業務功能的業務基線整理出來,比如,登錄這個操作會經過哪些微服務,把登錄這個操作的鏈條列出來,從api--途徑的服務--DB這樣一個鏈條。接到這個需求后,我就傻逼似的一個一個去問開發,然而開發每個人只負責自己開發的模塊,具體途徑的他們也不知道;然后一直拖一直拖,拖到了現在,總得找個辦法把這個給完成了,剛好公司有用到Zipkin這個,但是並不了解,只知道有這么個東西,那就先了解他,然后根據他的數據庫和我們自己的ELK操作日志找到這些個調用鏈路。 

思路

ELK日志會記錄操作日志,日志里會把Zipkin的三個ID打印出來,比如我做一個登陸操作,通過Kibana顯示的ELK里會有登陸這個操作的日志,那我獲取這個登陸操作的SpanId,通過Zipkin的API接口和SpanId可以獲取所有和這個SpanId有關的信息;然后根據獲取的信息把調用鏈給整理出來。 
 

Zipkin的相關了解

 
主要是根據寫篇博文學習;參考地址: https://juejin.im/post/5c3d4df0f265da61307517ad 
 

一、Zipkin的由來

在單機系統使用過程中,如果某個請求響應過慢或者響應出錯,通過查看日志就可以清楚的知道某個請求出了問題;如果在分布式系統中,客戶端一個請求到達服務器后,由多個服務協作完成。如服務A調用服務B,服務B調用服務C,服務C調用服務D,那么想要知道哪個服務處理時間過長或是處理異常導致的話,就需要一個服務一個服務的去機器查看日志,先定位出問題的服務,再定位出問題的地方。隨着系統越來越壯大,服務越來越多,一個請求對應處理的服務調用鏈就越長,這種排查方式很艱難,為了解決這個問題,便誕生了各種分布式場景中追蹤問題的解決方案,zipkin就是其中之一。
 

二、什么是ZipKin

一個獨立的分布式追蹤系統,客戶端存在於應用中(各個服務中),應具備追蹤信息生成,采集發送等功能,而服務端應該包含以下基本的三個功能
1)信息收集:用來收集各服務端采集的信息,並對這些信息進行梳理存儲、建立索引
2)數據存儲:存儲追蹤數據
3)查詢服務:提供查詢請求鏈路信息的接口
 
三、 它的整體結構圖
 
 
 
Zipkin(服務端)包含四個組件,分別是collector,storage,search,Web UI
1)collector信息收集器,作為一個守護進程,它會時刻等待着客戶端傳遞過來的追蹤數據,對這些數據進程驗證,存儲以及創建查詢需要的索引
2)storage是存儲組件,zipkin默認直接將數據存儲在內存中,此外支持使用Cassandra、Elasticsearch和Mysql
3)search是一個查詢進程,它提供了簡單的JSON API來提供外部調用查詢
4)Web UI是zipkin的服務端展示平台,主要調用search提供的接口,用圖標將鏈路信息清晰的展示
 
四、基本概念
 
Trace: 一個請求達到應用后所調用的所有服務組成的調用鏈就像一個樹結構(如圖),我們追蹤這個調用鏈路得到的這個數結構可以稱之為Trace
Span:在一次Trace中,每個服務的每一次調用,就是一個基本工作單元(如圖中的每一個樹節點),稱之為span
 
 
 
每一個span都有一個id作為唯一標識,同樣每一次Trace都會生成一個traceID在span中作為追蹤評標識,另外再通過一個parentId標明本次調用的發起者(就是發起者的span-id)。當span有了上面三個標識后,就可以很清晰的將多個span進行梳理串聯,最終歸納出一條完整的跟蹤鏈路。
 
 
五、實戰
 
1)根據指定的trace_id獲得返回值,然后根據返回值分析調用鏈
 
curl http://localhost:9411/api/v2/trace/2e0d4019eb7aae31

 

2)獲取所有的服務
 
curl http://localhost:9411/api/v2/services

 

3)span數據結構詳解
 
一次追蹤鏈路會包含很多的span,因此一個span便是一個數組,標准的json為:
 
[
  {
    "traceId": "string",    // 追蹤鏈路ID
    "name": "string",       // span名稱,一般為方法名稱
    "parentId": "string",   // 調用者ID
    "id": "string",         // spanID
    "kind": "CLIENT",       // 替代zipkin v1的注解中的四個核心狀態,詳細介紹見下文
    "timestamp": 0,         // 時間戳,調用時間
    "duration": 0,          // 持續時間-調用的服務所消耗的時間
    "debug": true,          
    "shared": true,
    "localEndpoint": {      // 本地網絡節點上下文
      "serviceName": "string",
      "ipv4": "string",
      "ipv6": "string",
      "port": 0
    },
    "remoteEndpoint": {    // 遠端網絡節點上下文
      "serviceName": "string",
      "ipv4": "string",
      "ipv6": "string",
      "port": 0
    },
    "annotations": [      // value通常是縮寫代碼,對應的時間戳表示代碼標記事件的時間
      {
        "timestamp": 0,
        "value": "string"
      }
    ],
    "tags": {        // span的上下文信息,比如:http.method、http.path
      "additionalProp1": "string",
      "additionalProp2": "string",
      "additionalProp3": "string"
    }
  }
]

 

我的根據返回的json信息,並根據 traceId、 parentId、id、kind(CLINET、CLIENT)把誰調用誰,哪個服務到哪個服務整理出來:
 
 
六、有關Cassandra數據庫相關操作
 
1)連接數據庫
cqlsh 172.10.0.5

 

2)查看所有的庫
 
cqlsh> describe keyspaces;

 

3)使用指定的庫
cqlsh> use zipkin2;

 

4)查看所有的表
cqlsh> describe tables;

 

5)根據指定條件查詢
#查詢前得對查詢列建立索引
cqlsh:zipkin2> create index on span(trace_id);
cqlsh:zipkin2> select * from trace_by_service_span where trace_id='f81a638649326474';

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM