微博平臺的鏈路追蹤及服務質量保障系統——Watchman系統

如其他大中型互聯網應用一樣,微博平臺由衆多的分佈式組件構成,用戶通過瀏覽器或移動客戶端的每一個HTTP請求到達應用服務器後,會經過很多個業務系統或系統組件,並留下足跡(footprint)。但是這些分散的數據對於問題排查,或是流程優化都幫助有限。對於這樣一種典型的跨進程/跨線程的場景,彙總收集並分析這類日誌就顯得尤爲重要。另一方面,收集每一處足跡(footprint)的性能數據,並根據策略對各子系統做流控或降級也是確保微博平臺高可用的重要因素。要能做到追蹤每個請求的完整調用鏈路;收集調用鏈路上每個服務的性能數據;通過計算性能數據和比對性能指標(SLA)再回饋到控制流程(control flow)中,基於這些目標就誕生了微博的Watchman系統。在業界,Twitter的Zipkin和淘寶的鷹眼系統也是類似的系統。

這樣的系統通常有幾個設計目標:

  1. 低侵入性(non-invasivenss):作爲非業務組件,應當儘可能少侵入或者不侵入其他業務系統,保持對使用方的透明性,可以大大減少開發人員的負擔和接入門檻。
  2. 靈活的應用策略(application-policy):可以決定所收集數據的範圍和粒度。
  3. 時效性(time-efficient):從數據的收集和產生,到數據計算/處理,再到展現或反饋控制,都要求儘可能得快速。
  4. 決策支持(decision-support):這些數據數據是否能在決策支持層面發揮作用,特別是從DevOps的角度。

Watchman系統架構圖

