Twitter zipkin 分佈式跟蹤系統的設計與實現

概述

Twitter的zipkin是一個致力於收集Twitter全部的分佈式服務的時間數據的分佈式跟蹤系統。它提供了收集數據,和查詢數據兩大服務。系統的理論模型來自於Google Dapper 論文。Dapper這篇論文能夠點擊這裏git

爲何須要分佈式跟蹤系統?

經過採集跟蹤數據能夠幫助開發者深刻了解在分佈式系統中某一個特定的請求時如何執行的。假如說,咱們如今有一個用戶請求超時,咱們就能夠將這個超時的請求調用鏈展現在UI當中。咱們能夠很快度的定位到致使響應很慢的服務到底是什麼。若是對這個服務細節也很很清晰,那麼咱們還能夠定位是服務中的哪一個問題致使超時。github

架構

通常來講,分佈式跟蹤系統由如下組件構成。redis

封裝基礎框架

跟蹤的信息是經過封裝好的框架,部署在每臺機器上面,而後發送到zipkin。當主機對某一個服務發起請求時,請求所通過的路徑都會被跟蹤記錄下來,而且最終會在zipkin 的服務器端把這些調用鏈組裝起來。Twitter對一些的基礎框架做了封裝,以便於對請求作攔截,而且在攔截的同時,還會把 Trace header 傳遞到下一層。sql

Finagle

Finagle 是Twitter的 SOA 框架,支持Java/Scala兩種語言。數據庫

Finagle 在Twitter被普遍使用,經過finagle來支持跟蹤是一個很是天然的入口點。目前twitter可使它支持客戶端/服務端的Thrift協議和HTTP協議,對於Memecache和Redis僅能作到客戶端支持。使用Scala語言來創建一個 Finagle Server,很是簡單,以下。想要加入跟蹤功能,只須要把tracer 做爲參數傳入,構建便可。後端

ServerBuilder().codec(ThriftServerFramedCodec())
                       .bindTo(serverAddr)
                       .name("servicename")
                       .tracer(ZipkinTracer.mk())
                       .build(new SomeService.FinagledService(queryService, new TBinaryProtocol.Factory()))

 

跟蹤客戶端也是相似的。一旦這樣作了以後,請求就會被自動記錄下來。包括客戶端請求的開始和結束、服務端的開始和結束。ruby

若是你想記錄一些自定義的內容,zipkin還提供了以下的API:記錄 timestamp / value服務器

 

Trace.record("starting that extremely expensive computation")

記錄key/value架構

 

Trace.recordBinary("http.response.code", "500")

Ruby Thriftapp

Ruby thrift 是對ruby語言的支持。

Querulous

Querulous 是一個Scala的訪問數據的框架,能夠理解爲Java中的hibernate,用它就能夠跟蹤全部的sql訪問狀況。

Cassie

Cassie是一個基於Finagle的Cassandra客戶端。能夠和Finagle同樣設置跟蹤功能。

 

KeyspaceBuilder.cluster.keyspace(keyspace).tracer(ZipkinTracer.mk())

 

 
 

傳輸

Twitter使用scirbe來把全部的跟蹤數據傳輸到zipkin的後端和hadoop文件系統。scribe是facebook開發的,運行在每臺機器上面。

Zipkin collector 進程

一旦蒐集的數據到達zipkin的後端,服務器端會對數據進行校驗、存儲,索引。

Storage

數據最開始是放在cassandra數據庫中,固然zipkin在存儲這塊,作到可插播,目前已經作到支持redis,Hbase,MySQL,PostgreSQL, SQLite, and H2。

Zipkin query 進程

當數據被索引和存儲以後,zipkin還提供一個查詢進程用於獲取數據。查詢接口也是基於Thrift協議來實現了,作到了與語言無關性。

UI

zipkin的數據可視化是經過一個叫作D3的js庫來實現的。

模塊

 

怎麼去封裝一個框架

在Twitter,zipkin已經被集成到一些基礎的框架和類庫之中,對於開發者來講,若是想要封裝其餘的框架,就須要對跟蹤的數據模型有一個清晰的認識:

  • annotation :包括一個值,時間戳,主機名
  • span :一組表明一次RPC請求所包含的annotations
  • Trace :一組表明一次用戶請求所包含的spans,其中根span只有一個。

 

另外,還須要把一些輕量級的TraceID和Span ID在服務之間傳遞,這樣才能造成一個完整的調用鏈。

跟蹤的頭信息包括如下:

  • Trace Id - 全局的 id
  • Span Id - 每一個方法調用的id
  • Optional Parent Span Id - 當前方法調用的父方法的 span id
  • Sampled boolean - 是否須要採樣

 

以HTTP協議爲例子,具體的封裝步驟以下:

服務端

  1. 檢查http header中是否存在Trace header信息,若是存在就把這些信息取出來,而後存入到ThreadLocal中,進而把請求串接起來;

  2. 若是不存在,那麼就開始一個新的Trace

客戶端

  1. 客戶端須要把Trace header的信息放在ThreadLocal中,

  2. 若是須要進行RPC調用,須要把Trace header的信息放在協議中,例如http header。

 

github 地址

 

Twitter zipkin github 地址 https://github.com/twitter/zipkin

相關文章
相關標籤/搜索