1. 程式人生 > 實用技巧 >全鏈路監控的方案概述與比較

全鏈路監控的方案概述與比較

全鏈路監控的方案概述與比較

目錄

問題背景

隨著微服務架構的流行,服務按照不同的維度進行拆分,一次請求往往需要涉及到多個服務。網際網路應用構建在不同的軟體模組集上,這些軟體模組,有可能是由不同的團隊開發、可能使用不同的程式語言來實現、有可能布在了幾千臺伺服器,橫跨多個不同的資料中心。因此,就需要一些可以幫助理解系統行為、用於分析效能問題的工具,以便發生故障的時候,能夠快速定位和解決問題。
全鏈路監控元件就在這樣的問題背景下產生了。最出名的是谷歌公開的論文提到的 Google Dapper想要在這個上下文中理解分散式系統的行為,就需要監控那些橫跨了不同的應用、不同的伺服器之間的關聯動作

所以,在複雜的微服務架構系統中,幾乎每一個前端請求都會形成一個複雜的分散式服務呼叫鏈路。一個請求完整呼叫鏈可能如下圖所示:

那麼在業務規模不斷增大、服務不斷增多以及頻繁變更的情況下,面對複雜的呼叫鏈路就帶來一系列問題:

  1. 如何快速發現問題?
  2. 如何判斷故障影響範圍?
  3. 如何梳理服務依賴以及依賴的合理性?
  4. 如何分析鏈路效能問題以及實時容量規劃?

同時我們會關注在請求處理期間各個呼叫的各項效能指標,比如:吞吐量(TPS)、響應時間及錯誤記錄等。

  1. 吞吐量,根據拓撲可計算相應元件、平臺、物理裝置的實時吞吐量。
  2. 響應時間,包括整體呼叫的響應時間和各個服務的響應時間等。
  3. 錯誤記錄,根據服務返回統計單位時間異常次數。

全鏈路效能監控 從整體維度到區域性維度展示各項指標,將跨應用的所有呼叫鏈效能資訊集中展現,可方便度量整體和區域性效能,並且方便找到故障產生的源頭,生產上可極大縮短故障排除時間。

有了全鏈路監控工具,我們能夠達到

  1. 請求鏈路追蹤,故障快速定位:可以通過呼叫鏈結合業務日誌快速定位錯誤資訊。
  2. 視覺化: 各個階段耗時,進行效能分析。
  3. 依賴優化:各個呼叫環節的可用性、梳理服務依賴關係以及優化。
  4. 資料分析,優化鏈路:可以得到使用者的行為路徑,彙總分析應用在很多業務場景。

目標要求

如上所述,那麼我們選擇全鏈路監控元件有哪些目標要求呢?Google Dapper中也提到了,總結如下:

  1. 探針的效能消耗

APM元件服務的影響應該做到足夠小。服務呼叫埋點本身會帶來效能損耗,這就需要呼叫跟蹤的低損耗,實際中還會通過配置取樣率的方式,選擇一部分請求去分析請求路徑。在一些高度優化過的服務,即使一點點損耗也會很容易察覺到,而且有可能迫使線上服務的部署團隊不得不將跟蹤系統關停。

  1. 程式碼的侵入性

即也作為業務元件,應當儘可能少入侵或者無入侵其他業務系統,對於使用方透明,減少開發人員的負擔

對於應用的程式設計師來說,是不需要知道有跟蹤系統這回事的。如果一個跟蹤系統想生效,就必須需要依賴應用的開發者主動配合,那麼這個跟蹤系統也太脆弱了,往往由於跟蹤系統在應用中植入程式碼的bug或疏忽導致應用出問題,這樣才是無法滿足對跟蹤系統“無所不在的部署”這個需求。

  1. 可擴充套件性

一個優秀的呼叫跟蹤系統必須支援分散式部署,具備良好的可擴充套件性。能夠支援的元件越多當然越好。或者提供便捷的外掛開發API,對於一些沒有監控到的元件,應用開發者也可以自行擴充套件。

  1. 資料的分析

