本來計劃接着上文介紹Skywalking的架構,但是我想了一下,覺得還是有必要先把鏈路跟蹤裏面涉及的一些基礎概念術語介紹一下,介紹這些Skywalking並不是一個比較好的選擇。原因一方面是Skywalking只是衆多APM實現之一,裏面有些設計並不適合其它APM,另一方面Skywalking提供的比較好的探針多時Java的,而且是字節碼注入的,不利於觀察學習。當然最重要的是有一個更合適的選擇:OpenTracing。

OpenTracing介紹

分佈式請求/鏈路跟蹤(Distributed Request Tracing)最早是Google內部在用,後來相對成熟以後,2010年對外發布了一篇論文: Dapper, a Large-Scale Distributed Systems Tracing Infrastructure ,但沒有將系統開源。接着就有一些公司和社區開始基於Dapper實現自己的鏈路跟蹤系統,比較有名的有(這裏只列舉開源的):Twitter的Zipkin、韓國的PinPoint、大衆點評的CAT,以及一些後起之秀:Uber的Jaeger,Apache Skywalking等。

在百花齊放的時候,出現了OpenTracing,關於它的介紹官方是這樣說的:

What is OpenTracing?

It is probably easier to start with what OpenTracing is NOT.

  • OpenTracing is not a download or a program. Distributed tracing requires that software developers add instrumentation to the code of an application, or to the frameworks used in the application.
  • OpenTracing is not a standard. The Cloud Native Computing Foundation (CNCF) is not an official standards body. The OpenTracing API project is working towards creating more standardized APIs and instrumentation for distributed tracing.

OpenTracing is comprised of an API specification, frameworks and libraries that have implemented the specification, and documentation for the project. OpenTracing allows developers to add instrumentation to their application code using APIs that do not lock them into any one particular product or vendor.

我簡單概括一下,OpenTracing制定了一些鏈路跟蹤的API規範,並且提供了一些框架和庫,這些框架和庫實現了它制定的那些API規範。而且它是一個獨立開放的項目,現在已經是雲原生基金會(Cloud Native Computing Foundation, CNCF)的項目了。任何組織和個人都可以貢獻符合API規範的庫/框架。雖然OpenTracing不是一個標準規範,但現在大多數鏈路跟蹤系統都在儘量兼容OpenTracing。

需要重點說明的是OpenTracing提供的框架和庫只是採集最原始的鏈路數據,並不做分析。如果放到Skywalking的架構中,它只實現了探針部分。也就是OpenTracing並不是一個完備的鏈路系統,所以我們無法單獨使用,必須配合兼容OpenTracing規範的系統使用,比如Jaeger、LightStep、Apache Skywalking、Elastic APM等。

最新的進展是OpenTracing已經和CNCF的另外一個項目 OpenTelemetry 合併了。

題外話:雖然APM各個系統號稱兼容OpenTracing,但兼容性到底如何,其實還是參差不齊的,比如Jaeger就比Skywalking兼容性好。

OpenTracing 術語介紹

說明:

  • 基本上所有的鏈路跟蹤系統以及OpenTracing裏面術語大多都是來自於Dapper論文裏面的。下面介紹的規範都是OpenTracing定義的一些規範
  • 爲了方便理解和交流,概念術語等使用英文,不做翻譯。

分佈式鏈路跟蹤系統的數據模型:

Traces(一般翻譯爲鏈路):一起請求從發出,然後經過多個模塊(這個模塊可能是函數或者系統,或者都有),最終得到請求回覆,整個請求按照調用時間和關係串起來就是一個trace。

Span則是組成trace的最基本單元,它一般代表分佈式系統中一個獨立的工作單元。有點抽象,沒關係,後面看一些例子就懂了。一個Span包含如下幾部分:

  • 操作名稱:一般用於展示、過濾、聚合
  • 開始和結束時間戳:用於計算耗時
  • 由key-value組成的Tags:用於添加一些時間無關的信息(可選)
  • 由key-value組成幷包含時間戳的Logs:用於添加一些時間相關的信息(可選)
  • span上下文,即SpanContext。一般包含兩部分數據:(1)span的狀態數據,比如traceID和spanID(2)Baggage Items。Baggage是鏈路跟蹤提供的一個通用的跨進程/服務傳遞數據的方式,格式也是key-value形式的。

Trace就是由若干個span組成的有向無環圖,圖中的每個節點就是Span,連接節點的邊稱之爲 References 。每個trace有一個唯一標識符traceID,每個span也有一個唯一標識符spanID。一個鏈路中的所有span的traceID是相同的,但spanID各不相同。一個鏈路中span典型的調用關係圖如下:

Causal relationships between Spans in a single Trace


        [Span A]  ←←←(the root span)
            |
     +------+------+
     |             |
 [Span B]      [Span C] ←←←(Span C is a `ChildOf` Span A)
     |             |
 [Span D]      +---+-------+
               |           |
           [Span E]    [Span F] >>> [Span G] >>> [Span H]
                                       ↑
                                       ↑
                                       ↑
                         (Span G `FollowsFrom` Span F)

對應的時間維度爲:

Temporal relationships between Spans in a single Trace


––|–––––––|–––––––|–––––––|–––––––|–––––––|–––––––|–––––––|–> time

 [Span A···················································]
   [Span B··············································]
      [Span D··········································]
    [Span C········································]
         [Span E·······]        [Span F··] [Span G··] [Span H··]

其實很簡單,就是個調用關係。需要說明的是一個trace的span間有兩種可能的關係:

  • ChildOf :即父子關係,也是最常見的關係。比如上圖中的Span A和Span B、Span C就是父子關係,表示只有Span B和Span C(包括Span A和Span B的所有子Span)都完成了,Span A才能完成,類似於同步調用(僅僅是類似於,並不完全一樣)。
  • FollowsFrom :其實也是父子關係,子Span是由父Span調用產生的,但父Span是否完成不依賴於子Span。比如圖中的Span F和Span G就屬於FollowsFrom關係。Span G由Span F調用創建,但Span F是否完成不依賴於Span G,有點類似於異步調用。

最後需要介紹的一個概念就是“active span”。一個線程裏面可以包含多個span,但同一時刻只能有一個span處於工作狀態,這個span稱之爲 ActiveSpan 。Span可以有這麼幾個狀態:

  • Started
  • Not Finished
  • Not "active"
  • Active

Span的狀態由 ScopeManager 管理,但是否實現由開發者決定。另外OpenTracing定義了Inject和Extract接口來簡化SpanContext跨進程傳遞。

如果你是第一次瞭解分佈式鏈路跟蹤,看了上面這些,我相信你還是一頭霧水,心裏有很多疑問。沒事,理論結合實踐是掌握知識最佳的手段,先對這些概念有個大概理解和印象,然後看下面的幾篇實戰文章:

說明:這4篇文章內容主要翻譯(意譯)自Yurishkuro大神的 opentracing-tutorial java ,加了一些補充說明以及在Jaeger UI上面的展示,方便理解,習慣看英文的也可以看原文,代碼自行從GitHub拉取。

通過這幾篇文章,對於分佈式鏈路跟蹤基本概念和原理應該可以理解的比較好了。後面會介紹一些SDK如何寫,以及一些具體的APM。

相關文章