擼了幾天的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 資訊
建立一個新的 上下文, 生成 traceId
和 spanId
,然後存放到 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
,最近致力於幫助更多小夥伴加入大廠,歡迎來撩~