資料的分析要快 ,分析的維度儘可能多。跟蹤系統能提供足夠快的資訊反饋,就可以對生產環境下的異常狀況做出快速反應。分析的全面,能夠避免二次開發

功能模組

一般的全鏈路監控系統,大致可分為四大功能模組:

  1. 埋點與生成日誌

埋點即系統在當前節點的上下文資訊,可以分為 客戶端埋點、服務端埋點,以及客戶端和服務端雙向型埋點。埋點日誌通常要包含以下內容traceId、spanId、呼叫的開始時間,協議型別、呼叫方ip和埠,請求的服務名、呼叫耗時,呼叫結果,異常資訊等,同時預留可擴充套件欄位,為下一步擴充套件做準備;

不能造成效能負擔:一個價值未被驗證,卻會影響效能的東西,是很難在公司推廣的!

因為要寫log,業務QPS越高,效能影響越重。通過取樣和非同步log解決

  1. 收集和儲存日誌

主要支援分散式日誌採集的方案,同時增加MQ作為緩衝;

  1. 每個機器上有一個 deamon 做日誌收集,業務程序把自己的Trace發到daemon,daemon把收集Trace往上一級傳送;
  2. 多級的collector,類似pub/sub架構,可以負載均衡;
  3. 對聚合的資料進行 實時分析和離線儲存
  4. 離線分析 需要將同一條呼叫鏈的日誌彙總在一起
  1. 分析和統計呼叫鏈路資料,以及時效性

呼叫鏈跟蹤分析:把同一TraceID的Span收集起來,按時間排序就是timeline。把ParentID串起來就是呼叫棧

拋異常或者超時,在日誌裡列印TraceID。利用TraceID查詢呼叫鏈情況,定位問題。

依賴度量

  1. 強依賴:呼叫失敗會直接中斷主流程
  2. 高度依賴:一次鏈路中呼叫某個依賴的機率高
  3. 頻繁依賴:一次鏈路呼叫同一個依賴的次數多

離線分析:按TraceID彙總,通過Span的ID和ParentID還原呼叫關係,分析鏈路形態。

實時分析:對單條日誌直接分析,不做彙總,重組。得到當前QPS,延遲。

  1. 展現以及決策支援

Google Dapper

Span

基本工作單元,一次鏈路呼叫(可以是RPC,DB等沒有特定的限制)建立一個span,通過一個64位ID標識它,uuid較為方便,span中還有其他的資料,例如描述資訊,時間戳,key-value對的(Annotation)tag資訊,parent_id等,其中parent-id可以表示span呼叫鏈路來源。

上圖說明了span在一次大的跟蹤過程中是什麼樣的。Dapper記錄了span名稱,以及每個span的ID和父ID,以重建在一次追蹤過程中不同span之間的關係。如果一個span沒有父ID被稱為root span。所有span都掛在一個特定的跟蹤上,也共用一個跟蹤id

Span資料結構:

type Span struct {
    TraceID    int64 // 用於標示一次完整的請求id
    Name       string
    ID         int64 // 當前這次呼叫span_id
    ParentID   int64 // 上層服務的呼叫span_id  最上層服務parent_id為null
    Annotation []Annotation // 用於標記的時間戳
    Debug      bool
}

Trace

類似於 樹結構的Span集合,表示一次完整的跟蹤,從請求到伺服器開始,伺服器返回response結束,跟蹤每次rpc呼叫的耗時,存在唯一標識trace_id。比如:你執行的分散式大資料儲存一次Trace就由你的一次請求組成。

每種顏色的note標註了一個span,一條鏈路通過TraceId唯一標識,Span標識發起的請求資訊。樹節點是整個架構的基本單元,而每一個節點又是對span的引用。節點之間的連線表示的span和它的父span直接的關係。雖然span在日誌檔案中只是簡單的代表span的開始和結束時間,他們在整個樹形結構中卻是相對獨立的。

Annotation

