閱讀119 返回首頁    go 搜狐


全鏈路穩定性背後的數字化支撐:阿裏巴巴鷹眼技術解密

作者|周小帆

編輯|小智

最新一代的阿裏全鏈路監控係統鷹眼 3.0,同時將基礎設施層、分布式應用層、業務邏輯層與客戶端層進行了全鏈路跟蹤;技術層麵,鷹眼 3.0 日均處理萬億級別的分布式調用鏈數據,針對海量實時監控的痛點,對底層的流計算、多維時序指標與事件存儲體係等進行了大量優化,同時引入了時序檢測、根因分析、業務鏈路特征等技術,將問題發現與定位由被動轉為主動。

注:本文整理自阿裏巴巴技術專家周小帆在 ArchSummit 2017 深圳站上的演講。

寫在前麵

今天我講的是應用分布式鏈路追蹤技術。業界大部分的應用分布式追蹤的原理源自 Google 的一篇 Dapper 係統的論文,我們的鷹眼係統也不例外。今天講的這個議題和微服務框架是有一些關係的,大家可能聽微服務相很多遍了,對微服務框架帶來的好處也感同身受,比如說它提高了開發的效率,它具備更好的擴展性,這些好處大家也體會過了。可是微服務其實是一把雙刃劍,微服務同時也帶來了一些問題,而這些問題也就是我們的鷹眼係統需要解決的問題。

本文分為三個部分,第一個是阿裏巴巴的分布式追蹤係統,也就是鷹眼係統的技術實現原理、基礎功能以及在阿裏的使用場景。第二個想和大家分享一下這套係統背後的一些技術細節,包括流計算,存儲的架構演進,我們踩過的一些坑、技術層麵一些優化是什麼樣的,也會分享一下我們是如何對監控係統進行模塊化改造的。第三個就是我們如何把一個被動的監控係統轉成一個主動發現問題的係統,這一塊我們其實也是在做初步的嚐試和探索,在做的過程中也希望跟大家一起分享,拋磚引玉,交流一下經驗。

分布式鏈路追蹤技術原理

微服務之熵

微服務的好處已經不用多說,而微服務的壞處,大家看這張圖就明白了。這張圖是 2012 年淘寶核心業務應用關係的拓撲圖,還不包含了其他的非核心業務應用,所謂的核心業務就是和交易相關的,和錢相關的業務。這張圖大家可能看不清楚,看不清楚才是正常的,因為當時的阿裏應用數量之多、應用間關係之混亂靠人工確實已經無法理清楚了。

基於微服務體係之下構建的業務係統存在的問題基本上分為四類,第一個是故障定位難,今天我們淘寶下單的動作,用戶在頁麵上點購買按鈕,這麼一個簡單操作,其實它背後是由十幾個甚至數十個的微服務去共同完成的,這十幾個甚至幾十個微服務也由不同的團隊去負責,這是微服務的過度協同帶來的結果,一旦出現問題,最壞情況下我們也許就要拉上十幾個團隊一起來看問題。

第二個問題是容量預估難,阿裏每年要做若幹次大促活動,在以前的巨石係統當中做容量預估是非常容易的,因為我們大促時候按照預估的流量與當前係統的單機壓測容量做一個對比,把所有的係統按比例去擴容就可以了。而實際上在大促的場景下,每一個係統在核心鏈路當中的參與度、重要性都是不一樣的,我們並不能對每一個係統做等比例的擴容,所以微服務架構下的容量預估也是一件難事。

第三個問題就是資源浪費多,資源浪費多首先是容量預估不準的一個後果,同時資源浪費多背後隱含的另一個問題就是性能優化難,為什麼這麼說呢?我們當打開一個頁麵發現它慢的時候,我根本不知道這個頁麵慢在哪裏,瓶頸在哪裏,怎麼去優化,這些問題累積下來,資源的浪費也成為了一個巨大的問題。

第四個是鏈路梳理難,我們一個新人加入阿裏的時候,老板讓他負責一個係統,他在這個複雜的微服務體係中,就像人第一次在沒有地圖沒有導航的情況下來到一個大城市一樣,根本不知道自己身在何處。應用負責人不知道自己的係統被誰依賴了,也不知道自己的係統下遊會影響其他哪些人。

整體來看,我們所說的微服務之熵主要就包含了這四個問題。

鷹眼是什麼

