分布式鏈路追蹤實(shí)踐(二) - 基于 OpenTracing 設(shè)計(jì)通用的鏈路追蹤設(shè)計(jì)

上一章中有對(duì)分布式追蹤鏈路方案 (Jaeger, Zipkin, SkyWalking 等) 進(jìn)行了介紹,不同的方案適用不同場(chǎng)景记劝、團(tuán)隊(duì)慢叨、開(kāi)發(fā)語(yǔ)言。在接入分布式鏈路追蹤過(guò)程中丽惭,會(huì)有不同的團(tuán)隊(duì)使用不同的方案實(shí)現(xiàn)击奶,如 A 團(tuán)隊(duì)使用的是 Zipkin, 而 B 團(tuán)隊(duì)使用的 Jaeger, 這樣就會(huì)存在不同追蹤系統(tǒng)的 API 兼容問(wèn)題 (切換方案會(huì)帶來(lái)比較大的改動(dòng)),為了解決這個(gè)問(wèn)題责掏,誕生了 OpenTracing 規(guī)范柜砾。

OpenTracing 規(guī)范

OpenTracing 是?個(gè)輕量級(jí)的標(biāo)準(zhǔn)化層,它位于應(yīng)?程序/類庫(kù)和追蹤或?志分析程序之間换衬,是?套分布式追蹤協(xié)議痰驱,與平臺(tái)证芭,語(yǔ)??關(guān),統(tǒng)?接?担映,?便開(kāi)發(fā)接?不同的分布式追蹤系統(tǒng)废士。

  • 語(yǔ)義規(guī)范 : 描述定義的數(shù)據(jù)模型 Tracer,Sapn 和 SpanContext 等蝇完;

  • 語(yǔ)義慣例 : 羅列出 tag 和 logging 操作時(shí)官硝,標(biāo)準(zhǔn)的key值;

OpenTracing

OpenTracing API

Trace

OpenTracing 中的 Trace(調(diào)?鏈)通過(guò)歸屬此鏈的 Span 來(lái)隱性定義短蜕。?條 Trace 可以認(rèn)為?個(gè)有多個(gè) Span 組成的有向?環(huán)圖(DAG圖)氢架,Span 是?個(gè)邏輯執(zhí)?單元,Span 與 Span 的因果關(guān)系命名為 References朋魔。

OpenTracing 定義兩種關(guān)系:

  • Childof:如下例?中岖研, SpanC 是 childof SpanA
  • FollowsFrom:如下例?中,SpanG 是 followsFrom SpanF
Trace
  • SpanC 是 childof SpanA, SpanG 是 FollowsFrom SpanF

  • childof指的是垂直鏈路, FollowsFrom 指的是橫向鏈路

Span

Span封裝了如下?tīng)顟B(tài)

  • 操作名稱

  • 開(kāi)始時(shí)間戳

  • 結(jié)束時(shí)間戳

  • ?組零或多個(gè)鍵:值結(jié)構(gòu)的 Span標(biāo)簽 (Tags)警检。鍵必須是字符串缎玫。值可以是字符串,布爾或數(shù)值類型.

  • ?組零或多個(gè) Span?志 (Logs)解滓,其中每個(gè)都是?個(gè)鍵:值映射并與?個(gè)時(shí)間戳配對(duì)。鍵必須是字符串筝家,值可以是任何類型洼裤。 并?所有的 OpenTracing 實(shí)現(xiàn)都必須?持每種值
    類型。

  • ?個(gè) SpanContext

  • 零或多個(gè)因果相關(guān)的 Span 間的 References (通過(guò)那些相關(guān)的 Span 的 SpanContext )

SpanContext 封裝了如下?tīng)顟B(tài)

  • 任何需要跟跨進(jìn)程 Span 關(guān)聯(lián)的溪王,依賴于 OpenTracing 實(shí)現(xiàn)的狀態(tài)(例如 Trace 和 Span 的 id)

  • 鍵:值 結(jié)構(gòu)的跨進(jìn)程的 Baggage Items(區(qū)別于 span tag腮鞍,baggage 是全局范圍,在 span 間保持傳遞莹菱,?tag 是 span 內(nèi)部移国,不會(huì)被? span 繼承使?。)

Trace/Span Identity