註解,用來記錄請求特定事件相關資訊(例如時間),一個span中會有多個annotation註解描述。通常包含四個註解資訊:

(1) cs:Client Start,表示客戶端發起請求

(2) sr:Server Receive,表示服務端收到請求

(3) ss:Server Send,表示服務端完成處理,並將結果傳送給客戶端

(4) cr:Client Received,表示客戶端獲取到服務端返回資訊

Annotation資料結構

type Annotation struct {
    Timestamp int64
    Value     string
    Host      Endpoint
    Duration  int32
}

呼叫示例

請求呼叫示例

  1. 當用戶發起一個請求時,首先到達前端A服務,然後分別對B服務和C服務進行RPC呼叫;
  2. B服務處理完給A做出響應,但是C服務還需要和後端的D服務和E服務互動之後再返還給A服務,最後由A服務來響應使用者的請求;

呼叫過程追蹤

  1. 請求到來生成一個全域性TraceID,通過TraceID可以串聯起整個呼叫鏈,一個TraceID代表一次請求。
  2. 除了TraceID外,還需要SpanID用於記錄呼叫父子關係。每個服務會記錄下parent id和span id,通過他們可以組織一次完整呼叫鏈的父子關係
  3. 一個沒有parent id的span成為root span,可以看成呼叫鏈入口。
  4. 所有這些ID可用全域性唯一的64位整數表示;
  5. 整個呼叫過程中每個請求都要透傳TraceID和SpanID
  6. 每個服務將該次請求附帶的TraceID和附帶的SpanID作為parent id記錄下,並且將自己生成的SpanID也記錄下。
  7. 要檢視某次完整的呼叫則 只要根據TraceID查出所有呼叫記錄,然後通過parent id和span id組織起整個呼叫父子關係

呼叫鏈核心工作

  1. 呼叫鏈資料生成,對整個呼叫過程的所有應用進行埋點並輸出日誌。
  2. 呼叫鏈資料採集,對各個應用中的日誌資料進行採集。
  3. 呼叫鏈資料儲存及查詢,對採集到的資料進行儲存,由於日誌資料量一般都很大,不僅要能對其儲存,還需要能提供快速查詢。
  4. 指標運算、儲存及查詢,對採集到的日誌資料進行各種指標運算,將運算結果儲存起來。
  5. 告警功能,提供各種閥值警告功能。

整體部署架構

  1. 通過AGENT生成呼叫鏈日誌。
  2. 通過logstash採集日誌到kafka。
  3. kafka負責提供資料給下游消費。
  4. storm計算匯聚指標結果並落到es。
  5. storm抽取trace資料並落到es,這是為了提供比較複雜的查詢。比如通過時間維度查詢呼叫鏈,可以很快查詢出所有符合的traceID,根據這些traceID再去 Hbase 查資料就快了
  6. logstash將kafka原始資料拉取到hbase中。hbase的rowkey為traceID,根據traceID查詢是很快的

AGENT無侵入部署

通過AGENT代理無侵入式部署,將效能測量與業務邏輯完全分離,可以測量任意類的任意方法的執行時間,這種方式大大提高了採集效率,並且減少運維成本。根據服務跨度主要分為兩大類AGENT

  1. 服務內AGENT,這種方式是通過 Java 的agent機制,對服務內部的方法呼叫層次資訊進行資料收集,如方法呼叫耗時、入參、出參等資訊。

  2. 跨服務AGENT,這種情況需要對主流RPC框架以外掛形式提供無縫支援。並通過提供標準資料規範以適應自定義RPC框架:

(1)Dubbo支援;

(2)Rest支援;

(3)自定義RPC支援;

呼叫鏈監控好處

  1. 準確掌握生產一線應用部署情況
  2. 從呼叫鏈全流程效能角度,識別對關鍵呼叫鏈,並進行優化
  3. 提供可追溯的效能資料,量化 IT 運維部門業務價值;
  4. 快速定位程式碼效能問題,協助開發人員持續性的優化程式碼;
  5. 協助開發人員進行白盒測試,縮短系統上線穩定期;