鷹眼就是主要的目的就是解決上麵所說的這四個問題,我們首先來定義一下鷹眼這個係統,它是一個以鏈路追蹤技術為核心的監控係統,它主要的手段是通過收集、存儲、分析、分布式係統中的調用事件數據,協助開發運營人員進行故障診斷、容量預估、性能瓶頸定位以及調用鏈路梳理。它的靈感是來自於 Google 的 Dapper。

基本實現原理

我們來看一下它的基本實現原理。在阿裏巴巴每天有超過一萬億次的分布式調用,這個數據其實也是很早之前統計的,如果在這一萬億次調用當中出現了一個問題,我們怎麼去定位?看一下這個例子,係統 A 調用 B,B 調用 C,在這之後 A 又調用了 D,如果 B 調 C 出了問題的話,那麼負責維護 A 係統的開發人員根本不知道問題到底出在哪裏,他隻知道這次調用失敗了,那麼我們怎麼樣解決這個問題?雖然現在的很多大公司都在重複造很多輪子,但還好在阿裏巴巴中間件這個東西沒有被重複造出兩個,基礎設施還是相對比較統一的。所以我們可以在一套中間件裏做統一埋點,在分布式調用框架、分布式消息係統、緩存係統、統一接入層、Web 框架層的發送與接收請求的地方做統一埋點,埋點的數據能夠被一套中間件在係統之間進行無縫透傳。

當用戶的請求進來的時候,我們在第一個接收到這個請求的服務器的中間件會生成唯一的 TraceID,這個 TraceID 會隨著每一次分布式調用透傳到下遊的係統當中,所有透傳的事件會存儲在 RPC log 文件當中,隨後我們會有一個中心化的處理集群把所有機器上的日誌增量地收集到集群當中進行處理,處理的邏輯比較簡單,就是做了簡單清洗後再倒排索引。隻要係統中報錯,然後把 TraceID 作為異常日誌當中的關鍵字打出來,我們可以看到這次調用在係統裏麵經曆了這些事情,我們通過 TraceID 其實可以很容易地看到這次調用是卡在 B 到 C 的數據庫調用,它超時了,通過這樣的方式我們可以很容易追溯到這次分布式調用鏈路中問題到底出在哪裏。其實通過 TraceId 我們隻能夠得到上麵這張按時間排列的調用事件序列,我們希望得到的是有嵌套關係的調用堆棧。

要想還原調用堆棧,我們還需要另外一個東西叫做 RPCId(在 OpenTracing 中有類似的概念,叫做 SpanID),RPCId 是一個多維序列。它經過第一次鏈路的時候初始值是 0,它每進行一次深入調用的時候就變成 0.1,然後再升就是 0.1.1,它每進行一次同深度的調用,就是說 A 調完 B 以後又調了 D 就會變成 0.2,RPCId 也隨著本次調用被打印至同一份 RPC Log 中,連同調用事件本身和 TraceId 一起被采集到中心處理集群中一起處理。

收集完了以後,我們對所有調用事件按照 RPCId 進行一個深度遍曆,我們就可以獲得這樣的一個調用堆棧,上圖中的調用堆棧實際上就是真實的淘寶交易係統裏麵進行下單的交易調用堆棧,可以看到這次調用經曆了很多係統。但大家在鷹眼的視角上麵來看,就好像是在本地發生的一樣,我們可以很容易地去看到如果一次調用出現了問題,那問題的現象是出現在哪裏,最後問題的根因又是發生在了哪裏。除了調用異常的返回碼之外,我們在右邊其實還可以看到每次調用的耗時是多少,我們也可以看到每一次調用如果慢了它是慢在哪裏。我們從這張圖中解釋了鷹眼是如何解決微服務四大問題中的故障定位難的問題,它可以通過倒排索引,讓用戶反查出每一次調用的全貌是怎樣的。

如果我們對萬億級別的調用鏈數據進行聚合,是否能夠獲得更有價值的信息?我們可以看一下,每一次調用除了它唯一標識 TraceID 和 RPCID 之外,還包含了一些標簽信息 (Tag),什麼是標簽呢?就是具備共性的, 大家都會有的這麼一些信息,比如說這次調用它分別經曆了這些係統,這些係統它每次調用的 IP 是什麼,經過哪個機房,服務名是什麼?有一些標簽是可以通過鏈路透傳下去的,比如入口 url,它透傳下去以後我就知道這次請求在下去之後發生的每一次事件都是由通過這個入口去發起的,那麼如果把這些標簽進行聚合計算,我們可以得到調用鏈統計的數據,例如按某機房標簽統計調用鏈,我們就可以得到每個機房的調用次數的趨勢圖。

