鏈路追蹤系統:雲原生比賽分析

摘要

本人近日在參加阿里雲原生的鏈路追蹤系統設計比賽,在比賽中感覺收穫頗多,包括一些工具框架的使用,例如okhttp以及springboot,同時也對於如何使用springboot有了更進一步的認識。本博客就自己的收穫以及對於賽題進行簡單的梳理。比賽的詳細介紹詳見比賽首頁

鏈路追蹤

本次比賽是需要實現鏈路追蹤系統,關於鏈路追蹤的詳細介紹可參加官網的詳細介紹,本人簡單說一下我的理解,在本賽題中,鏈路實際上就是多個同處一個事務或流程中的http調用。因爲對於網絡系統編程(或者雲原生or分佈式),單個事務的執行勢必涉及到多個不同系統,而體現在具體執行中,就是一個個不同的http調用組成了一個事務的執行。本質上,同屬一個調用鏈路的http span組成了一個有向無環圖,本次比賽爲了簡化,直接將同屬相同調用鏈路的http span用全局唯一的traceId進行了標識,也就是不需要參賽選手進行調用鏈路的組建,只需要將數據流中所關心的調用鏈路給出即可。

數據格式

比賽中給出的http span是以http流給出的,每條http span佔據一行,數據格式如下:

traceId | startTime | spanId | parentSpanId | duration | serviceName | spanName | host | tags

具體各字段意義解釋如下的:

  • traceId:全局唯一的Id,用作整個鏈路的唯一標識與組裝
  • startTime:調用的開始時間
  • spanId: 調用鏈中某條數據(span)的id
  • parentSpanId: 調用鏈中某條數據(span)的父親id,頭節點的span的parantSpanId爲0
  • duration:調用耗時
  • serviceName:調用的服務名
  • spanName:調用的埋點名
  • host:機器標識,比如ip,機器名
  • tags: 鏈路信息中tag信息,存在多個tag的key和value信息。格式爲key1=val1&key2=val2&key3=val3 比如 http.status_code=200&error=1

比賽給了兩條http流,而且爲了簡化比賽,假定相同traceIdspan前後不會超過2萬條。

賽題分析

在不考慮數據量的條件下,最樸素的解決方法當然就是在客戶端將http流全部緩存下來,然後存入HashMap<String,List<String>>中,其中Key是符合上報條件的traceIdValue是與之對應的所有http span,再按照http spanstartTime屬性升序排序即可。由於數據量龐大,顯然這樣的方案不可行,但是我們注意到題目中給出的提示,假定相同traceIdspan前後不會超過2萬條,這樣我們實際上就可以將龐大的數據流分割成基本單位爲2萬大小的batch來逐步的處理,爲了說明方便,給出如下的示意圖:

如上圖所示,我們將數據流按照上述形式進行了分割以後,實際上就可以轉化爲樸素的解法了,處理紅色batch時,需要將前後各一個batch進行彙總,共同計算結果,這是由於相同的traceId有可能橫跨兩個batch,但是出現在前面還是後面是不確定的,因此需要一起計算。需要注意的是,由於相同的調用鏈路有可能出現在不同的數據流中,我們需要將當前batch多個數據流中有問題的traceId全部彙總以後,在進行彙總計算。說明了整體的算法思路之後,我們分析一下時間複雜度,假設總的數據量爲N,由於每個batch都需要重複計算前後各一個batch,那麼總的複雜度爲3N。

賽題交互邏輯設計

由於比賽要求實現客戶端和服務端,實際上就是將過濾和計算模塊解耦,方便以後的系統設計。客戶端需要進行存在問題的traceId過濾彙報以及數據的緩存服務,後端則負責將客戶端上報過來的有問題的traceId拉取客戶端當前緩存的數據,然後在進行彙總以及最終的上報。由於涉及到複雜的http交互,繪製如下的示意圖明確交互過程:

賽題具體實現

整體設計流程基本上都體現在上圖中了,然後下面闡述實現中的幾個關鍵點:

  • 由於調用鏈路並行存在多條數據流中,我們根據過濾出的traceId後端進行計算時,一定要拿到多條數據流的彙總結果,這樣才能保證結果的正確性。還有就是當客戶端將當前batch和下一個batch過濾結果都彙總完畢時,纔可以進行最終結果的彙總。其目的是爲了保證traceId出現在不同的batch這一現象。

  • 前後端傳遞數據使用okhttp模塊和fastjson,分別爲我們提供了http通信和對象的序列化服務,而http的請求處理我們使用springboot來完成。

  • 爲了方便客戶端和後端的交互,我們設計了TraceIdBatch類,方便我們判斷前後端的狀態。其UML圖如下:

    其中batchPos是爲了標記backend正在處理的batch序號,processCount用來標記已彙總數據裏的個數,當已彙總的數據流大於等於提供的數據流條數,標誌着客戶端當前batch過濾彙報的完成,backend就可以根據彙總的結果向client拉取結果,進行計算。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章