常見開源產品

cat, zipkin, pinpoint , skywalking

cat

由大眾點評開源,基於Java開發的實時應用監控平臺,包括實時應用監控,業務監控 。 整合方案是通過

程式碼埋點的方式來實現監控,比如: 攔截器,註解,過濾器等。 對程式碼的侵入性很大,整合成本較高。

風險較大。

支援技術棧:

  • dubbo
  • spring mvc ,spring aop ,springmvc-url
  • spring boot
  • mybatis
  • log4j , logback
  • playframework
  • http請求

zipkin

由Twitter團隊開源, Zipkin是一個分散式的跟蹤系統。它有助於收集資料需要解決潛在的問題在市微服架構的時機。它管理資料的收集和查詢 .

該產品結合spring-cloud-sleuth使用較為簡單, 整合很方便。 但是功能較簡單。

支援技術棧:

  • spring cloud

    以上是結合spring-cloud-sleuth支援的技術棧
    

pinpoint

由韓國團隊naver團隊開源,針對大規模分散式系統用鏈路監控,使用java寫的工具。靈感來自短小精悍,幫助分析系統的總

體結構和內部元件如何被呼叫在分散式應用提供了一個很好的解決方案。

使用java探針位元組碼增加技術,實現對整個應用的監控 。 對應用零侵入

支援技術棧:

  • Tomcat 6+, Jetty 8/9, JBoss 6, Resin 4, Websphere 6+, Vertx 3.3+
  • Spring, Spring Boot (Embedded Tomcat, Jetty)
  • HTTP Client 3.x/4.x, HttpConnector, GoogleHttpClient, OkHttpClient, NingAsyncHttpClient
  • Thrift, Dubbo
  • mysql, oracle, mssql, cubrid,PostgreSQL, maria
  • arcus, memcached, redis, cassandra
  • MyBatis
  • DBCP, DBCP2, HIKARICP
  • gson, Jackson, Json Lib
  • log4j, Logback

skywalking

2015年由個人吳晟(華為開發者)開源 , 2017年加入Apache孵化器。

針對分散式系統的應用效能監控系統,特別針對微服務、cloud native和容器化(Docker, Kubernetes, Mesos)架構, 其核心是個分散式追蹤系統。

使用java探針位元組碼增加技術,實現對整個應用的監控 。 對應用零侵入

支援技術棧

  • Tomcat7+ , resin3+, jetty
  • spring boot ,spring mvc
  • strtuts2
  • spring RestTemplete ,spring-cloud-feign
  • okhttp , httpClient
  • msyql ,oracle , H2 , sharding-jdbc,PostgreSQL
  • dubbo,dubbox ,motan, gRpc ,
  • rocketMq , kafla
  • redis, mongoDB,memcached ,
  • elastic-job , Netflix Eureka , Hystric

方案比較

市面上的全鏈路監控理論模型大多都是借鑑Google Dapper論文,本文重點關注以下三種APM元件:

  1. Zipkin:由Twitter公司開源,開放原始碼分散式的跟蹤系統,用於收集服務的定時資料,以解決微服務架構中的延遲問題,包括:資料的收集、儲存、查詢和展現。
  2. Pinpoint:一款對Java編寫的大規模分散式系統的APM工具,由韓國人開源的分散式跟蹤元件。
  3. Skywalking:國產的優秀APM元件,是一個對JAVA分散式應用程式叢集的業務執行情況進行追蹤、告警和分析的系統。

以上三種全鏈路監控方案需要對比的項提煉出來

  1. 探針的效能

主要是agent對服務的吞吐量、CPU和記憶體的影響。微服務的規模和動態性使得資料收集的成本大幅度提高。

  1. collector的可擴充套件性

能夠水平擴充套件以便支援大規模伺服器叢集。

  1. 全面的呼叫鏈路資料分析