這樣做有什麼好處呢?實際上在容量預估當中這樣做的好處是非常明顯的。我們來看一個例子,假如我們有一個交易下單入口標簽,我們對這樣的標簽做了聚合以後,不光能看到單次調用它的情況是如何,還能看到將這些調用鏈數據聚合以後,它的總調用次數是多少,平均耗時是多少,我可以發現係統當中熱點瓶頸在哪裏,同時我們可以發現一些非法流量,也就是說我之前不知道的事。

比如說我們今天看到交易下單入口,訂單係統耗時比以往要長了,以往都是一毫秒,但現在是三毫秒,我們通過完整鏈路可以看到,實際上這次交易下單應該是一個單元內的操作,但是有一部分流量因為業務邏輯的原因,本該到杭州的數據庫最後跑到上海的數據庫,這麼一個跨集群的網絡調用,實際上會導致整體的耗時增加,我們可以通過這種方式看到它熱點是由什麼原因引起的。同時,我們在做雙 11 流量預估的時候,機器預估其實可以很容易做,因為我們隻要知道交易下單入口我們預期的峰值是多少,可以按照平時的調用比例知道這次下單入口,在下遊的每一個調用環節分攤到的基線流量是多少,根據基線流量來做等比例的擴容,就可以得到雙 11 相對來說比較精準的擴容機器數量。

這是真實的我們係統當中的下單鏈路聚合結果圖。除了我剛才說的一些點,我們還可以獲得一些什麼呢?比如說易故障點,也就是說這個係統看上去大麵上沒什麼問題,但是偶爾它會出一些小問題。為什麼我們說是易故障點,因為一旦它出現問題,下遊的鏈路就終止了,也就是說調用對下遊係統其實是強依賴的關係,那我們可以認為這個鏈路如果有一天下遊係統真的掛了,那麼整條鏈路的穩定性很可能出現問題,我們可以根據這些數據幫助用戶提前發現這些潛在的問題。

第一節就是對基礎功能的小結,它分為兩部分的功能,第一個是通過 TraceId 和 RPCId 對分布式調用鏈的堆棧進行還原,從而實現故障定位的功能。同時通過調用鏈數據分析,將這些入口、鏈路特征、應用、機房這麼一些 tag 進行聚合統計,可以做到容量預估、性能瓶頸的定位以及調用鏈的梳理,所有這些都包含在我們在 2012 年發布的第一版鷹眼係統中,我們接下來看一下這套係統背後的技術演進過程。

EagleEye 架構演進

鷹眼 2012 年架構

這是我們 2012 年架構,這一套架構完成了剛才我在第一章裏麵所說的這些功能。其實後端的技術架構看上去非常簡單,但實際上是非常“重”的,我們整體的技術架構實現的大概是這樣一個流程,中間件會打出調用事件流,統一在所有機器上安裝的 agent 把數據上報到收集集群,然後數據進行一些簡單的清洗以後,將它存到 HDFS 當中。後麵我們做兩件事。

鷹眼 2014 年架構

也因為這樣的原因,我們在 14 年的時候完成了這麼一個實時化的改造,我們把原來比較簡單的、職責較為單一的負責鏈路調用收集的中心集群改造成了用現在大家都知道的流計算引擎去完成這件事。我們把一部分核心的,我們認為比較重要的,用戶認為比較重要的數據通過流計算引擎增量計算,第一時間經過統計和聚合存儲到 HBase 當中,通過大屏幕可以第一時間實時地看到用戶整體的微服務之間的調用流量情況。通過實時化的改造我們也催生出了一些場景,比如說 14 年,在全鏈路壓測的時候鷹眼成為了不管是運維人員還是開發人員非常重要的數據支撐工具,它可以實時看到流量壓測下來以後每個係統的響應情況和鏈路之間的調用關係。同時實時流量調度與限流也是會基於這麼一個調用鏈的情況去追溯到,比如說我發現有個下遊係統扛不住了,那麼我可以根據這個鏈路數據反過來追溯到上遊,去看到鏈路數據的發源地是哪裏,是手機淘寶還是天貓的交易。可以根據這樣的鏈路追溯實時地去響應去做一些流量調度和限流的工作,異常鏈路整個的數據必須以非常高的實時性呈現給用戶。

鷹眼 2016 年架構