Trace/Span Identity 
Key 
uber-trace-id
? Case-insensitive in HTTP
? Lower-case in protocols that preserve header case
Value 
{trace-id}:{span-id}:{parent-span-id}:{flags}
? {trace-id} ? 64-bit or 128-bit random number in base16 format
? Can be variable length, shorter values are 0-padded on the left
? Clients in some languages support 128-bit, migration pending
? Value of 0 is not valid
? {span-id} ? 64-bit random number in base16 format
? Value of 0 is not valid
? {parent-span-id} ? 64-bit value in base16 format representing parent span id
? Deprecated, most Jaeger clients ignore on the receiving side, but still include it on the sending side
? 0 value is valid and means “root span” (when not ignored)
? {flags} ? One byte bitmap, as two hex digits
? Bit 1 (right-most, least significant, bit mask 0x01) is “sampled” flag
? 1 means the trace is sampled and all downstream services are advised to respect that
? 0 means the trace is not sampled and all downstream services are advised to respect that
? We’re considering a new feature that allows downstream services to upsample if they find their tracing level is too low
? Bit 2 (bit mask 0x02 ) is “debug” flag
? Debug flag should only be set when the sampled flag is set
? Instructs the backend to try really hard not to drop this trace
? Bit 3 (bit mask 0x04 ) is not used
? Bit 4 (bit mask 0x08 ) is “firehose” flag
? Spans tagged as “firehose” are excluded from being indexed in the storage
? The traces can only be retrieved by trace ID (usually available from other sources, like logs)
? Other bits are unused

Inject 和 Extract 操作

  1. 跨進(jìn)程道伟,機(jī)器通訊迹缀,通過(guò)傳遞 Spancontext 來(lái)提供?夠的信息建? span 間的關(guān)系。

  2. SpanContext 通過(guò) Inject 操作向 Carrier 中增加蜜徽,傳遞后通過(guò) Extracted 從 Carrier 中取出祝懂。

Inject

// TracerWrapper tracer wrapper
func AddTracer(ctx context.Context, r *http.Request, tracer opentracing.Tracer, tags map[string]string) context.Context {
    //初始化 tracer
    opentracing.InitGlobalTracer(tracer)
    var sp opentracing.Span
    //從 header 中獲取 span
    spanCtx, _ := opentracing.GlobalTracer().Extract(opentracing.HTTPHeaders, 
        opentracing.HTTPHeadersCarrier(r.Header))
    if spanCtx != nil {
        sp = opentracing.GlobalTracer().StartSpan(r.URL.Path, opentracing.ChildOf(spanCtx))
    }else{
    //如果 header 中沒(méi)有攜帶 context, 則新建 span
        sp = tracer.StartSpan(r.URL.Path)
    }
    //寫入 tag 或者 日志
    for k, v := range tags {
        // sp.LogKV(k, v)
        // sp.SetTag(k, v)
        sp.LogFields(
            spanLog.String(k, v),
        )
    }
    //注入span (用于傳遞)
    if err := opentracing.GlobalTracer().Inject(
        sp.Context(),
        opentracing.HTTPHeaders,
        opentracing.HTTPHeadersCarrier(r.Header)); err != nil {
        logger.Fatalln("inject failed", err)
    }
    ...
}

Extracted

// TracerWrapper tracer wrapper
 func AddTracer(ctx context.Context, r *http.Request, tracer opentracing.Tracer, tags map[string]string) context.Context {
    //初始化 tracer
    opentracing.InitGlobalTracer(tracer)
    var sp opentracing.Span
    //從 header 中獲取 span
    spanCtx, _ := opentracing.GlobalTracer().Extract(opentracing.HTTPHeaders, 
        opentracing.HTTPHeadersCarrier(r.Header))
    if spanCtx != nil {
        sp = opentracing.GlobalTracer().StartSpan(r.URL.Path, opentracing.ChildOf(spanCtx))
    }else{
    //如果 header 中沒(méi)有攜帶 context, 則新建 span
        sp = tracer.StartSpan(r.URL.Path)
    }
    //寫入 tag 或者 日志
    for k, v := range tags {
        // sp.LogKV(k, v)
        // sp.SetTag(k, v)
        sp.LogFields(
            spanLog.String(k, v),
        )
    }
    ...
 }
  1. 分布式跟蹤(包擴(kuò)跨服務(wù),進(jìn)程拘鞋,主機(jī)等)需要對(duì) trace 上下? (spanContext) 進(jìn)?傳遞砚蓬,通過(guò) Inject ?法, 在 io.Writer 中注?上下?信息,服務(wù)端通過(guò) Extracted 取出盆色,通過(guò)對(duì)上下?和業(yè)務(wù)邏輯判斷 span 之間的關(guān)系(childof or followsfrom)灰蛙。

Sampling,采樣