提供程式碼級別的可見性以便輕鬆定位失敗點和瓶頸。

  1. 對於開發透明,容易開關

新增新功能而無需修改程式碼,容易啟用或者禁用。

  1. 完整的呼叫鏈應用拓撲

自動檢測應用拓撲,幫助你搞清楚應用的架構

探針的效能

比較關注探針的效能,畢竟APM定位還是工具,如果啟用了鏈路監控組建後,直接導致吞吐量降低過半,那也是不能接受的。對skywalking、zipkin、pinpoint進行了壓測,並與基線(未使用探針)的情況進行了對比。
選用了一個常見的基於Spring的應用程式,他包含Spring Boot, Spring MVC,redis客戶端,mysql。 監控這個應用程式,每個trace,探針會抓取5個span(1 Tomcat, 1 SpringMVC, 2 Jedis, 1 Mysql)。這邊基本和 skywalkingtest 的測試應用差不多。
模擬了三種併發使用者:500,750,1000。使用jmeter測試,每個執行緒傳送30個請求,設定思考時間為10ms。使用的取樣率為1,即100%,這邊與生產可能有差別。pinpoint預設的取樣率為20,即50%,通過設定agent的配置檔案改為100%。zipkin預設也是1。組合起來,一共有12種。下面看下彙總表:

從上表可以看出,在三種鏈路監控元件中,skywalking的探針對吞吐量的影響最小,zipkin的吞吐量居中。pinpoint的探針對吞吐量的影響較為明顯,在500併發使用者時,測試服務的吞吐量從1385降低到774,影響很大。然後再看下CPU和memory的影響,在內部伺服器進行的壓測,對CPU和memory的影響都差不多在10%之內。

collector的可擴充套件性

collector的可擴充套件性,使得能夠水平擴充套件以便支援大規模伺服器叢集。

  1. zipkin

開發zipkin-Server(其實就是提供的開箱即用包),zipkin-agent與zipkin-Server通過http或者mq進行通訊,http通訊會對正常的訪問造成影響,所以還是推薦基於mq非同步方式通訊,zipkin-Server通過訂閱具體的topic進行消費。這個當然是可以擴充套件的,多個zipkin-Server例項進行非同步消費mq中的監控資訊

  1. skywalking

skywalking的collector支援兩種部署方式:單機和叢集模式。collector與agent之間的通訊使用了gRPC

  1. pinpoint

同樣,pinpoint也是支援叢集和單機部署的。pinpoint agent通過thrift通訊框架,傳送鏈路資訊到collector

全面的呼叫鏈路資料分析

全面的呼叫鏈路資料分析,提供程式碼級別的可見性以便輕鬆定位失敗點和瓶頸。

  1. zipkin

zipkin的鏈路監控粒度相對沒有那麼細,從上圖可以看到呼叫鏈中具體到介面級別,再進一步的呼叫資訊並未涉及。

  1. skywalking

skywalking 還支援20+的中介軟體、框架、類庫,比如:主流的dubbo、Okhttp,還有DB和訊息中介軟體。上圖skywalking鏈路呼叫分析擷取的比較簡單,閘道器呼叫user服務,由於支援眾多的中介軟體,所以skywalking鏈路呼叫分析比zipkin完備些

  1. pinpoint

pinpoint應該是這三種APM元件中,資料分析最為完備的元件。提供程式碼級別的可見性以便輕鬆定位失敗點和瓶頸,上圖可以看到對於執行的sql語句,都進行了記錄。還可以配置報警規則等,設定每個應用對應的負責人,根據配置的規則報警,支援的中介軟體和框架也比較完備。

對於開發透明,容易開關

對於開發透明,容易開關,新增新功能而無需修改程式碼,容易啟用或者禁用。我們期望功能可以不修改程式碼就工作並希望得到程式碼級別的可見性。

對於這一點,Zipkin 使用修改過的類庫和它自己的容器(Finagle)來提供分散式事務跟蹤的功能。但是,它要求在需要時修改程式碼。skywalking和pinpoint都是基於位元組碼增強的方式,開發人員不需要修改程式碼,並且可以收集到更多精確的資料因為有位元組碼中的更多資訊

