隨著互聯(lián)網(wǎng)架構(gòu)的擴(kuò)張,分布式系統(tǒng)變得日趨復(fù)雜,越來(lái)越多的組件開(kāi)始走向分布式化,如微服務(wù)、消息收發(fā)、分布式數(shù)據(jù)庫(kù)、分布式緩存、分布式對(duì)象存儲(chǔ)、跨域調(diào)用,這些組件共同構(gòu)成了繁雜的分布式網(wǎng)絡(luò),那現(xiàn)在的問(wèn)題是一個(gè)請(qǐng)求經(jīng)過(guò)了這些服務(wù)后其中出現(xiàn)了一個(gè)調(diào)用失敗的問(wèn)題,只知道有異常,但具體的異常在哪個(gè)服務(wù)引起的就需要進(jìn)入每一個(gè)服務(wù)里面看日志,這樣的處理效率是非常低的。 分布式調(diào)用鏈其實(shí)就是將一次分布式請(qǐng)求還原成調(diào)用鏈路。顯式的在后端查看一次分布式請(qǐng)求的調(diào)用情況,比如各個(gè)節(jié)點(diǎn)上的耗時(shí)、請(qǐng)求具體打到了哪臺(tái)機(jī)器上、每個(gè)服務(wù)節(jié)點(diǎn)的請(qǐng)求狀態(tài)等等。 鏈路跟蹤系統(tǒng)的功能1. 故障快速定位通過(guò)調(diào)用鏈跟蹤,一次請(qǐng)求的邏輯軌跡可以用完整清晰的展示出來(lái)。開(kāi)發(fā)中可以在業(yè)務(wù)日志中添加調(diào)用鏈ID,可以通過(guò)調(diào)用鏈結(jié)合業(yè)務(wù)日志快速定位錯(cuò)誤信息。 2. 各個(gè)調(diào)用環(huán)節(jié)的性能分析 在調(diào)用鏈的各個(gè)環(huán)節(jié)分別添加調(diào)用時(shí)延,可以分析系統(tǒng)的性能瓶頸,進(jìn)行針對(duì)性的優(yōu)化。通過(guò)分析各個(gè)環(huán)節(jié)的平均時(shí)延,QPS等信息,可以找到系統(tǒng)的薄弱環(huán)節(jié),對(duì)一些模塊做調(diào)整,如數(shù)據(jù)冗余等。
3. 數(shù)據(jù)分析等調(diào)用鏈綁定業(yè)務(wù)后查看具體每條業(yè)務(wù)數(shù)據(jù)對(duì)應(yīng)的鏈路問(wèn)題,可以得到用戶的行為路徑,經(jīng)過(guò)了哪些服務(wù)器上的哪個(gè)服務(wù),匯總分析應(yīng)用在很多業(yè)務(wù)場(chǎng)景。 4. 生成服務(wù)調(diào)用拓?fù)鋱D 通過(guò)可視化分布式系統(tǒng)的模塊和他們之間的相互聯(lián)系來(lái)理解系統(tǒng)拓?fù)?。點(diǎn)擊某個(gè)節(jié)點(diǎn)會(huì)展示這個(gè)模塊的詳情,比如它當(dāng)前的狀態(tài)和請(qǐng)求數(shù)量。
分布式調(diào)用跟蹤系統(tǒng)的設(shè)計(jì)1. 分布式調(diào)用跟蹤系統(tǒng)的設(shè)計(jì)目標(biāo)低侵入性,應(yīng)用透明:作為非業(yè)務(wù)組件,應(yīng)當(dāng)盡可能少侵入或者無(wú)侵入其他業(yè)務(wù)系統(tǒng),對(duì)于使用方透明,減少開(kāi)發(fā)人員的負(fù)擔(dān) 低損耗:服務(wù)調(diào)用埋點(diǎn)本身會(huì)帶來(lái)性能損耗,這就需要調(diào)用跟蹤的低損耗,實(shí)際中還會(huì)通過(guò)配置采樣率的方式,選擇一部分請(qǐng)求去分析請(qǐng)求路徑 大范圍部署,擴(kuò)展性:作為分布式系統(tǒng)的組件之一,一個(gè)優(yōu)秀的調(diào)用跟蹤系統(tǒng)必須支持分布式部署,具備良好的可擴(kuò)展性 2. 埋點(diǎn)和生成日志 埋點(diǎn)即系統(tǒng)在當(dāng)前節(jié)點(diǎn)的上下文信息,可以分為客戶端埋點(diǎn)、服務(wù)端埋點(diǎn),以及客戶端和服務(wù)端雙向型埋點(diǎn)。埋點(diǎn)日志通常要包含以下內(nèi)容: TraceId、RPCId、調(diào)用的開(kāi)始時(shí)間,調(diào)用類(lèi)型,協(xié)議類(lèi)型,調(diào)用方ip和端口,請(qǐng)求的服務(wù)名等信息; 調(diào)用耗時(shí),調(diào)用結(jié)果,異常信息,消息報(bào)文等; 預(yù)留可擴(kuò)展字段,為下一步擴(kuò)展做準(zhǔn)備; 3. 抓取和存儲(chǔ)日志日志的采集和存儲(chǔ)有許多開(kāi)源的工具可以選擇,一般來(lái)說(shuō),會(huì)使用離線+實(shí)時(shí)的方式去存儲(chǔ)日志,主要是分布式日志采集的方式。典型的解決方案如Flume結(jié)合Kafka等MQ。 4. 分析和統(tǒng)計(jì)調(diào)用鏈數(shù)據(jù)一條調(diào)用鏈的日志散落在調(diào)用經(jīng)過(guò)的各個(gè)服務(wù)器上,首先需要按 TraceId 匯總?cè)罩?,然后按照RpcId 對(duì)調(diào)用鏈進(jìn)行順序整理。用鏈數(shù)據(jù)不要求百分之百準(zhǔn)確,可以允許中間的部分日志丟失。 5. 計(jì)算和展示匯總得到各個(gè)應(yīng)用節(jié)點(diǎn)的調(diào)用鏈日志后,可以針對(duì)性的對(duì)各個(gè)業(yè)務(wù)線進(jìn)行分析。需要對(duì)具體日志進(jìn)行整理,進(jìn)一步儲(chǔ)存在HBase或者關(guān)系型數(shù)據(jù)庫(kù)中,可以進(jìn)行可視化的查詢。 鏈路跟蹤Trace模型一次典型的分布式調(diào)用過(guò)程,如下圖所示:
Trace調(diào)用模型,主要有以下概念: Trace:一次完整的分布式調(diào)用跟蹤鏈路。 Span: 追蹤服務(wù)調(diào)基本結(jié)構(gòu),表示跨服務(wù)的一次調(diào)用; 多span形成樹(shù)形結(jié)構(gòu),組合成一次Trace追蹤記錄。 Annotation:在span中的標(biāo)注點(diǎn),記錄整個(gè)span時(shí)間段內(nèi)發(fā)生的事件。 BinaryAnnotation:可以認(rèn)為是特殊的Annotation,用戶自定義事件。 Annotation類(lèi)型:保留類(lèi)型 Cs CLIENT_SEND,客戶端發(fā)起請(qǐng)求 Cr CLIENT_RECIEVE,客戶端收到響應(yīng) Sr SERVER_RECIEVE,服務(wù)端收到請(qǐng)求 Ss SERVER_SEND,服務(wù)端發(fā)送結(jié)果 用戶自定義類(lèi)型: Event 記錄普通事件 Exception 記錄異常事件 Client && Server:對(duì)于跨服務(wù)的一次調(diào)用,請(qǐng)求發(fā)起方為client,服務(wù)提供方為server 各術(shù)語(yǔ)在一次分布式調(diào)用中,關(guān)系如下圖所示:
調(diào)用跟蹤系統(tǒng)的選型大的互聯(lián)網(wǎng)公司都有自己的分布式跟蹤系統(tǒng),比如Google的Dapper,Twitter的zipkin,淘寶的鷹眼,新浪的Watchman,京東的Hydra等,下面來(lái)簡(jiǎn)單分析。 Google的DrapperDapper是Google生產(chǎn)環(huán)境下的分布式跟蹤系統(tǒng),Dapper有三個(gè)設(shè)計(jì)目標(biāo): 低消耗:跟蹤系統(tǒng)對(duì)在線服務(wù)的影響應(yīng)該做到足夠小。 應(yīng)用級(jí)的透明:對(duì)于應(yīng)用的程序員來(lái)說(shuō),是不需要知道有跟蹤系統(tǒng)這回事的。如果一個(gè)跟蹤系統(tǒng)想生效,就必須需要依賴應(yīng)用的開(kāi)發(fā)者主動(dòng)配合,那么這個(gè)跟蹤系統(tǒng)顯然是侵入性太強(qiáng)的。 延展性:Google至少在未來(lái)幾年的服務(wù)和集群的規(guī)模,監(jiān)控系統(tǒng)都應(yīng)該能完全把控住。 處理分為3個(gè)階段: ①各個(gè)服務(wù)將span數(shù)據(jù)寫(xiě)到本機(jī)日志上; ②dapper守護(hù)進(jìn)程進(jìn)行拉取,將數(shù)據(jù)讀到dapper收集器里; ③dapper收集器將結(jié)果寫(xiě)到bigtable中,一次跟蹤被記錄為一行。 阿里-鷹眼關(guān)于淘寶的鷹眼系統(tǒng),主要資料來(lái)自于內(nèi)部分享: 鷹眼埋點(diǎn)和生成日志:
如何抓取和存儲(chǔ)日志,記錄本地文件,使用額外的后臺(tái)進(jìn)程定期(時(shí)間間隔小)收集日志。這種方式的優(yōu)勢(shì)在于對(duì)應(yīng)用的性能影響小,方便做消息堆積;但是需要在每臺(tái)業(yè)務(wù)server上都部署并管理日志收集agent,運(yùn)維量比較大。
鷹眼的實(shí)現(xiàn)小結(jié):
注意Dapper與Eagle eye都不開(kāi)源。 阿里EDAS+ARMS的立體化監(jiān)控體系通過(guò)阿里云提供的EDAS結(jié)合ARMS可以打造立體化監(jiān)控體系,其中EDAS用于應(yīng)用管控層面,用于控制鏈路和應(yīng)用;而ARMS更關(guān)注業(yè)務(wù)運(yùn)營(yíng)層面,如電商交易、車(chē)聯(lián)網(wǎng)、零售;實(shí)際上,監(jiān)控需要全方位關(guān)注業(yè)務(wù)、鏈路、應(yīng)用、系統(tǒng),通過(guò)ARMS與EDAS相互補(bǔ)全,形成了立體化監(jiān)控體系。 大眾點(diǎn)評(píng)——CAT架構(gòu)簡(jiǎn)單??梢詫?shí)現(xiàn)一個(gè)Trace系統(tǒng)的所有功能。架構(gòu)如下圖所示:
跟蹤模型Transaction是最重要的事件消息類(lèi)型,適合記錄跨越系統(tǒng)邊界的程序訪問(wèn)行為,比如遠(yuǎn)程調(diào)用,數(shù)據(jù)庫(kù)調(diào)用,也適合執(zhí)行時(shí)間較長(zhǎng)的業(yè)務(wù)邏輯監(jiān)控,記錄次數(shù)與時(shí)間開(kāi)銷(xiāo)。Transaction可嵌套。 跨服務(wù)的跟蹤功能與點(diǎn)評(píng)內(nèi)部的RPC框架集成,這部分未開(kāi)源。 客戶端接入方式對(duì)于方法調(diào)用、sql、url請(qǐng)求等粒度較小的興趣點(diǎn),需要業(yè)務(wù)人員手寫(xiě)代碼實(shí)現(xiàn)。 日志收集方式直接向日志收集器發(fā)異步請(qǐng)求(有本地內(nèi)存緩存),一臺(tái)客戶端會(huì)連向幾個(gè)服務(wù)端,當(dāng)一個(gè)服務(wù)端出問(wèn)題,數(shù)據(jù)不會(huì)丟失。 當(dāng)所有服務(wù)端都掛掉,消息會(huì)存入queue,當(dāng)queue滿了,就丟棄了,沒(méi)有做數(shù)據(jù)存儲(chǔ)本地等工作。 全量采樣,系統(tǒng)繁忙的時(shí)候?qū)π阅苡绊戄^大(可能達(dá)到10%的影響) 最后一個(gè)穩(wěn)定版本是2014年1月,之后已經(jīng)失去維護(hù)。 京東-hydra與dubbo框架集成。對(duì)于服務(wù)級(jí)別的跟蹤統(tǒng)計(jì),現(xiàn)有業(yè)務(wù)可以無(wú)縫接入。對(duì)于細(xì)粒度的興趣點(diǎn),需要業(yè)務(wù)人員手動(dòng)添加。架構(gòu)如下:
Hydra中跟蹤數(shù)據(jù)模型Trace:一次服務(wù)調(diào)用追蹤鏈路。 Span:追蹤服務(wù)調(diào)基本結(jié)構(gòu),多span形成樹(shù)形結(jié)構(gòu)組合成一次Trace追蹤記錄。 Annotation:在span中的標(biāo)注點(diǎn),記錄整個(gè)span時(shí)間段內(nèi)發(fā)生的事件。 BinaryAnnotation:屬于Annotation一種類(lèi)型和普通Annotation區(qū)別,這鍵值對(duì)形式標(biāo)注在span中發(fā)生的事件,和一些其他相關(guān)的信息。 日志收集方式與CAT類(lèi)似。支持自適應(yīng)采樣,規(guī)則粗暴簡(jiǎn)單,對(duì)于每秒鐘的請(qǐng)求次數(shù)進(jìn)行統(tǒng)計(jì),如果超過(guò)100,就按照10%的比率進(jìn)行采樣。 開(kāi)源項(xiàng)目已于2013年6月停止維護(hù)。 Twitter—OpenZipkin功能、數(shù)據(jù)跟蹤模型與hydra類(lèi)似。Zipkin本身不開(kāi)源,開(kāi)源社區(qū)的是另外一套scala實(shí)現(xiàn),依托于finagle這個(gè)RPC框架。架構(gòu)如下:
Zipkin與其他Trace系統(tǒng)的不同之處在于: Zipkin中針對(duì) HttpClient、jax-rs2、jersey/jersey2等HTTP客戶端封裝了攔截器。可以在較小的代碼侵入條件下實(shí)現(xiàn)URl請(qǐng)求的攔截、時(shí)間統(tǒng)計(jì)和日志記錄等操作。 日志收集Cat是直接將日志發(fā)往消費(fèi)集群;hydra是發(fā)給日志收集器,日志收集器推到消息隊(duì)列;Zipkin的client將統(tǒng)計(jì)日志發(fā)往消息隊(duì)列,日志收集器讀取后落地存儲(chǔ);Dapper和Eagle eye是記錄本地文件,后臺(tái)進(jìn)程定期掃描。 Trace系統(tǒng)現(xiàn)狀分析以上幾款鏈路跟蹤系統(tǒng)都各自滿足了請(qǐng)求鏈路追蹤的功能,但落實(shí)到我們自己的生產(chǎn)環(huán)境中時(shí),這些Trace系統(tǒng)存在諸多問(wèn)題:Google和alibaba的Trace系統(tǒng)不開(kāi)源,但現(xiàn)階段來(lái)說(shuō)阿里是做得最好的,如果用的是阿里的服務(wù)器,可考慮直接用阿里的追蹤系統(tǒng)以節(jié)省開(kāi)發(fā)代價(jià); 京東和點(diǎn)評(píng)的雖然開(kāi)源,但是已經(jīng)多年沒(méi)有維護(hù),項(xiàng)目依賴的jdk版本以及第三方框架過(guò)于陳舊等等,不適合用在生產(chǎn)環(huán)境中; Twitter的OpenZipkin使用scala開(kāi)發(fā),而且其實(shí)現(xiàn)基于twitter內(nèi)部的RPC框架finagle,第三方依賴比較多,接入和運(yùn)維的成本非常高。 如果不是用阿里的服務(wù),我們可以借鑒這些開(kāi)源實(shí)現(xiàn)的思想, 自行開(kāi)發(fā)Trace系統(tǒng)。那是自己從0開(kāi)始開(kāi)發(fā)還是基于開(kāi)源方案二次開(kāi)發(fā)? 這里面也要考慮到跨平臺(tái),如NET和java環(huán)境,盡量減少原系統(tǒng)的侵入性或只需要更改少量的代碼即可接入,在這里可以基于zipkin和pinpoint進(jìn)行二次開(kāi)發(fā),功能可參考阿里的系統(tǒng)。 Zipkin 和 Pinpoint 選型對(duì)比Pinpoint 與 Zipkin 都是基于 Google Dapper 的那篇論文,因此理論基礎(chǔ)大致相同。Pinpoint 與 Zipkin 有明顯的差異,主要體現(xiàn)在如下幾個(gè)方面: 1. Pinpoint 是一個(gè)完整的性能監(jiān)控解決方案:有從探針、收集器、存儲(chǔ)到 Web 界面等全套體系;而 Zipkin 只側(cè)重收集器和存儲(chǔ)服務(wù),雖然也有用戶界面,但其功能與 Pinpoint 不可同日而語(yǔ)。反而 Zipkin 提供有 Query 接口,更強(qiáng)大的用戶界面和系統(tǒng)集成能力,可以基于該接口二次開(kāi)發(fā)實(shí)現(xiàn)。 2. Zipkin 官方提供有基于 Finagle 框架(Scala 語(yǔ)言)的接口,而其他框架的接口由社區(qū)貢獻(xiàn),目前可以支持 Java、Scala、Node、Go、Python、Ruby 和 C# 等主流開(kāi)發(fā)語(yǔ)言和框架;但是 Pinpoint 目前只有官方提供的 Java Agent 探針,其他的都在請(qǐng)求社區(qū)支援中。 3. Pinpoint 提供有 Java Agent 探針,通過(guò)字節(jié)碼注入的方式實(shí)現(xiàn)調(diào)用攔截和數(shù)據(jù)收集,可以做到真正的代碼無(wú)侵入,只需要在啟動(dòng)服務(wù)器的時(shí)候添加一些參數(shù),就可以完成探針的部署;而 Zipkin 的 Java 接口實(shí)現(xiàn) Brave,只提供了基本的操作 API,如果需要與框架或者項(xiàng)目集成的話,就需要手動(dòng)添加配置文件或增加代碼。 4. Pinpoint 的后端存儲(chǔ)基于 HBase,而 Zipkin 基于 Cassandra。 接入難度因?yàn)?Brave 的注入需要依賴底層框架提供相關(guān)接口,因此并不需要對(duì)框架有一個(gè)全面的了解,只需要知道能在什么地方注入,能夠在注入的時(shí)候取得什么數(shù)據(jù)就可以了。就像上面的例子,我們根本不需要知道 MySQL 的 JDBC Driver 是如何實(shí)現(xiàn)的也可以做到攔截 SQL 的能力。但是 Pinpoint 就不然,因?yàn)?Pinpoint 幾乎可以在任何地方注入任何代碼,這需要開(kāi)發(fā)人員對(duì)所需注入的庫(kù)的代碼實(shí)現(xiàn)有非常深入的了解,通過(guò)查看其 MySQL 和 Http Client 插件的實(shí)現(xiàn)就可以洞察這一點(diǎn),當(dāng)然這也從另外一個(gè)層面說(shuō)明 Pinpoint 的能力確實(shí)可以非常強(qiáng)大,而且其默認(rèn)實(shí)現(xiàn)的很多插件已經(jīng)做到了非常細(xì)粒度的攔截。 針對(duì)底層框架沒(méi)有公開(kāi) API 的時(shí)候,其實(shí) Brave 也并不完全無(wú)計(jì)可施,我們可以采取 AOP 的方式,一樣能夠?qū)⑾嚓P(guān)攔截注入到指定的代碼中,而且顯然 AOP 的應(yīng)用要比字節(jié)碼注入簡(jiǎn)單很多。 以上這些直接關(guān)系到實(shí)現(xiàn)一個(gè)監(jiān)控的成本,在 Pinpoint 的官方技術(shù)文檔中,給出了一個(gè)參考數(shù)據(jù)。如果對(duì)一個(gè)系統(tǒng)集成的話,那么用于開(kāi)發(fā) Pinpoint 插件的成本是 100,將此插件集成入系統(tǒng)的成本是 0;但對(duì)于 Brave,插件開(kāi)發(fā)的成本只有 20,而集成成本是 10。從這一點(diǎn)上可以看出官方給出的成本參考數(shù)據(jù)是 5:1。但是官方又強(qiáng)調(diào)了,如果有 10 個(gè)系統(tǒng)需要集成的話,那么總成本就是 10 * 10 + 20 = 120,就超出了 Pinpoint 的開(kāi)發(fā)成本 100,而且需要集成的服務(wù)越多,這個(gè)差距就越大。 從短期目標(biāo)來(lái)看,Pinpoint 確實(shí)具有壓倒性的優(yōu)勢(shì):無(wú)需對(duì)項(xiàng)目代碼進(jìn)行任何改動(dòng)就可以部署探針、追蹤數(shù)據(jù)細(xì)粒化到方法調(diào)用級(jí)別、功能強(qiáng)大的用戶界面以及幾乎比較全面的 Java 框架支持。但是長(zhǎng)遠(yuǎn)來(lái)看,學(xué)習(xí) Pinpoint 的開(kāi)發(fā)接口,以及未來(lái)為不同的框架實(shí)現(xiàn)接口的成本都還是個(gè)未知數(shù)。相反,掌握 Brave 就相對(duì)容易,而且 Zipkin 的社區(qū)更加強(qiáng)大,更有可能在未來(lái)開(kāi)發(fā)出更多的接口。在最壞的情況下,我們也可以自己通過(guò) AOP 的方式添加適合于我們自己的監(jiān)控代碼,而并不需要引入太多的新技術(shù)和新概念。而且在未來(lái)業(yè)務(wù)發(fā)生變化的時(shí)候,Pinpoint 官方提供的報(bào)表是否能滿足要求也不好說(shuō),增加新的報(bào)表也會(huì)帶來(lái)不可以預(yù)測(cè)的工作難度和工作量。 最后還要考慮日志收集(直接發(fā)送、記錄到本地再上傳)、日志接收(消息隊(duì)列,直接進(jìn)入ElasticSearch)、數(shù)據(jù)清洗(Logstach、Storm、SparkStreaming)、日志存儲(chǔ)(Mysql、Hbase、ElasticSearch)、頁(yè)面展示(自研還是直接用第三方的)。
|
|
來(lái)自: xujin3 > 《特定系統(tǒng)》