OpenTracing API 不強(qiáng)調(diào)采樣的概念祟剔,但是?多數(shù)追蹤系統(tǒng)通過(guò)不同?式實(shí)現(xiàn)采樣。有些情況下摩梧,應(yīng)?系統(tǒng)需要通知追蹤程序物延,這條特定的調(diào)?需要被記錄,即使根據(jù)默認(rèn)采樣規(guī)則障本,它不需要被記錄教届。sampling.priority tag 提供這樣的?式。追蹤系統(tǒng)不保證?定采納這個(gè)參數(shù)驾霜,但是會(huì)盡可能的保留這條調(diào)?案训。

sampling.priority - integer

  • 如果?于 0, 追蹤系統(tǒng)盡可能保存這條調(diào)?鏈
  • 等于 0, 追蹤系統(tǒng)不保存這條調(diào)?鏈
  • 如果此tag沒(méi)有提供,追蹤系統(tǒng)使???的默認(rèn)采樣規(guī)則

采樣速率

?產(chǎn)環(huán)境系統(tǒng)性能很重要粪糙,所以對(duì)于所有的請(qǐng)求都開(kāi)啟 Trace 顯然會(huì)帶來(lái)?較?的壓?强霎,另外,?量的數(shù)據(jù)也會(huì)帶來(lái)很?存儲(chǔ)壓?蓉冈。為此城舞,jaeger ?持設(shè)置采樣速率,根據(jù)系統(tǒng)實(shí)際情況設(shè)置合適的采樣頻率寞酿。

Jaeger 官?提供了多種采集策略家夺,使?者可以按需選擇使?:

  • const,全量采集伐弹,采樣率設(shè)置0,1 分別對(duì)應(yīng)打開(kāi)和關(guān)閉;
  • probabilistic拉馋,概率采集,默認(rèn)萬(wàn)份之?惨好,0~1之間取值;
  • rateLimiting煌茴,限速采集,每秒只能采集?定量的數(shù)據(jù);
  • remote日川,?種動(dòng)態(tài)采集策略蔓腐,根據(jù)當(dāng)前系統(tǒng)的訪問(wèn)量調(diào)節(jié)采集策略;

總結(jié)

  1. OpenTracing 設(shè)計(jì)類似于 Interface 抽象層設(shè)計(jì), 很適合不同方案兼容的場(chǎng)景, 并且具有很好的擴(kuò)展性, 后期改動(dòng)成本較小;
  2. 適合生產(chǎn)方案遷移 ;

在生產(chǎn)中使用 OpenTracing 需要考慮兼容不同協(xié)議的鏈路追蹤問(wèn)題,下一章和大家分享 支持 HTTP 和 gRPC 分布式鏈路追蹤 SDK 設(shè)計(jì) 龄句。

原文: 分布式鏈路追蹤實(shí)踐(二)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末回论,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子分歇,更是在濱河造成了極大的恐慌透葛,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件卿樱,死亡現(xiàn)場(chǎng)離奇詭異僚害,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門萨蚕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)靶草,“玉大人,你說(shuō)我怎么就攤上這事岳遥∞认瑁” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵浩蓉,是天一觀的道長(zhǎng)派继。 經(jīng)常有香客問(wèn)我,道長(zhǎng)捻艳,這世上最難降的妖魔是什么驾窟? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮认轨,結(jié)果婚禮上绅络,老公的妹妹穿的比我還像新娘。我一直安慰自己嘁字,他們只是感情好恩急,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著纪蜒,像睡著了一般衷恭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上纯续,一...
    開(kāi)封第一講書(shū)人閱讀 49,144評(píng)論 1 285
  • 那天随珠,我揣著相機(jī)與錄音,去河邊找鬼杆烁。 笑死,一個(gè)胖子當(dāng)著我的面吹牛简卧,可吹牛的內(nèi)容都是我干的兔魂。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼举娩,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼析校!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起铜涉,我...
    開(kāi)封第一講書(shū)人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤智玻,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后芙代,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體吊奢,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年纹烹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了页滚。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片召边。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖裹驰,靈堂內(nèi)的尸體忽然破棺而出隧熙,到底是詐尸還是另有隱情,我是刑警寧澤幻林,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布贞盯,位于F島的核電站,受9級(jí)特大地震影響沪饺,放射性物質(zhì)發(fā)生泄漏躏敢。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一随闽、第九天 我趴在偏房一處隱蔽的房頂上張望父丰。 院中可真熱鬧,春花似錦掘宪、人聲如沸蛾扇。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)镀首。三九已至,卻和暖如春鼠次,著一層夾襖步出監(jiān)牢的瞬間更哄,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工腥寇, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留成翩,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓赦役,卻偏偏與公主長(zhǎng)得像麻敌,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子掂摔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容