完整的呼叫鏈應用拓撲

自動檢測應用拓撲,幫助你搞清楚應用的架構。

上面三幅圖,分別展示了APM元件各自的呼叫拓撲,都能實現完整的呼叫鏈應用拓撲。相對來說,pinpoint介面顯示的更加豐富,具體到呼叫的DB名,zipkin的拓撲侷限於服務於服務之間

Pinpoint與Zipkin細化比較

Pinpoint與Zipkin差異性

  1. Pinpoint 是一個完整的效能監控解決方案:有從探針、收集器、儲存到 Web 介面等全套體系;而 Zipkin 只側重收集器和儲存服務,雖然也有使用者介面,但其功能與 Pinpoint 不可同日而語。反而 Zipkin 提供有 Query 介面,更強大的使用者介面和系統整合能力,可以基於該介面二次開發實現。
  2. Zipkin 官方提供有基於 Finagle 框架(Scala 語言)的介面,而其他框架的介面由社群貢獻,目前可以支援 Java、Scala、Node、Go、Python、Ruby 和 C# 等主流開發語言和框架;但是 Pinpoint 目前只有官方提供的 Java Agent 探針,其他的都在請求社群支援中(請參見#1759和#1760)。
  3. Pinpoint 提供有 Java Agent 探針,通過位元組碼注入的方式實現呼叫攔截和資料收集,可以做到真正的程式碼無侵入,只需要在啟動伺服器的時候新增一些引數,就可以完成探針的部署;而 Zipkin 的 Java 介面實現 Brave,只提供了基本的操作 API,如果需要與框架或者專案整合的話,就需要手動新增配置檔案或增加程式碼
  4. Pinpoint 的後端儲存基於 HBase,而 Zipkin 基於 Cassandra

Pinpoint與Zipkin相似性

Pinpoint 與 Zipkin 都是基於 Google Dapper 的那篇論文,因此理論基礎大致相同。兩者都是將服務呼叫拆分成若干有級聯關係的 Span,通過 SpanId 和 ParentSpanId 來進行呼叫關係的級聯;最後再將整個呼叫鏈流經的所有的 Span 匯聚成一個 Trace,報告給服務端的 collector 進行收集和儲存

即便在這一點上,Pinpoint 所採用的概念也不完全與那篇論文一致。比如他採用 TransactionId 來取代 TraceId,而真正的 TraceId 是一個結構,裡面包含了 TransactionId, SpanId 和 ParentSpanId。而且 Pinpoint 在 Span 下面又增加了一個 SpanEvent 結構,用來記錄一個 Span 內部的呼叫細節(比如具體的方法呼叫等等),因此 Pinpoint 預設會比 Zipkin 記錄更多的跟蹤資料。但是理論上並沒有限定 Span 的粒度大小,所以一個服務呼叫可以是一個 Span,那麼每個服務中的方法呼叫也可以是個 Span,這樣的話,其實 Brave 也可以跟蹤到方法呼叫級別,只是具體實現並沒有這樣做而已

位元組碼注入 vs API 呼叫

Pinpoint 實現了基於位元組碼注入的 Java Agent 探針,而 Zipkin 的 Brave 框架僅僅提供了應用層面的 API,但是細想問題遠不那麼簡單。位元組碼注入是一種簡單粗暴的解決方案,理論上來說無論任何方法呼叫,都可以通過注入程式碼的方式實現攔截,也就是說沒有實現不了的,只有不會實現的。但 Brave 則不同,其提供的應用層面的 API 還需要框架底層驅動的支援,才能實現攔截。比如,MySQL 的 JDBC 驅動,就提供有注入 interceptor 的方法,因此只需要實現 StatementInterceptor 介面,並在 Connection String 中進行配置,就可以很簡單的實現相關攔截;而與此相對的,低版本的 MongoDB 的驅動或者是 Spring Data MongoDB 的實現就沒有如此介面,想要實現攔截查詢語句的功能,就比較困難。