那麼 2016 年我們又做了哪些呢?這套係統足夠實時,但是還不夠輕量,因為 Hadoop 還在那,那麼 2016 年我們徹底把 Hadoop 那一套給拋棄掉,把所有的統計計算全部變到了實時引擎當中。每天幾萬億查詢的調用鏈事件存在 HBase 當中顯然是扛不住的,我們是放到一個叫做 HiStore 的 MPP 列式數據庫當中,這一套列式存儲數據庫不但能夠完成原來按照 TraceId 的事情,同時它還可以通過耗時超過多少毫秒,錯誤碼是多少各種各樣的多維查詢條件,把 TraceId 給查出來,更加方便用戶去查找問題。

流計算挑戰

我們在實施這套流計算的過程當中遇到一些坑。第一個我們回顧一下離線計算實時計算區別,離線計算實際上是通過批次計算這麼一個手段,對靜態的文件進行分而治之的 map-reduce 的工作,流計算實際上是對無限的流數據切成很小的批次,對每一個批次進行的一個增量的計算,也就是說數據是不斷上來的,監控數據不斷產生的。以往的做法是把它存到一個大的存儲當中,後麵悠哉悠哉地去跑一下,計算任務掛了也沒有關係。但是流計算我們不能這麼做,我們必須要保持 24 x 7 的穩定性,沒有辦法停機維護的。因為一停機的話整個監控數據掉下來,因此係統必須具備自愈能力。解決方案其實是我們跟 JStorm 團隊進行了緊密的合作, 做了不少優化,比如說把中控節點改成了高可用,自帶 Exactly-Once 功能,當數據出現問題的時候,我們可以永遠通過上一回滾點去回滾到上批次的數據,這樣可以做到監控數據永不停息,永不丟失。

流計算第二個挑戰我剛才也提到它的中間結果是盡量不落地的,那麼不落地帶來的問題就是說它實際上要比離線計算要難得多。舉一個例子,統計全量數據,如果我們是統計一個入口 UV 這件事,其實我們在離線計算當中,這是非常容易做的。按照訪問 Id 排個序,遍曆得到它的 UV 就可以了,但是在流計算裏麵是比較難做的。這邊簡單提兩點,一個就是全量計算到增量計算的過程,這個過程我們實際上是用了一些開源流計算庫,這邊給推薦大家 StreamLib,它可以很容易地幫你通過近似計算估算的方式完成一些看上去在流計算裏麵比較難的事情。流計算就跟離線計算一樣,熱點問題在離線計算當中,因為我預先知道熱點在哪裏,其實很容易去做數據的拆分,但是在流計算當中我們預先是不知道的。所以其實我們的做法也非常簡單,我們前置了一個 LocalReduce 節點,也就是說在所有的監控數據進來之前先在本地監控一次,實際上再發到下遊的時候它的流量就是均勻的,它就不會對下遊的節點產生影響。

監控係統

做監控係統,大家隻要做過監控係統底層設施建設的其實都可能碰到這麼樣一個問題,也就是說那這個問題,其實我在剛開始做鷹眼的時候也是碰到比較痛苦的一個問題,就是說淩晨兩點鍾突然監控的曲線掉下來了,這時候我應該給運維人員發報警,還是不發報警,為什麼我很難做這個抉擇,因為我不知道監控的對象真的出了問題,還是監控係統本身的流計算部分出了問題,流計算係統是不是哪裏卡住了,還是數據收集通道出現了問題。其實當流計算係統被應用到了監控領域中,它提出了更高的要求,一個叫做“確定性”的要求。“確定性”要求在監控係統裏麵,是遠遠大於最終一致性的,所以為了解決這個問題,我們看了一圈現在的流計算引擎提供的解法,實際上沒有很好的現成方案去解決這個問題。

相關優化

我們自己實現了一個齊全度算法來完成確定性的保證。它與 Apache Flink 中采納的 Snapshot 算法有些近似,它其實是在整個流的過程當中去安插一些屏障 (Barrier),我們可以做一個假設,在所有流計算數據產生的地方,數據都是有序的。也就是說我們在收集數據的時候,通過第一探測數據源的深度,第二個在數據時間間隔出現交替的時候,比如說從 12:10 跑到 12:11 的時候去安插一個屏障隨著流做傳遞,流計算過程中保證 FIFO,下遊可以把這些屏障聚合起來,這樣最終數據落地的時候,我就可以知道數據源當中有多少個屏障已經達到了最終的存儲當中。通過這種方式,我們其實可以預測出當一個係統在任意一個時刻它的齊全度是多少,這樣的話我們其實可以很容易得到一件事,就是說這個線掉下去了,但是因為在某一個時間點的屏障還沒有完全到齊,所以我現在可以預測是因為監控係統卡住了,沒有辦法給下遊的運維人員發報警。因為我知道現在數據還沒有收齊,我沒有具備確定性的閾值保證,是沒有辦法去發報警的。這個齊全度的算法,也就是我們在流計算當中,針對監控係統報警場景作出的確定性保證的優化。

