分散式跟蹤系統的四大功能模組如何協同工作

2020-02-03 00:44:00

了解分散式跟蹤中的主要體系結構決策,以及各部分如何組合在一起。

早在十年前,認真研究過分散式跟蹤基本上只有學者和一小部分大型網際網路公司中的人。對於任何採用微服務的組織來說,它如今成為一種籌碼。其理由是確立的:微服務通常會發生讓人意想不到的錯誤,而分散式跟蹤則是描述和診斷那些錯誤的最好方法。

也就是說,一旦你準備將分散式跟蹤整合到你自己的應用程式中,你將很快意識到對於不同的人來說“分散式跟蹤Distributed Tracing”一詞意味著不同的事物。此外,跟蹤生態系統裡擠滿了具有相似內容的重疊專案。本文介紹了分散式跟蹤系統中四個(可能)獨立的功能模組,並描述了它們間將如何協同工作。

分散式跟蹤:一種思維模型

大多數用於跟蹤的思維模型來源於 Google 的 Dapper 論文OpenTracing 使用相似的術語,因此,我們從該專案借用了以下術語:

Tracing

  • 跟蹤Trace:事物在分散式系統執行的過程描述。
  • 跨度Span:一種命名的定時操作,表示工作流的一部分。跨度可接受鍵值對標籤以及附加到特定跨度範例的細粒度的、帶有時間戳的結構化紀錄檔。
  • 跨度上下文Span context:攜帶分散式事務的跟蹤資訊,包括當它通過網路或訊息匯流排將服務傳遞給服務時。跨度上下文包含跟蹤識別符號、跨度識別符號以及跟蹤系統所需傳播到下游服務的任何其他資料。

如果你想要深入研究這種思維模式的細節,請仔細參照 OpenTracing 技術規範

四大功能模組

從應用層分散式跟蹤系統的觀點來看,現代軟體系統架構如下圖所示:

Tracing

現代軟體系統的元件可分為三類:

  • 應用程式和業務邏輯:你的程式碼。
  • 廣泛共用庫:他人的程式碼
  • 廣泛共用服務:他人的基礎架構

這三類元件有著不同的需求,驅動著監控應用程式的分散式跟蹤系統的設計。最終的設計得到了四個重要的部分:

  • 跟蹤檢測 APIA tracing instrumentation API:修飾應用程式程式碼
  • 線路協定Wire protocol:在 RPC 請求中與應用程式資料一同傳送的規定
  • 資料協定Data protocol:將非同步資訊(帶外)傳送到你的分析系統的規定
  • 分析系統Analysis system:用於處理跟蹤資料的資料庫和互動式使用者介面

為了更深入的解釋這個概念,我們將深入研究驅動該設計的細節。如果你只需要我的一些建議,請跳轉至下方的四大解決方案。

需求,細節和解釋

應用程式程式碼、共用庫以及共用式服務在操作上有顯著的差別,這種差別嚴重影響了對其進行檢測的請求操作。

檢測應用程式程式碼和業務邏輯

在任何特定的微服務中,由微服務開發者編寫的大部分程式碼是應用程式或者商業邏輯。這部分程式碼規定了特定區域的操作。通常,它包含任何特殊、獨一無二的邏輯判斷,這些邏輯判斷首先證明了建立新型微服務的合理性。基本上按照定義,該程式碼通常不會在多個服務中共用或者以其他方式出現。

也即是說你仍需了解它,這也意味著需要以某種方式對它進行檢測。一些監控和跟蹤分析系統使用黑盒代理black-box agents自動檢測程式碼,另一些系統更想使用顯式的白盒檢測工具。對於後者,抽象跟蹤 API 提供了許多對於微服務的應用程式程式碼來說更為實用的優勢:

  • 抽象 API 允許你在不重新編寫檢測程式碼的條件下換新的監視工具。你可能想要變更雲服務提供商、供應商和監測技術,而一大堆不可移植的檢測程式碼將會為該過程增加有意義的開銷和麻煩。
  • 事實證明,除了生產監控之外,該工具還有其他有趣的用途。現有的專案使用相同的跟蹤工具來驅動測試工具、分散式偵錯程式、“混沌工程”故障注入器和其他元應用程式。
  • 但更重要的是,若將應用程式元件提取到共用庫中要怎麼辦呢?由上述內容可得到結論:

檢測共用庫

在大多數應用程式中出現的實用程式程式碼(處理網路請求、資料庫呼叫、磁碟寫操作、執行緒、並行管理等)通常情況下是通用的,而非特別應用於某個特定應用程式。這些程式碼會被打包成庫和框架,而後就可以被裝載到許多的微服務上並且被部署到多種不同的環境中。

其真正的不同是:對於共用程式碼,其他人則成為了使用者。大多數使用者有不同的依賴關係和操作風格。如果嘗試去使用該共用程式碼,你將會注意到幾個常見的問題:

  • 你需要一個 API 來編寫檢測。然而,你的庫並不知道你正在使用哪個分析系統。會有多種選擇,並且執行在相同應用下的所有庫無法做出不相容的選擇。
  • 由於這些包封裝了所有網路處理程式碼,因此從請求報頭注入和提取跨度上下文的任務往往指向 RPC 庫。然而,共用庫必須了解到每個應用程式正在使用哪種跟蹤協定。
  • 最後,你不想強制使用者使用相互衝突的依賴項。大多數使用者有不同的依賴關係和操作風格。即使他們使用 gRPC,係結的 gRPC 版本是否相同?因此任何你的庫附帶用於跟蹤的監控 API 必定是免於依賴的。

