隨着互聯網架構的擴張,分佈式系統變得日趨複雜,愈來愈多的組件開始走向分佈式化,如微服務、消息收發、分佈式數據庫、分佈式緩存、分佈式對象存儲、跨域調用,這些組件共同構成了繁雜的分佈式網絡,那如今的問題是一個請求通過了這些服務後其中出現了一個調用失敗的問題,只知道有異常,但具體的異常在哪一個服務引發的就須要進入每個服務裏面看日誌,這樣的處理效率是很是低的。java
分佈式調用鏈其實就是將一次分佈式請求還原成調用鏈路。顯式的在後端查看一次分佈式請求的調用狀況,好比各個節點上的耗時、請求具體打到了哪臺機器上、每一個服務節點的請求狀態等等。程序員
經過調用鏈跟蹤,一次請求的邏輯軌跡能夠用完整清晰的展現出來。開發中能夠在業務日誌中添加調用鏈ID,能夠經過調用鏈結合業務日誌快速定位錯誤信息。sql
(2)各個調用環節的性能分析數據庫
在調用鏈的各個環節分別添加調用時延,能夠分析系統的性能瓶頸,進行鍼對性的優化。經過分析各個環節的平均時延,QPS等信息,能夠找到系統的薄弱環節,對一些模塊作調整,如數據冗餘等。後端
調用鏈綁定業務後查看具體每條業務數據對應的鏈路問題,能夠獲得用戶的行爲路徑,通過了哪些服務器上的哪一個服務,彙總分析應用在不少業務場景。跨域
經過可視化分佈式系統的模塊和他們之間的相互聯繫來理解系統拓撲。點擊某個節點會展現這個模塊的詳情,好比它當前的狀態和請求數量。緩存
低侵入性,應用透明:做爲非業務組件,應當儘量少侵入或者無侵入其餘業務系統,對於使用方透明,減小開發人員的負擔服務器
低損耗:服務調用埋點自己會帶來性能損耗,這就須要調用跟蹤的低損耗,實際中還會經過配置採樣率的方式,選擇一部分請求去分析請求路徑網絡
大範圍部署,擴展性:做爲分佈式系統的組件之一,一個優秀的調用跟蹤系統必須支持分佈式部署,具有良好的可擴展性架構
埋點即系統在當前節點的上下文信息,能夠分爲客戶端埋點、服務端埋點,以及客戶端和服務端雙向型埋點。埋點日誌一般要包含如下內容:
TraceId、RPCId、調用的開始時間,調用類型,協議類型,調用方ip和端口,請求的服務名等信息;
調用耗時,調用結果,異常信息,消息報文等;
預留可擴展字段,爲下一步擴展作準備;
日誌的採集和存儲有許多開源的工具能夠選擇,通常來講,會使用離線+實時的方式去存儲日誌,主要是分佈式日誌採集的方式。典型的解決方案如Flume結合Kafka等MQ。
一條調用鏈的日誌散落在調用通過的各個服務器上,首先須要按 TraceId 彙總日誌,而後按照RpcId 對調用鏈進行順序整理。用鏈數據不要求百分之百準確,能夠容許中間的部分日誌丟失。
彙總獲得各個應用節點的調用鏈日誌後,能夠針對性的對各個業務線進行分析。須要對具體日誌進行整理,進一步儲存在HBase或者關係型數據庫中,能夠進行可視化的查詢。
一次典型的分佈式調用過程,以下圖所示:
Trace調用模型,主要有如下概念:
Trace:一次完整的分佈式調用跟蹤鏈路。
Span: 追蹤服務調基本結構,表示跨服務的一次調用; 多span造成樹形結構,組合成一次Trace追蹤記錄。
Annotation:在span中的標註點,記錄整個span時間段內發生的事件。
BinaryAnnotation:能夠認爲是特殊的Annotation,用戶自定義事件。
Annotation類型:保留類型
Cs CLIENT_SEND,客戶端發起請求
Cr CLIENT_RECIEVE,客戶端收到響應
Sr SERVER_RECIEVE,服務端收到請求
Ss SERVER_SEND,服務端發送結果
用戶自定義類型:
Event 記錄普通事件
Exception 記錄異常事件
Client && Server:對於跨服務的一次調用,請求發起方爲client,服務提供方爲server
各術語在一次分佈式調用中,關係以下圖所示:
大的互聯網公司都有本身的分佈式跟蹤系統,好比Google的Dapper,Twitter的zipkin,淘寶的鷹眼,新浪的Watchman,京東的Hydra等,下面來簡單分析。
Dapper是Google生產環境下的分佈式跟蹤系統,Dapper有三個設計目標:
低消耗:跟蹤系統對在線服務的影響應該作到足夠小。
應用級的透明:對於應用的程序員來講,是不須要知道有跟蹤系統這回事的。若是一個跟蹤系統想生效,就必須須要依賴應用的開發者主動配合,那麼這個跟蹤系統顯然是侵入性太強的。
延展性:Google至少在將來幾年的服務和集羣的規模,監控系統都應該能徹底把控住。
處理分爲3個階段:
①各個服務將span數據寫到本機日誌上;
②dapper守護進程進行拉取,將數據讀到dapper收集器裏;
③dapper收集器將結果寫到bigtable中,一次跟蹤被記錄爲一行。
關於淘寶的鷹眼系統,主要資料來自於內部分享:
鷹眼埋點和生成日誌:
如何抓取和存儲日誌,記錄本地文件,使用額外的後臺進程按期(時間間隔小)收集日誌。這種方式的優點在於對應用的性能影響小,方便作消息堆積;可是須要在每臺業務server上都部署並管理日誌收集agent,運維量比較大。
鷹眼的實現小結:
注意Dapper與Eagle eye都不開源。
經過阿里雲提供的EDAS結合ARMS能夠打造立體化監控體系,其中EDAS用於應用管控層面,用於控制鏈路和應用;而ARMS更關注業務運營層面,如電商交易、車聯網、零售;實際上,監控須要全方位關注業務、鏈路、應用、系統,經過ARMS與EDAS相互補全,造成了立體化監控體系。
架構簡單。能夠實現一個Trace系統的全部功能。架構以下圖所示:
Transaction是最重要的事件消息類型,適合記錄跨越系統邊界的程序訪問行爲,好比遠程調用,數據庫調用,也適合執行時間較長的業務邏輯監控,記錄次數與時間開銷。Transaction可嵌套。
跨服務的跟蹤功能與點評內部的RPC框架集成,這部分未開源。
對於方法調用、sql、url請求等粒度較小的興趣點,須要業務人員手寫代碼實現。
直接向日志收集器發異步請求(有本地內存緩存),一臺客戶端會連向幾個服務端,當一個服務端出問題,數據不會丟失。
當全部服務端都掛掉,消息會存入queue,當queue滿了,就丟棄了,沒有作數據存儲本地等工做。
全量採樣,系統繁忙的時候對性能影響較大(可能達到10%的影響)
最後一個穩定版本是2014年1月,以後已經失去維護。
與dubbo框架集成。對於服務級別的跟蹤統計,現有業務能夠無縫接入。對於細粒度的興趣點,須要業務人員手動添加。架構以下:
Trace: 一次服務調用追蹤鏈路。
Span: 追蹤服務調基本結構,多span造成樹形結構組合成一次Trace追蹤記錄。
Annotation: 在span中的標註點,記錄整個span時間段內發生的事件。
BinaryAnnotation: 屬於Annotation一種類型和普通Annotation區別,這鍵值對形式標註在span中發生的事件,和一些其餘相關的信息。
與CAT相似。支持自適應採樣,規則粗暴簡單,對於每秒鐘的請求次數進行統計,若是超過100,就按照10%的比率進行採樣。
開源項目已於2013年6月中止維護。
功能、數據跟蹤模型與hydra相似。Zipkin自己不開源,開源社區的是另一套scala實現,依託於finagle這個RPC框架。架構以下:
Zipkin與其餘Trace系統的不一樣之處在於:
Zipkin中針對 HttpClient、jax-rs二、jersey/jersey2等HTTP客戶端封裝了攔截器。能夠在較小的代碼侵入條件下實現URl請求的攔截、時間統計和日誌記錄等操做。
Cat是直接將日誌發往消費集羣;hydra是發給日誌收集器,日誌收集器推到消息隊列;Zipkin的client將統計日誌發往消息隊列,日誌收集器讀取後落地存儲;Dapper和Eagle eye是記錄本地文件,後臺進程按期掃描。
以上幾款鏈路跟蹤系統都各自知足了請求鏈路追蹤的功能,但落實到咱們本身的生產環境中時,這些Trace系統存在諸多問題:Google和alibaba的Trace系統不開源,但現階段來講阿里是作得最好的,若是用的是阿里的服務器,可考慮直接用阿里的追蹤系統以節省開發代價;
京東和點評的雖然開源,可是已經多年沒有維護,項目依賴的jdk版本以及第三方框架過於陳舊等等,不適合用在生產環境中;
Twitter的OpenZipkin使用scala開發,並且其實現基於twitter內部的RPC框架finagle,第三方依賴比較多,接入和運維的成本很是高。
若是不是用阿里的服務,咱們能夠借鑑這些開源實現的思想, 自行開發Trace系統。那是本身從0開始開發仍是基於開源方案二次開發? 這裏面也要考慮到跨平臺,如NET和java環境,儘可能減小原系統的侵入性或只須要更改少許的代碼便可接入,在這裏能夠基於zipkin和pinpoint進行二次開發,功能可參考阿里的系統。
Pinpoint 與 Zipkin 都是基於 Google Dapper 的那篇論文,所以理論基礎大體相同。Pinpoint 與 Zipkin 有明顯的差別,主要體如今以下幾個方面:
由於 Brave 的注入須要依賴底層框架提供相關接口,所以並不須要對框架有一個全面的瞭解,只須要知道能在什麼地方注入,可以在注入的時候取得什麼數據就能夠了。就像上面的例子,咱們根本不須要知道 MySQL 的 JDBC Driver 是如何實現的也能夠作到攔截 SQL 的能力。可是 Pinpoint 就否則,由於 Pinpoint 幾乎能夠在任何地方注入任何代碼,這須要開發人員對所需注入的庫的代碼實現有很是深刻的瞭解,經過查看其 MySQL 和 Http Client 插件的實現就能夠洞察這一點,固然這也從另一個層面說明 Pinpoint 的能力確實能夠很是強大,並且其默認實現的不少插件已經作到了很是細粒度的攔截。
針對底層框架沒有公開 API 的時候,其實 Brave 也並不徹底機關用盡,咱們能夠採起 AOP 的方式,同樣可以將相關攔截注入到指定的代碼中,並且顯然 AOP 的應用要比字節碼注入簡單不少。
以上這些直接關係到實現一個監控的成本,在 Pinpoint 的官方技術文檔中,給出了一個參考數據。若是對一個系統集成的話,那麼用於開發 Pinpoint 插件的成本是 100,將此插件集成入系統的成本是 0;但對於 Brave,插件開發的成本只有 20,而集成成本是 10。從這一點上能夠看出官方給出的成本參考數據是 5:1。可是官方又強調了,若是有 10 個系統須要集成的話,那麼總成本就是 10 * 10 + 20 = 120,就超出了 Pinpoint 的開發成本 100,並且須要集成的服務越多,這個差距就越大。
從短時間目標來看,Pinpoint 確實具備壓倒性的優點:無需對項目代碼進行任何改動就能夠部署探針、追蹤數據細粒化到方法調用級別、功能強大的用戶界面以及幾乎比較全面的 Java 框架支持。可是長遠來看,學習 Pinpoint 的開發接口,以及將來爲不一樣的框架實現接口的成本都仍是個未知數。相反,掌握 Brave 就相對容易,並且 Zipkin 的社區更增強大,更有可能在將來開發出更多的接口。在最壞的狀況下,咱們也能夠本身經過 AOP 的方式添加適合於咱們本身的監控代碼,而並不須要引入太多的新技術和新概念。並且在將來業務發生變化的時候,Pinpoint 官方提供的報表是否能知足要求也很差說,增長新的報表也會帶來不能夠預測的工做難度和工做量。
最後還要考慮日誌收集(直接發送、記錄到本地再上傳)、日誌接收(消息隊列,直接進入ElasticSearch)、數據清洗(Logstach、Storm、SparkStreaming)、日誌存儲(Mysql、Hbase、ElasticSearch)、頁面展現(自研仍是直接用第三方的)。