存儲層優化

存儲層的優化也說一下,我們一開始是用 HBase 來做倒排索引的,其實我們現在在測試環境當中還是用 HBase 來存,因為簡單可靠。第二個階段也就是我們在 2012 年的時候,把這個 TraceId 進行分片,按 TraceId 排序,反過來用戶通過二分查找方式進行查找。實際上我們現在是用了列式存儲的技術,區別是把同一列的內容用物理相鄰的方式進行存儲,這樣可以換來更好的壓縮比。

因為我們知道對於調用鏈的數據來說,大部分的調用鏈數據都是一些非常相近的數值型類型,比如說 2ms,3ms,1ms 這樣的數據,如果物理上能夠連續地存儲在一起的話,它的壓縮比是非常高的,我們實際通過我們內部叫做 HiStore 這麼一個產品, 經過這個產品的壓縮以後,我們整體調用鏈的壓縮比最高能達到 20:1,也就是說每天如果是 100G 調用鏈日誌,我們最終壓縮下來隻有 5G。

指標存儲,因為大家對現在對時間序列數據庫的開源的實現應該也有所了解,我們對 OpenTSDB 也做了一些改造,第一個把 Proxy 層直接幹掉了,降低了網絡開銷和一些不確定性。第二個 OpenTSDB 必須讓你的數據一次算完指標,直接丟到裏麵存儲,沒有辦法再進行更新的操作。而在一個真實的流計算場景下,我們知道數據有早來的、遲來的,因此業務上原本應該屬於同一個時間窗口的兩條數據有可能實際卻在相差非常遙遠的兩個係統時間內到達流計算引擎,晚到的數據對於原先指標的更新的操作就很難去做。我們在基於 HBase 的時序存儲的背後增加了應對這種場景的 Co-Processor,對於這些晚來的數據背後可以進行一個合並操作,變相地解決了流計算當中數據和時間窗口不對齊的問題。

模塊化改造

下麵一個議題上是我們對鷹眼進行的模塊化改造,我先講一下背景, 大家如果對分布式調用鏈係統非常熟悉的話,實際上它的核心還是在於 TraceId,也就是說我要查什麼問題必須有 TraceId 才行,但實際業務當中碰到的問題,都不是開發人員或者運維人員發現的,而是一線的客服發現的,是業務操作人員發現的,他會跟你說某某訂單號的訂單有問題,某某用戶發現某某商品狀態不對。其實這些問題都是跟業務緊密相關的,實際上最終所有用戶向我們提出了一個需求,需要能夠將業務 Id 和 TraceId 雙向綁定,第二個是業務指標和係統指標雙向關聯。這兩個需求的本質都是用戶需要“自定義”自己的鏈路。這樣的需求來了,我們按照 2012 年的架構來做,就出現了一些問題。

按照我們之前所描述的架構,一種簡單解決自定義鏈路數據的解決方法是,讓所有的用戶都把自定義的數據按照規範打同一份日誌,所有的這些計算方式我們沿用原來的那一套,用統一的方式去處理用戶的自定義鏈路日誌,把它和另外的中間鏈路進行關聯就可以了,實際上我們發現在阿裏的環境下這套方案沒法實施。第一個原因用戶的日誌量根本是不可控的,存儲和計算的開銷很大。

第二是用戶的這些數據,從各個方麵都充滿了自定義的需求,比如說它數據來源不一定是日誌,可能是隊列,可能是數據庫的修改的 binlog,可能是巡檢、撥測的結果。數據過濾方式也不一樣,它聚合的維度更是五花八門,就算是我們係統的數據,聚合維度都是不一樣的。持久化方式也是不一樣的,因為我們原生的方案隻提供兩種,一種是列式存儲,它是基於寫多讀少這麼一個場景,有的用戶說我就是要毫秒級查詢,我想用某某存儲來存這些數據。部署方式也存在各種各樣,比如說跨機房、獨立部署、專有雲輸出的需求等。