因此,一個(a)沒有依賴關係、(b)與線路協定無關、(c)使用流行的供應商和分析系統的抽象 API 應該是對檢測共用庫程式碼的要求。

檢測共用式服務

最後,有時整個服務(或微服務集合體)的通用性足以使許多獨立的應用程式使用它們。這種共用式服務通常由第三方託管和管理,例如快取伺服器、訊息佇列以及資料庫。

從應用程式開發者的角度來看,理解共用式服務本質上是黑盒子是極其重要的。它不可能將你的應用程式監控注入到共用式服務。恰恰相反,托管服務通常會執行它自己的監控方案。

四個方面的解決方案

因此,抽象的跟蹤應用程式介面將會幫助庫發出資料並且注入/抽取跨度上下文。標準的線路協定將會幫助黑盒服務相互連線,而標準的資料格式將會幫助分離的分析系統合併其中的資料。讓我們來看一下部分有希望解決這些問題的方案。

跟蹤 API:OpenTracing 專案

如你所見,我們需要一個跟蹤 API 來檢測應用程式程式碼。為了將這種工具擴充套件到大多數進行跨度上下文注入和提取的共用庫中,則必須以某種關鍵方式對 API 進行抽象。

OpenTracing 專案主要針對解決庫開發者的問題,OpenTracing 是一個與供應商無關的跟蹤 API,它沒有依賴關係,並且迅速得到了許多監控系統的支援。這意味著,如果庫附帶了內建的本地 OpenTracing 工具,當監控系統在應用程式啟動連線時,跟蹤將會自動啟動。

就個人而言,作為一個已經編寫、發布和操作開源軟體十多年的人,在 OpenTracing 專案上工作並最終解決這個觀察性的難題令我十分滿意。

除了 API 之外,OpenTracing 專案還維護了一個不斷增長的工具列表,其中一些可以在這裡找到。如果你想參與進來,無論是通過提供一個檢測外掛,對你自己的 OSS 庫進行本地測試,或者僅僅只想問個問題,都可以通過 Gitter 向我們打招呼。

線路協定: HTTP 報頭 trace-context

為了監控系統能進行互操作,以及減輕從一個監控系統切換為另外一個時帶來的遷移問題,需要標準的線路協定來傳播跨度上下文。

w3c 分散式跟蹤上下文社群小組在努力制定此標準。目前的重點是制定一系列標準的 HTTP 報頭。該規範的最新草案可以在此處找到。如果你對此小組有任何的疑問,郵寄清單Gitter 聊天室是很好的解惑地點。

(LCTT 譯註:本文原文發表於 2018 年 5 月,可能現在社群已有不同進展)

資料協定 (還未出現!!)

對於黑盒服務,在無法安裝跟蹤程式或無法與程式進行互動的情況下,需要使用資料協定從系統中匯出資料。

目前這種資料格式和協定的開發工作尚處在初級階段,並且大多在 w3c 分散式跟蹤上下文工作組的上下文中進行工作。需要特別關注的是在標準資料模式中定義更高階別的概念,例如 RPC 呼叫、資料庫語句等。這將允許跟蹤系統對可用資料型別做出假設。OpenTracing 專案也通過定義一套標準標籤集來解決這一事務。該計劃是為了使這兩項努力結果相互配合。

注意當前有一個中間地帶。對於由應用程式開發者操作但不想編譯或以其他方式執行程式碼修改的“網路裝置”,動態連結可以幫助避免這種情況。主要的例子就是服務網格和代理,就像 Envoy 或者 NGINX。針對這種情況,可將相容 OpenTracing 的跟蹤器編譯為共用物件,然後在執行時動態連結到可執行檔案中。目前 C++ OpenTracing API 提供了該選項。而 JAVA 的 OpenTracing 跟蹤器解析也在開發中。

這些解決方案適用於支援動態連結,並由應用程式開發者部署的的服務。但從長遠來看,標準的資料協定可以更廣泛地解決該問題。

分析系統:從跟蹤資料中提取有見解的服務

最後不得不提的是,現在有足夠多的跟蹤監視解決方案。可以在此處找到已知與 OpenTracing 相容的監控系統列表,但除此之外仍有更多的選擇。我更鼓勵你研究你的解決方案,同時希望你在比較解決方案時發現本文提供的框架能派上用場。除了根據監控系統的操作特性對其進行評級外(更不用提你是否喜歡 UI 和其功能),確保你考慮到了上述三個重要方面、它們對你的相對重要性以及你感興趣的跟蹤系統如何為它們提供解決方案。

結論

最後,每個部分的重要性在很大程度上取決於你是誰以及正在建立什麼樣的系統。舉個例子,開源庫的作者對 OpenTracing API 非常感興趣,而服務開發者對 trace-context 規範更感興趣。當有人說一部分比另一部分重要時,他們的意思通常是“一部分對我來說比另一部分重要”。

然而,事實是:分散式跟蹤已經成為監控現代系統所必不可少的事物。在為這些系統進行構建模組時,“盡可能解耦”的老方法仍然適用。在構建像分散式監控系統一樣的跨系統的系統時,乾淨地解耦元件是維持靈活性和前向相容性地最佳方式。

感謝你的閱讀!現在當你準備好在你自己的應用程式中實現跟蹤服務時,你已有一份指南來了解他們正在談論哪部分部分以及它們之間如何相互共同作業。