因此在這一點上,Brave 是硬傷,無論使用位元組碼注入多麼困難,但至少也是可以實現的,但是 Brave 卻有無從下手的可能,而且是否可以注入,能夠多大程度上注入,更多的取決於框架的 API 而不是自身的能力。

難度及成本

經過簡單閱讀 Pinpoint 和 Brave 外掛的程式碼,可以發現兩者的實現難度有天壤之別。在都沒有任何開發文件支撐的前提下,Brave 比 Pinpoint 更容易上手。Brave 的程式碼量很少,核心功能都集中在 brave-core 這個模組下,一箇中等水平的開發人員,可以在一天之內讀懂其內容,並且能對 API 的結構有非常清晰的認識。

Pinpoint 的程式碼封裝也是非常好的,尤其是針對位元組碼注入的上層 API 的封裝非常出色,但是這依然要求閱讀人員對位元組碼注入多少有一些瞭解,雖然其用於注入程式碼的核心 API 並不多,但要想了解透徹,恐怕還得深入 Agent 的相關程式碼,比如很難一目瞭然的理解 addInterceptor 和 addScopedInterceptor 的區別,而這兩個方法就是位於 Agent 的有關型別中。

因為 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 完全處於劣勢,從社群所開發出來的整合介面就可見一斑。

Pinpoint 的資料介面缺乏文件,而且也不太標準(參考論壇討論帖),需要閱讀很多程式碼才可能實現一個自己的探針(比如 Node 的或者 PHP 的)。而且團隊為了效能考慮使用了 Thrift 作為資料傳輸協議標準,比起 HTTP 和 JSON 而言難度增加了不少。

社群支援

