1. 程式人生 > 其它 >擼了幾天的sofa-tracer之後,我悟了!

擼了幾天的sofa-tracer之後,我悟了!

什麼是分散式鏈路跟蹤

簡而言之,在分散式系統下,用於跟蹤鏈路而衍生出的一項技術。

應用場景如下:

應用A,B,C,D,E 以一個層級關係依賴, 當用戶向 應用A 發起請求,但是返回了個異常,為了排查這個問題,我們可能要一臺臺伺服器去排查。在分散式架構下,每個應用又部署了幾十上百臺伺服器, 那一天下來,可能多沒找到問題的觸發點。

通過分散式鏈路跟蹤,結合 如 鷹眼 等平臺的 鏈路分析,我們可以很快定位到 問題發生機器地址。

那為什麼我們可以很快速定位到哪臺機器?

  • TraceId 日誌收集,收集異常日誌,快速發現異常原因
  • TraceId 埋入機器IP,快速定位異常機器

基本概念

一條 trace

鏈路是由多個與之關聯的 span 組成,一條鏈路整體可以看做是一張有向無環圖,各個 span之間的邊緣關係被稱之為References

  • traceId: 每條鏈路只有唯一的 traceId
  • spanId : 每個節點為一個 span ,存在層級關係

如何自己實現一套 Tracer

引用 SOFATracer 鏈路透傳原理:

  • 跨程序的透傳,即如何將鏈路資料從一個程序傳遞到下游程序中
  • 執行緒中的透傳
    • 當前請求跨程序呼叫結束之後,當前如何恢復 tracer 上下文資訊
    • 如何實現跨執行緒的透傳,如在當前執行緒中起一個非同步執行緒的場景

TracerId & SpanId 生成規則

TraceId 生成規則:

 伺服器 IP + 產生 ID 時候的時間 + 自增序列 + 當前程序號

0ad1348f1403169275002100356696

SpanId 生成規則:

root 節點為0,後續以 . 分割,不斷分層延續

跨程序透傳 TracerId

SOFATracer 為例 描述一下,一個 Http 請求是如何跨程序間進行傳輸的.

SofaTracer 原始碼地址:

https://github.com/sofastack-guides/sofa-tracer-guides/tree/master/tracer-sample-with-springmvc

在一個 Http 請求中, 當請求經過 Filter

SOFATracer 做的主要就是判斷當前請求的header中是否存在 traceId, spanId

從依賴包中,我們可以看到,只有一個filter

Header存在 Tracer 資訊

將上下文資訊,存放到 ThreadLocal

Header 不存在 Tracer 資訊

建立一個新的 上下文, 生成 traceIdspanId ,然後存放到 ThreadLocal

跨執行緒透傳 TracerId

通過深拷貝,建立一個新的上線文資訊, 將 SofaTracerSpanContext 傳遞到子執行緒中

public SofaTracerSpanContext cloneInstance() {
  // 重新構建一個 SofaTracerSpanContext 物件例項
  // 這裡會以當前父執行緒中的 tracerId,spanId,parentId以及取樣資訊 作為構建構建引數
  SofaTracerSpanContext spanContext = new SofaTracerSpanContext(this.traceId, this.spanId,
  this.parentId, this.isSampled);
  // 系統透傳資料
  spanContext.addSysBaggage(this.sysBaggage);
  // 業務透傳資料
  spanContext.addBizBaggage(this.bizBaggage);
  spanContext.childContextIndex = this.childContextIndex;
  return spanContext;
}

手擼一個 DEMO

MyFilter

總結

原理看著挺簡單,但是實際使用上,還要考慮很多方面的問題, 如果日誌收集,日誌分析,traceId 生成規則等等,感興趣的大夥可以去看一下原始碼: 傳送門

感謝大家的閱讀,希望對大家有所幫助,我是 九靈 ,有需要交流的童鞋可以 加我wx,Jayce-K,最近致力於幫助更多小夥伴加入大廠,歡迎來撩~