這樣的自定義鏈路監控需求我們是沒有辦法滿足的。當需求無法滿足時,大家都喜歡造輪子,監控係統裏麵的這些輪子造起來還真的蠻有意思,它有流計算,高壓縮比的存儲,有各種各樣的數據收集,海量數據挑戰。所以我們在想,與其我們訂一套規範讓你們強製接入,然後你回過頭跟我們說我們的這套規範滿足不了你們的需求,所以你們得自己造一個輪子,還不如把輪子直接給用戶,讓用戶自己通過這些輪子造出自己的汽車來。一開始我們嚐試著自己在 pipeline 裏麵寫代碼。全鏈路壓測、線上精準回歸、故障主動發現的這些場景我們就在原來那套邏輯裏麵去寫,寫完了以後發現真的是扛不住了,因為我們光是解決中間自己的問題就已經連軸轉了。

後來我們發現在這套 pipeline 裏雖然需求五花八門,但組成 pipeline 的各個組件其實存在大量複用的可能,所有的這些對於監控數據的計算邏輯都是可複用的。

積木塊係統

如果我們能夠把這些可被複用的邏輯變成積木塊,讓用戶按照自己的需求去拚裝監控係統的 pipeline,對用戶來說是一件很爽的事情。所以我們幹脆就做了一套積木塊的係統,其實是把整個監控係統當中這些模塊,進行了抽象和分類,比如說切分、邏輯判斷、聚合、持久化、告警,還有一些用戶自定義的邏輯,這一塊也是借助了這套叫做 Google Blockly 開源可視化的框架,我們對它進行二次開發。用戶可以直接在我們的界麵上,拚出自己的監控數據處理流程。

我們來看一個例子,假如有一個交易係統,現在係統裏麵有一份日誌,日誌按照豎線分隔分別代表不同含義,它對我們的要求是,第一: 如果操作出現失敗,將該業務與鷹眼調用鏈產生關聯,這樣根據交易的 ID 我們能查到底下鏈路到底失敗在哪裏。第二個是現在原生的鷹眼裏雖然有交易下單的微服務調用曲線,但實際上是想知道與之對應的各個來源交易額度,想跟微服務的調用曲線放在一個視圖上進行關聯的對比。

我們首先定義數據來源,然後定義切分規則豎線分隔,分別這些字符是什麼意思。當返回碼為“ERROR”時,去記錄一個鷹眼事件,這個事件是什麼呢?交易下單錯誤,然後我把 TraceId 和用戶的手機號進行關聯,同時 RPCId、日期都關聯上去,我們再定義一個 Aggregator 積木塊來做一個聚合計算,比如按照比如入口去進行一個聚合,聚合的計算是對價格的累加,聚合後順便存到 ODPS 阿裏的大數據存儲平台,可能後麵這個用戶還需要對這份日誌去做一個離線的分析。

這一套積木塊的框架,隻要在頁麵上麵簡單拖拽就可以完成,同時這個框架還提供了一個所見既所得編輯模式,也就是說你把樣例日誌放在右上角,左邊拚出你的積木塊以後點一個測試,右邊結果就出來了,來驗證你這個積木塊的邏輯是否符合預期。點擊啟動這個積木塊就會被翻譯成流計算的邏輯,把它提交到當前比較空閑的一個流計算 Slot 去執行,當然這個翻譯的過程我們也是有一些優化。自動合並開銷比較小的算子,比如說簡單的一些切分、邏輯判斷,把它壓到一個 action 當中去執行。不必要的數據傳遞,也就是說下一步不需要的 key 和 value,其實我們幫它自動刪掉了,這樣用戶不會進行那些沒有必要的網絡開銷,點擊啟動以後這個邏輯就直接跑到我們鷹眼計算邏輯集群裏麵去執行了。

用戶對這套積木塊係統比較熟悉的話,基本上五分鍾就可以完成一個自定義鏈路的過程。自定義鏈路完成後的結果在圖中我們可以看到,在是鷹眼的係統調用堆棧之上,會穿插顯示出在與係統調用並行出現的業務事件,另外,由於 TraceId 與業務 Id 形成了雙向關聯,客服人員在進行排查問題的時候,隻要輸入一個手機號,對應的所有係統鏈路就出來了。除了 Id 關聯之外,業務指標和係統指標也實現了雙向關聯,我們可以在一個視圖中看到左邊是服務用量,右邊是各個業務的圖,在上麵這張圖的例子中我們可以看到這個時間點的整體調用量上去了,我們可以知道大部分是來自於淘寶業務,其他的兩個天貓和聚劃算的業務量是沒有什麼變化的。

