分布式跟蹤系統(tǒng)的四大功能模塊如何協(xié)同工作
了解分布式跟蹤中的主要體系結(jié)構(gòu)決策,以及各部分如何組合在一起。
早在十年前,認(rèn)真研究過(guò)分布式跟蹤基本上只有學(xué)者和一小部分大型互聯(lián)網(wǎng)公司中的人。對(duì)于任何采用微服務(wù)的組織來(lái)說(shuō),它如今成為一種籌碼。其理由是確立的:微服務(wù)通常會(huì)發(fā)生讓人意想不到的錯(cuò)誤,而分布式跟蹤則是描述和診斷那些錯(cuò)誤的最好方法。
也就是說(shuō),一旦你準(zhǔn)備將分布式跟蹤集成到你自己的應(yīng)用程序中,你將很快意識(shí)到對(duì)于不同的人來(lái)說(shuō)“分布式跟蹤”一詞意味著不同的事物。此外,跟蹤生態(tài)系統(tǒng)里擠滿了具有相似內(nèi)容的重疊項(xiàng)目。本文介紹了分布式跟蹤系統(tǒng)中四個(gè)(可能)獨(dú)立的功能模塊,并描述了它們間將如何協(xié)同工作。
分布式跟蹤:一種思維模型
大多數(shù)用于跟蹤的思維模型來(lái)源于 Google 的 Dapper 論文。OpenTracing 使用相似的術(shù)語(yǔ),因此,我們從該項(xiàng)目借用了以下術(shù)語(yǔ):
Tracing
- 跟蹤:事物在分布式系統(tǒng)運(yùn)行的過(guò)程描述。
- 跨度:一種命名的定時(shí)操作,表示工作流的一部分。跨度可接受鍵值對(duì)標(biāo)簽以及附加到特定跨度實(shí)例的細(xì)粒度的、帶有時(shí)間戳的結(jié)構(gòu)化日志。
- 跨度上下文:攜帶分布式事務(wù)的跟蹤信息,包括當(dāng)它通過(guò)網(wǎng)絡(luò)或消息總線將服務(wù)傳遞給服務(wù)時(shí)??缍壬舷挛陌櫂?biāo)識(shí)符、跨度標(biāo)識(shí)符以及跟蹤系統(tǒng)所需傳播到下游服務(wù)的任何其他數(shù)據(jù)。
如果你想要深入研究這種思維模式的細(xì)節(jié),請(qǐng)仔細(xì)參照 OpenTracing 技術(shù)規(guī)范。
四大功能模塊
從應(yīng)用層分布式跟蹤系統(tǒng)的觀點(diǎn)來(lái)看,現(xiàn)代軟件系統(tǒng)架構(gòu)如下圖所示:
Tracing
現(xiàn)代軟件系統(tǒng)的組件可分為三類:
- 應(yīng)用程序和業(yè)務(wù)邏輯:你的代碼。
- 廣泛共享庫(kù):他人的代碼
- 廣泛共享服務(wù):他人的基礎(chǔ)架構(gòu)
這三類組件有著不同的需求,驅(qū)動(dòng)著監(jiān)控應(yīng)用程序的分布式跟蹤系統(tǒng)的設(shè)計(jì)。最終的設(shè)計(jì)得到了四個(gè)重要的部分:
- 跟蹤檢測(cè) API:修飾應(yīng)用程序代碼
- 線路協(xié)議:在 RPC 請(qǐng)求中與應(yīng)用程序數(shù)據(jù)一同發(fā)送的規(guī)定
- 數(shù)據(jù)協(xié)議:將異步信息(帶外)發(fā)送到你的分析系統(tǒng)的規(guī)定
- 分析系統(tǒng):用于處理跟蹤數(shù)據(jù)的數(shù)據(jù)庫(kù)和交互式用戶界面
為了更深入的解釋這個(gè)概念,我們將深入研究驅(qū)動(dòng)該設(shè)計(jì)的細(xì)節(jié)。如果你只需要我的一些建議,請(qǐng)?zhí)D(zhuǎn)至下方的四大解決方案。
需求,細(xì)節(jié)和解釋
應(yīng)用程序代碼、共享庫(kù)以及共享式服務(wù)在操作上有顯著的差別,這種差別嚴(yán)重影響了對(duì)其進(jìn)行檢測(cè)的請(qǐng)求操作。
檢測(cè)應(yīng)用程序代碼和業(yè)務(wù)邏輯
在任何特定的微服務(wù)中,由微服務(wù)開(kāi)發(fā)者編寫(xiě)的大部分代碼是應(yīng)用程序或者商業(yè)邏輯。這部分代碼規(guī)定了特定區(qū)域的操作。通常,它包含任何特殊、獨(dú)一無(wú)二的邏輯判斷,這些邏輯判斷首先證明了創(chuàng)建新型微服務(wù)的合理性?;旧习凑斩x,該代碼通常不會(huì)在多個(gè)服務(wù)中共享或者以其他方式出現(xiàn)。
也即是說(shuō)你仍需了解它,這也意味著需要以某種方式對(duì)它進(jìn)行檢測(cè)。一些監(jiān)控和跟蹤分析系統(tǒng)使用黑盒代理自動(dòng)檢測(cè)代碼,另一些系統(tǒng)更想使用顯式的白盒檢測(cè)工具。對(duì)于后者,抽象跟蹤 API 提供了許多對(duì)于微服務(wù)的應(yīng)用程序代碼來(lái)說(shuō)更為實(shí)用的優(yōu)勢(shì):
- 抽象 API 允許你在不重新編寫(xiě)檢測(cè)代碼的條件下?lián)Q新的監(jiān)視工具。你可能想要變更云服務(wù)提供商、供應(yīng)商和監(jiān)測(cè)技術(shù),而一大堆不可移植的檢測(cè)代碼將會(huì)為該過(guò)程增加有意義的開(kāi)銷和麻煩。
- 事實(shí)證明,除了生產(chǎn)監(jiān)控之外,該工具還有其他有趣的用途。現(xiàn)有的項(xiàng)目使用相同的跟蹤工具來(lái)驅(qū)動(dòng)測(cè)試工具、分布式調(diào)試器、“混沌工程”故障注入器和其他元應(yīng)用程序。
- 但更重要的是,若將應(yīng)用程序組件提取到共享庫(kù)中要怎么辦呢?由上述內(nèi)容可得到結(jié)論:
檢測(cè)共享庫(kù)
在大多數(shù)應(yīng)用程序中出現(xiàn)的實(shí)用程序代碼(處理網(wǎng)絡(luò)請(qǐng)求、數(shù)據(jù)庫(kù)調(diào)用、磁盤(pán)寫(xiě)操作、線程、并發(fā)管理等)通常情況下是通用的,而非特別應(yīng)用于某個(gè)特定應(yīng)用程序。這些代碼會(huì)被打包成庫(kù)和框架,而后就可以被裝載到許多的微服務(wù)上并且被部署到多種不同的環(huán)境中。
其真正的不同是:對(duì)于共享代碼,其他人則成為了使用者。大多數(shù)用戶有不同的依賴關(guān)系和操作風(fēng)格。如果嘗試去使用該共享代碼,你將會(huì)注意到幾個(gè)常見(jiàn)的問(wèn)題:
- 你需要一個(gè) API 來(lái)編寫(xiě)檢測(cè)。然而,你的庫(kù)并不知道你正在使用哪個(gè)分析系統(tǒng)。會(huì)有多種選擇,并且運(yùn)行在相同應(yīng)用下的所有庫(kù)無(wú)法做出不兼容的選擇。
- 由于這些包封裝了所有網(wǎng)絡(luò)處理代碼,因此從請(qǐng)求報(bào)頭注入和提取跨度上下文的任務(wù)往往指向 RPC 庫(kù)。然而,共享庫(kù)必須了解到每個(gè)應(yīng)用程序正在使用哪種跟蹤協(xié)議。
- 最后,你不想強(qiáng)制用戶使用相互沖突的依賴項(xiàng)。大多數(shù)用戶有不同的依賴關(guān)系和操作風(fēng)格。即使他們使用 gRPC,綁定的 gRPC 版本是否相同?因此任何你的庫(kù)附帶用于跟蹤的監(jiān)控 API 必定是免于依賴的。
因此,一個(gè)(a)沒(méi)有依賴關(guān)系、(b)與線路協(xié)議無(wú)關(guān)、(c)使用流行的供應(yīng)商和分析系統(tǒng)的抽象 API 應(yīng)該是對(duì)檢測(cè)共享庫(kù)代碼的要求。
檢測(cè)共享式服務(wù)
最后,有時(shí)整個(gè)服務(wù)(或微服務(wù)集合體)的通用性足以使許多獨(dú)立的應(yīng)用程序使用它們。這種共享式服務(wù)通常由第三方托管和管理,例如緩存服務(wù)器、消息隊(duì)列以及數(shù)據(jù)庫(kù)。
從應(yīng)用程序開(kāi)發(fā)者的角度來(lái)看,理解共享式服務(wù)本質(zhì)上是黑盒子是極其重要的。它不可能將你的應(yīng)用程序監(jiān)控注入到共享式服務(wù)。恰恰相反,托管服務(wù)通常會(huì)運(yùn)行它自己的監(jiān)控方案。
四個(gè)方面的解決方案
因此,抽象的跟蹤應(yīng)用程序接口將會(huì)幫助庫(kù)發(fā)出數(shù)據(jù)并且注入/抽取跨度上下文。標(biāo)準(zhǔn)的線路協(xié)議將會(huì)幫助黑盒服務(wù)相互連接,而標(biāo)準(zhǔn)的數(shù)據(jù)格式將會(huì)幫助分離的分析系統(tǒng)合并其中的數(shù)據(jù)。讓我們來(lái)看一下部分有希望解決這些問(wèn)題的方案。
跟蹤 API:OpenTracing 項(xiàng)目
如你所見(jiàn),我們需要一個(gè)跟蹤 API 來(lái)檢測(cè)應(yīng)用程序代碼。為了將這種工具擴(kuò)展到大多數(shù)進(jìn)行跨度上下文注入和提取的共享庫(kù)中,則必須以某種關(guān)鍵方式對(duì) API 進(jìn)行抽象。
OpenTracing 項(xiàng)目主要針對(duì)解決庫(kù)開(kāi)發(fā)者的問(wèn)題,OpenTracing 是一個(gè)與供應(yīng)商無(wú)關(guān)的跟蹤 API,它沒(méi)有依賴關(guān)系,并且迅速得到了許多監(jiān)控系統(tǒng)的支持。這意味著,如果庫(kù)附帶了內(nèi)置的本地 OpenTracing 工具,當(dāng)監(jiān)控系統(tǒng)在應(yīng)用程序啟動(dòng)連接時(shí),跟蹤將會(huì)自動(dòng)啟動(dòng)。
就個(gè)人而言,作為一個(gè)已經(jīng)編寫(xiě)、發(fā)布和操作開(kāi)源軟件十多年的人,在 OpenTracing 項(xiàng)目上工作并最終解決這個(gè)觀察性的難題令我十分滿意。
除了 API 之外,OpenTracing 項(xiàng)目還維護(hù)了一個(gè)不斷增長(zhǎng)的工具列表,其中一些可以在這里找到。如果你想?yún)⑴c進(jìn)來(lái),無(wú)論是通過(guò)提供一個(gè)檢測(cè)插件,對(duì)你自己的 OSS 庫(kù)進(jìn)行本地測(cè)試,或者僅僅只想問(wèn)個(gè)問(wèn)題,都可以通過(guò) Gitter 向我們打招呼。
線路協(xié)議: HTTP 報(bào)頭 trace-context
為了監(jiān)控系統(tǒng)能進(jìn)行互操作,以及減輕從一個(gè)監(jiān)控系統(tǒng)切換為另外一個(gè)時(shí)帶來(lái)的遷移問(wèn)題,需要標(biāo)準(zhǔn)的線路協(xié)議來(lái)傳播跨度上下文。
w3c 分布式跟蹤上下文社區(qū)小組在努力制定此標(biāo)準(zhǔn)。目前的重點(diǎn)是制定一系列標(biāo)準(zhǔn)的 HTTP 報(bào)頭。該規(guī)范的最新草案可以在此處找到。如果你對(duì)此小組有任何的疑問(wèn),郵件列表和Gitter 聊天室是很好的解惑地點(diǎn)。
(LCTT 譯注:本文原文發(fā)表于 2018 年 5 月,可能現(xiàn)在社區(qū)已有不同進(jìn)展)
數(shù)據(jù)協(xié)議 (還未出現(xiàn)?。。?/h4>
對(duì)于黑盒服務(wù),在無(wú)法安裝跟蹤程序或無(wú)法與程序進(jìn)行交互的情況下,需要使用數(shù)據(jù)協(xié)議從系統(tǒng)中導(dǎo)出數(shù)據(jù)。
目前這種數(shù)據(jù)格式和協(xié)議的開(kāi)發(fā)工作尚處在初級(jí)階段,并且大多在 w3c 分布式跟蹤上下文工作組的上下文中進(jìn)行工作。需要特別關(guān)注的是在標(biāo)準(zhǔn)數(shù)據(jù)模式中定義更高級(jí)別的概念,例如 RPC 調(diào)用、數(shù)據(jù)庫(kù)語(yǔ)句等。這將允許跟蹤系統(tǒng)對(duì)可用數(shù)據(jù)類型做出假設(shè)。OpenTracing 項(xiàng)目也通過(guò)定義一套標(biāo)準(zhǔn)標(biāo)簽集來(lái)解決這一事務(wù)。該計(jì)劃是為了使這兩項(xiàng)努力結(jié)果相互配合。
注意當(dāng)前有一個(gè)中間地帶。對(duì)于由應(yīng)用程序開(kāi)發(fā)者操作但不想編譯或以其他方式執(zhí)行代碼修改的“網(wǎng)絡(luò)設(shè)備”,動(dòng)態(tài)鏈接可以幫助避免這種情況。主要的例子就是服務(wù)網(wǎng)格和代理,就像 Envoy 或者 NGINX。針對(duì)這種情況,可將兼容 OpenTracing 的跟蹤器編譯為共享對(duì)象,然后在運(yùn)行時(shí)動(dòng)態(tài)鏈接到可執(zhí)行文件中。目前 C++ OpenTracing API 提供了該選項(xiàng)。而 JAVA 的 OpenTracing 跟蹤器解析也在開(kāi)發(fā)中。
這些解決方案適用于支持動(dòng)態(tài)鏈接,并由應(yīng)用程序開(kāi)發(fā)者部署的的服務(wù)。但從長(zhǎng)遠(yuǎn)來(lái)看,標(biāo)準(zhǔn)的數(shù)據(jù)協(xié)議可以更廣泛地解決該問(wèn)題。
分析系統(tǒng):從跟蹤數(shù)據(jù)中提取有見(jiàn)解的服務(wù)
最后不得不提的是,現(xiàn)在有足夠多的跟蹤監(jiān)視解決方案。可以在此處找到已知與 OpenTracing 兼容的監(jiān)控系統(tǒng)列表,但除此之外仍有更多的選擇。我更鼓勵(lì)你研究你的解決方案,同時(shí)希望你在比較解決方案時(shí)發(fā)現(xiàn)本文提供的框架能派上用場(chǎng)。除了根據(jù)監(jiān)控系統(tǒng)的操作特性對(duì)其進(jìn)行評(píng)級(jí)外(更不用提你是否喜歡 UI 和其功能),確保你考慮到了上述三個(gè)重要方面、它們對(duì)你的相對(duì)重要性以及你感興趣的跟蹤系統(tǒng)如何為它們提供解決方案。
結(jié)論
最后,每個(gè)部分的重要性在很大程度上取決于你是誰(shuí)以及正在建立什么樣的系統(tǒng)。舉個(gè)例子,開(kāi)源庫(kù)的作者對(duì) OpenTracing API 非常感興趣,而服務(wù)開(kāi)發(fā)者對(duì) trace-context 規(guī)范更感興趣。當(dāng)有人說(shuō)一部分比另一部分重要時(shí),他們的意思通常是“一部分對(duì)我來(lái)說(shuō)比另一部分重要”。
然而,事實(shí)是:分布式跟蹤已經(jīng)成為監(jiān)控現(xiàn)代系統(tǒng)所必不可少的事物。在為這些系統(tǒng)進(jìn)行構(gòu)建模塊時(shí),“盡可能解耦”的老方法仍然適用。在構(gòu)建像分布式監(jiān)控系統(tǒng)一樣的跨系統(tǒng)的系統(tǒng)時(shí),干凈地解耦組件是維持靈活性和前向兼容性地最佳方式。
感謝你的閱讀!現(xiàn)在當(dāng)你準(zhǔn)備好在你自己的應(yīng)用程序中實(shí)現(xiàn)跟蹤服務(wù)時(shí),你已有一份指南來(lái)了解他們正在談?wù)撃牟糠植糠忠约八鼈冎g如何相互協(xié)作。