對於這些設計目標,Watchman系統是怎麼樣做的呢?

  • 既然要追蹤調用鏈路要收集數據,通常的做法就是通過代碼埋點來記錄日誌。這樣一方面要求在所有需要收集數據的地方侵入代碼進行修改,並且(可能)引入新的依賴。比如淘寶的鷹眼系統在跨進程的遠程調用兩側(stub和skeleton)通過埋點記錄數據並傳遞請求上下文(request-context)。

    watchman-runtime組件利用字節碼增強的方式在載入期織入增強邏輯(load-time weaving),爲了跨進程/線程傳遞請求上下文,對於跨線程watchman-enhance組件通過javaagent的方式在應用啓動並載入class時修改了JDK自身的幾種線程池(ThreadPool或幾類Executor)實現,在客戶代碼提交(execute或submit)時對傳入的runnable/callable對象包上具有追蹤能力的實現(proxy-pattern),並且從父線程上去繼承或初始化請求上下文(request-context);如下圖所示:

    而對於跨進程的RPC場景,則動態增強傳輸層的客戶端和服務端的邏輯。微博平臺使用的Motan RPC框架有着類似filter-chain的流程,watchman-aspect會插入自己的filter實現;實現的邏輯就是在RPC請求前獲取請求方的請求上下文,序列化後裝配近請求體中,服務方獲取請求後,再從請求體中反序列化請求上下文,同時設置到線程上下文中(ThreadLocal)。如下圖所示:

    這類增強或修改都在運行期完成,對於開發人員完全透明,對於運維人員也很友好;

    普通Java調用的處理方式(埋點/追蹤)則是通過AspectJ的靜態織入,相信廣大讀者對AspectJ都不陌生,它提供非常強大的AOP的能力,我們使用AspectJ來定義幾類切面,分別針對WeiboAuth、HTTP接口、資源客戶端的下行方法等。再利用AspectJ的語法定義各個切點,形如:

     

    @AfterReturning(value="execution(public $type $signature($param))",returning="$return"
    

     

    之後在目標項目的maven構建過程中依靠ajc進行編譯期的織入。之所以選擇編譯期織入方式是因爲我們的業務場景是十分performance-sensitive的。每一個生效的切點也會在運行時向configserver註冊SLA數據。(這個後面會講到)

  • watchman-core組件內置幾類策略,分別用來控制收集數據的範圍、收集數據的採樣率、以及幾種控制策略。

    每個請求進入Watchman系統的邊界後(在這裏是微博平臺Auth系統),通過這些策略來決定哪些足跡需要記錄,比如REST API、RPC調用、存儲/緩存的操作等;同時也通過策略決定本次請求是否需要採樣,採樣率可以動態修改;之後創建請求上下文並向後傳遞。在每一個控制點,又會根據控制策略來確定對本次請求是否丟棄,或是對整個方法以什麼樣的方式來gracefully degrade等;

    我們先來看下請求上下問(request-context)的簡單定義:

    RequestContext類關聯一個閥門策略接口(ThrottleStrategy)和採樣策略接口(SampleStrategy),每個req-ctx實例被構造時會傳入兩個策略的具體實現。在記錄(trace())時,會根據當前採樣策略來決定是否採集數據,並且策略可以動態更新,包括本地配置文件的方式,或者同步configserver的方式。從完全關閉、百萬分之一到全量採集幾個粒度可以選擇。

    閥門策略,顧名思義,就像一個閥門,用來控制流量的大小,或是開啓/關閉。默認是全開的,因爲認爲業務99.999%是可用的,同時源源不斷的性能數據會被收集,在watchman-stream進行彙總計算後會產生與註冊在configserver中的SLA數據的比對結果。比如A服務的性能統計結果低於SLA水平,那麼就會通知到閥門策略,並通過隨機丟棄請求的方式來做流控,當性能結果嚴重低於SLA時就關閉,達到降級的效果。

    互聯網運維中對降級還有一個指標是,是否能優雅的降級,也就是不損害用戶體驗的情況下進行降級。這一點watchman-aspect會根據代碼上的註解(annotation)來實現,@Degradable可以標註在方法上,可以指定returnType(required)和returnValue(optional),降級時根據returnType來生成僞造的結果並返回,如果使用方有指定returnValue就直接用後者返回,如果默認提供的returnType不滿足需要也可以進行擴展。

  • watchman-aspect組件通過異步日誌(async-logger)會在各個節點上輸出日誌文件,如何將這些分散的日誌源源不斷的收集彙總並計算?

    通過watchman-prism組件(基於Scribe),將日誌推送到watchman-stream組件(基於Storm),利用這兩個業界成熟的系統以流式的方式處理數據,stream中bolt會根據需求進行聚合、統計等計算(針對性能數據),規範化、排序(針對調用鏈數據),之後寫入HBase中。這個過程通過benchmark反映出的結果來看,完全能達到準實時的要求(30s左右)。 對於日誌數據推送:首先應用要以一致的方式輸出日誌,理所當然就是通過Log框架的logger來輸出,每個節點產生日誌後需要再依賴scribe推送到日誌中心,所以我們實現了自己的AsyncScribeAppender,如下:

    由於Scribe是基於Thrift進行通信,所以我們的Appender擴展於Log4j的AppenderSkeleton,以普通Logger的API形式供上層使用(異步),同時再作爲一個ThriftClient直接將數據寫到節點上的ScribeClient,之後再通過網絡把日誌推到遠程。watchman-prism在這裏作爲遠程接受方,它是擴展於Scribe的一個ThriftServer。 而Storm這一側,衆所周知,spout組件作爲數據的入口,分發到各個bolt進行流式計算,spout是拉(pull)的模式,它從watchman-prism中不斷取數據,經過簡單的過濾後發射(emit)到其他bolt,不同的bolt有着不同的計算任務,之後將不同緯度的計算數據寫入HBase中。

  • 服務質量保障是Watchman系統的另一特點,在面向服務的架構(SOA)中,各個服務的提供方需要給出SLA(service level agreement)數據,量化服務的各種指標(如吞吐、承載)和服務質量(如99.99% <50ms)。這裏的服務包括http形式的REST API,RPC服務,DB或Cache的接口,以及網絡IO層面等; 微博平臺的各業務方的每一層服務都會在Vintage(微博的類Zookeeper系統)中註冊自己的SLA數據,運行時watchman-stream將不斷計算得出的性能數據與通過watchman-registry獲得的各服務的SLA數據進行比對。結果會反映到Dashboard上,這裏與運維的告警系統等集成,可以及時將狀況推送出去,除此之外也會更新registry中的指標,ConfigService根據指標的變化判斷是否通知各個註冊的客戶方,也就是watchman-aspect,閥門策略就會根據通知調整閾值進行干預。流程如下:

    比如某個服務由於瞬時訪問高峯,造成底層資源壓力變大從而服務響應時間變長,控制策略可以根據設定隨機丟棄後續的請求,如果情況加劇就會自動降級該服務,保證核心服務路徑。整個過程可以自動完成也可以人工通過Dashboard控制。

Watchman系統的下一步

之後的迭代會進一步增強watchman-stream的計算/分析能力,爭取在更多的維度上挖掘出有價值的數據;同時依靠watchman-prism來彙總更豐富的業務日誌,力圖在一個請求鏈路上展現更豐富的上下文相關數據。

總之,爲構建更健壯、更可靠的微博平臺,Watchman系統會繼續演進。

發佈了15 篇原創文章 · 獲贊 1 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章