模塊化改造的結果,總結一下就是 2014 的第一個季度以前鷹眼是一個隻能接受固定來源格式、按固定方式清洗、聚合、持久化的監控係統,到了 2014 年的 Q1 以後,實際上它也變成了一個自定義流式數據采集、清洗、計算、持久化的係統,它可以讓用戶自定義的鏈路數據和原來的鷹眼鏈路數據進行雙向的關聯,很快的,這套係統就在用戶當中推廣起來了。

截止七月前兩天還統計了一下,整個鷹眼的集群線上作業數超過了 1780 了,實際上其中隻有 2 個是鷹眼原生的鏈路統計,其他都是由用戶自己配置的,可以說我們是提供了一套接入平台,是用戶幫助我們構建了完整的鷹眼全鏈路監控體係。每天日均處理量是一個 PB 以上,秒級處理峰值是 7000 萬每秒。除了原先中間那塊藍色中間件之外,我們還接入了下麵橘黃色的用戶業務上麵的數據以及一些其他上下遊的基礎設施的鏈路數據,比如說移動用戶終端、瀏覽器等設備的鏈路數據,還有數據庫層麵的數據,我們把 TraceId 和數據庫的 binlog 打通了,當然這個也是依賴於我們數據庫團隊的一些改造。

上麵紅色的部分實際上是模塊化之前,模塊化之後藍色部分就是用戶自定義的鏈路,日誌事件流、數據庫事件流、終端事件流都可以通過自定義的邏輯存到指定的存儲當中,同時它的這些數據一定要通過 TraceId 和我們原生的這些鷹眼數據進行關聯,這樣就算大家再怎麼重複造輪子,最終都可以關聯在一起,為一輛汽車所用,這個才是造輪子的最終目的。

從被動到主動

我們聊一下從監控係統如何從被動報警轉化為主動發現,這一轉變是我們從去年開始啟動的一個項目。剛才大家看到的鷹眼係統目前已經已經到了 7000 萬每秒的處理峰值,在這個之前其實我們不斷地做優化,2016 年以前我們自己一直陶醉在技術優化的享受當中。到了去年的時候,我們開始反思問自己一些問題,這些問題包括:我們真的需要存儲每一條鏈路嗎?就算我們的壓縮比很高,但實際上隨著阿裏流量不斷的增長,不管怎麼優化存儲量也是相當驚人的。第二個是就算我們有那麼多數據,用戶在上麵配了這麼多報表,我們給用戶算出這麼多報表,用戶真的理解每個報表的含義嗎?第三個是我們能不能比用戶更早發現問題,在這個之前實際上鷹眼還是一個被動的用戶出現問題了過來查問題的係統,我們能不能領先一步,在用戶發現問題之前提前把問題暴露,給用戶預知問題,甚至提示用戶問題的最終原因在哪裏。

識別、關聯、定位

我們解決問題的方法基本上也是分為三個步驟,第一個是識別,第二個是關聯,第三個是定位,具體的說一下每一個步驟。

識別什麼呢?識別每一個鏈路當中出現異常的情況。時序指標當中的異常點,也就是突然高上去那一下子,那個時間點我們要識別出來。指標中的一些離群點,比如說機房當中所有的機器,某些機器出現和其他機器不一樣的行為,我們把它識別出來。

我們還能識別什麼?其實今年我們做了一個挺有意思的項目,用戶接了這麼多的自定義日誌進來,我們實際上把用戶的這些日誌進行了自動的歸納和整理。平時大家做應用負責人的時候可能都會有一個經曆,我們常常會帶著很強的“主觀性”去觀察我們的日誌。特別是在發布的時候會盯著日誌看,看日誌跟以前長得差不多,這次發布好像是沒什麼問題,換一個人來發布的時候就完全懵了,因為他不知道日誌以前長什麼樣子。我們其實做這件事的目的就是幫你把日誌每一個種類當中的次數歸納整理出來。

當你的日誌出現異動,什麼叫異動,如果你的日誌裏麵長期出現某一類的異常,這個不算異動,這個叫破罐子破摔,這個異常沒有人修的,或者是前麵開發的人都已經離職走了,沒人知道怎麼回事。異動是什麼,昨天沒有,今天有了,昨天每小時隻有兩百條的,今天每小時有兩萬條,這是一個異動。

再說一下識別,我們會把這些異動給識別出來,也作為識別的一個依據,和之前的所有異常點結合在一起,進行一個關聯,怎麼關聯呢?