這一點也不必多說,Zipkin 由 Twitter 開發,可以算得上是明星團隊,而 Naver 的團隊只是一個默默無聞的小團隊(從#1759的討論中可以看出)。雖然說這個專案在短期內不太可能消失或停止更新,但畢竟不如前者用起來更加放心。而且沒有更多社群開發出來的外掛,讓 Pinpoint 只依靠團隊自身的力量完成諸多框架的整合實屬困難,而且他們目前的工作重點依然是在提升效能和穩定性上。

其他

Pinpoint 在實現之初就考慮到了效能問題,www.naver.com 網站的後端某些服務每天要處理超過 200 億次的請求,因此他們會選擇 Thrift 的二進位制變長編碼格式、而且使用 UDP 作為傳輸鏈路,同時在傳遞常量的時候也儘量使用資料參考字典,傳遞一個數字而不是直接傳遞字串等等。這些優化也增加了系統的複雜度:包括使用 Thrift 介面的難度、UDP 資料傳輸的問題、以及資料常量字典的註冊問題等等。

相比之下,Zipkin 使用熟悉的 Restful 介面加 JSON,幾乎沒有任何學習成本和整合難度,只要知道資料傳輸結構,就可以輕易的為一個新的框架開發出相應的介面。

另外 Pinpoint 缺乏針對請求的取樣能力,顯然在大流量的生產環境下,不太可能將所有的請求全部記錄,這就要求對請求進行取樣,以決定什麼樣的請求是我需要記錄的。Pinpoint 和 Brave 都支援取樣百分比,也就是百分之多少的請求會被記錄下來。但是,除此之外 Brave 還提供了 Sampler 介面,可以自定義取樣策略,尤其是當進行 A/B 測試的時候,這樣的功能就非常有意義了。

總結

從短期目標來看,Pinpoint 確實具有壓倒性的優勢:無需對專案程式碼進行任何改動就可以部署探針、追蹤資料細粒化到方法呼叫級別、功能強大的使用者介面以及幾乎比較全面的 Java 框架支援。但是長遠來看,學習 Pinpoint 的開發介面,以及未來為不同的框架實現介面的成本都還是個未知數。相反,掌握 Brave 就相對容易,而且 Zipkin 的社群更加強大,更有可能在未來開發出更多的介面。在最壞的情況下,我們也可以自己通過 AOP 的方式新增適合於我們自己的監控程式碼,而並不需要引入太多的新技術和新概念。而且在未來業務發生變化的時候,Pinpoint 官方提供的報表是否能滿足要求也不好說,增加新的報表也會帶來不可以預測的工作難度和工作量。

Tracing和Monitor區別

Monitor可分為系統監控和應用監控。系統監控比如CPU,記憶體,網路,磁碟等等整體的系統負載的資料,細化可具體到各程序的相關資料。這一類資訊是直接可以從系統中得到的。應用監控需要應用提供支援,暴露了相應的資料。比如應用內部請求的QPS,請求處理的延時,請求處理的error數,訊息佇列的佇列長度,崩潰情況,程序垃圾回收資訊等等。Monitor主要目標是發現異常,及時報警

Tracing的基礎和核心都是呼叫鏈。相關的metric大多都是圍繞呼叫鏈分析得到的。Tracing主要目標是系統分析。提前找到問題比出現問題後再去解決更好

Tracing和應用級的Monitor技術棧上有很多共同點。都有資料的採集,分析,儲存和展式。只是具體收集的資料維度不同,分析過程不一樣。

各開源產品的比較

cat zipkin pinpoint skywalking
依賴 Java 6,7,8Maven 3.2.3+mysql5.6Linux 2.6以及之上(2.6核心才可以支援epoll) Java 6,7,8Maven3.2+rabbitMQ Java 6,7,8maven3+Hbase0.94+ Java 6,7,8maven3.0+nodejszookeeperelasticsearch
實現方式 程式碼埋點(攔截器,註解,過濾器等) 攔截請求,傳送(HTTP,mq)資料至zipkin服務 java探針,位元組碼增強 java探針,位元組碼增強
儲存選擇 mysql , hdfs in-memory , mysql , Cassandra , Elasticsearch HBase elasticsearch , H2
通訊方式 http , MQ thrift GRPC
MQ監控 不支援 不支援 不支援 支援(RocketMQ,kafka)
全域性呼叫統計 支援 不支援 支援 支援
trace查詢 不支援 支援 不支援 支援
報警 支援 不支援 支援 支援
JVM監控 不支援 不支援 支援 支援
star數 4.5K 7.9K 5.6K 2.8K
優點 功能完善。 spring-cloud-sleuth可以很好的整合zipkin , 程式碼無侵入,整合非常簡單 , 社群更加活躍。對外提供有query介面,更加容易二次開發 完全無侵入, 僅需修改啟動方式,介面完善,功能細緻。 完全無侵入,介面完善,支援應用拓撲圖及單個呼叫鏈查詢。功能比較完善(zipkin + pinpoint)
缺點 程式碼侵入性較強,需要埋點文件比較混亂,文件與釋出版本的符合性較低,需要依賴點評私服 (或者需要把他私服上的jar手動下載下來,然後上傳到我們的私服上去)。 預設使用的是http請求向zipkin上報資訊,耗效能。跟sleuth結合可以使用rabbitMQ的方式非同步來做,增加了複雜度,需要引入rabbitMQ 。資料分析比較簡單。 不支援查詢單個呼叫鏈, 對外表現的是整個應用的呼叫生態。二次開發難度較高 3.2版本之前BUG較多 ,網上反映相容性較差 . 3.2新版本的反映情況較少依賴較多。
文件 網上資料較少,僅官網提供的文件,比較亂 文件完善 文件完善 文件完善
開發者 大眾點評 twitter naver 吳晟(華為開發者) ,目前已經加入Apache孵化器
使用公司 大眾點評, 攜程, 陸金所,同程旅遊,獵聘網 twitter naver 華為軟體開發雲、天源迪科、噹噹網、京東金融

參考:

分散式鏈路追蹤技術對比

全鏈路監控(一):方案概述與比較