第一個是按點關聯:同一個部署單元,比如說同一台機器上麵或者同一個應用裏麵的這些東西可以相互關聯。第二個是按線關聯,時間點上靠近的,比如說這件事在某個時間點發生的,在前一分鍾發生了另外一件可疑的事,這兩件事其實可以關聯起來。第三個是按鏈路關聯,下麵是一個鏈路,在 A 點上發生的事在 B 點上同一時刻也發生了,這兩件事就可能有關係。最終通過關聯的結果我們可以定位原因了,通過這三步識別、關聯以及最後定位,我們可以定位到最終這些相關聯的事到底什麼是現象,什麼是原因,可以把現象和原因做出有可能的關聯。

舉個例子,我們前段時間通過這套係統發現了一個案例,某個核心入口應用 A 的業務指標出現了小幅的波動,另外一個係統應用賣家中心日誌出現了新增的異常堆棧,這兩件事通過識別把它識別出來,當然在同一個時間點上識別出了一堆其他亂七八糟的異常,我們是怎麼把這兩件看似不相關的事情關聯起來呢?

第一,在波動前一分鍾,我們同時發現了做數據庫拆分有分庫分表的規則推送的變更,在這個變更發生前一分鍾我們發現了業務指標的波動。按點關聯是為什麼,因為應用 B 實際上是接受到了配置變更的,那麼按時間線關聯,實際上這兩個事情,時間線上麵是非常接近的。鏈路關聯是什麼呢?應用 A 是強依賴應用 B 的,兩個應用強依賴,其實是可以通過一些基線去得到。那麼最終我就可以認為這一次的分布分表配置變更是引發 A 應用指標波動的高嫌疑原因,實際上我們通過識別出來異動新增的異常堆棧,人工驗證以後確實如此。也就是說這一套識別加上關聯再加上定位的手段,我們認為有可能是行之有效的,我們也準備將這套係統繼續開發下去,今後有什麼新的進展也可以跟大家一起同步。

總 * 結

總結一下之前講的一些東西,實際上我之前講的這幾部分內容的順序,也就正好吻合鷹眼版本的演進史,第一版本實現基本的鏈路定位以及指標分析的能力。第二個是平台化,通過積木塊的方式把這些輪子給用戶,讓用戶自定義我們的鏈路,用模塊化平台化的手段讓所有用戶把不同的數據接入進來,共建我們的全鏈路係統。第三個版本實際上是全息排查,同時我們對流計算以及底下的一些存儲做了優化。

實際上如果我們去看整個監控領域的話,基礎運維層麵是大概五年前大家都做得滾瓜爛熟的事情,再往上是應用層以及鏈路層的監控,這些監控通常是通過調用鏈的數據或者調用鏈聚合的數據來完成的。業務層麵,我們希望通過業務和應用係統層麵雙向的 TraceId 的關聯以及指標的關聯來完成一件事,就是業務出現了問題,我能第一時刻定位到底是哪個係統出了問題,哪個係統的變更可能導致業務層麵給用戶感知的問題。

17 年我們的鷹眼係統也正式在公有雲向用戶開放,目前 EDAS 中的鷹眼包含了對阿裏中間件 (Aliware) 體係之上構建的微服務係統提供了開箱即用的鏈路監控能力。而更加完整的自定義鏈路監控功能、前端瀏覽器監控以及其他相關的 APM 功能在阿裏雲的 ARMS(Application Realtime Monitoring System) 上麵也開放了,如果將 EDAS/PTS/ARMS 配合在一起使用的話基本可以讓一個企業在微服務治理、容量規劃、應用鏈路監控以及全鏈路壓測方麵做到和阿裏相同的水準。同時我們內部也在做一些智能診斷相關的一些事情,包括業務鏈路自動梳理和自動根因定位的能力,在合適的時機也會在雲產品上開放給大家使用。

作者介紹

周小帆,阿裏巴巴高級技術專家。8 年金融 + 電商 + 中間件工作經驗,目前就職於阿裏巴巴中間件技術部,整體負責中間件的監控與數據化運營工作,同時為阿裏商品、菜鳥、安全、國際站等多個業務部門提供了完整監控方案。參與了阿裏近五年來監控體係的建設及演進。阿裏雲“業務實時監控 (ARMS)”技術負責人。興趣是業務架構、分布式計算與數據存儲技術。

最後更新:2017-10-08 09:17:52

  上一篇:go 阿裏巴巴版圖再度擴大,物流公司百世集團在美上市
  下一篇:go 蔡崇信準備向NBA球隊投資?阿裏巴巴否認