天天看點

棱鏡-分布式實時計算的跟蹤校驗系統

該文章來自于阿裡巴巴技術協會(ATA)精選文章。

摘要:*目前,各種分布式實時計算系統已經在各大網際網路公司得到了廣泛應用。但是,這些實時系統的計算過程多不進行持久化,如果出現消息丢失等異常情況,通常很難定位問題出現的位置和具體原因,更無法做到主動發現消息丢失。對于廣告營銷等對消息準确性要求較高的業務場景來說,這種消息丢失的代價通常很高,即便很低的消息丢失率也會造成大量的财物損失。為此,阿裡媽媽開發了一套面向分布式實時計算架構storm的實時跟蹤校驗系統——棱鏡系統,棱鏡系統實時記錄每條消息在storm上的處理路徑,主動發現消息丢失情況并報警。本文詳細介紹了幾位作者在開發棱鏡中遇到的困難和相應的解決方案,相信對其他分布式實時計算系統的跟蹤校驗系統也有一定的借鑒意義。*

  如今的網際網路應用,日均資料處理量越來越大,對計算實時性的要求也越來越高。為此,各種分布式實時計算系統層出不窮,比較有名的有Yahoo S4,storm,puma等。其中storm由于具備易恢複、可擴充、高容錯等特性,目前被廣泛應用在阿裡媽媽營銷系統的各條業務線上。

不過,雖然storm的acker機制巧妙地保證了每條消息都會被完整處理,但這一機制也有其局限:1)必須正确的調用ack和fail接口,對于邏輯複雜的應用,誤調用在所難免;2)和storm相連接配接的外部更新系統不在acker的監控範圍内;3)如果消息處理出錯,無法确切知道在storm的哪個bolt出錯。

同時,由于Storm計算過程未進行持久化,無法檢視曆史消息的處理路徑。這樣即便我們發現了某條消息有處理不完整的情況出現,也很難複現。

在棱鏡系統上線之前,阿裡媽媽的開發人員通常不能及時發現線上問題,有時甚至要晚于客戶發現。而為了定位這些問題,往往又需要分别查詢storm及storm通路的多個外部分布式系統的日志。由于這些日志散落在叢集的各台機器上,查找起來非常費時,且有些日志受限于單機的存儲能力,儲存的時效有限。這樣帶來的問題一是問題處理不及時,引發客戶投訴,客戶滿意度下降,造成财物損失;二是定位問題費時費力,定位成功率也不高;三是有些問題客戶自己可能也無法發現,或者發現後沒有及時回報,導緻bug一直線上上運作。

  為了解決1.1節中提到的問題,我們開發了棱鏡系統,它實時地監測着storm系統的運作情況,記錄下每條消息的處理路徑,友善開發人員複現問題。同時準實時地對每條消息的處理路徑進行校驗,在發現問題時主動向開發和運維人員報警,并提供了一鍵消息重發工具,在異常出現時做到及時恢複。

棱鏡系統在設計之初,就考慮到了營銷系統的特殊要求,提出了以下設計目标:

1. 精确性,作為一個跟蹤校驗系統,如果本身不夠精确,那麼必定引起使用者的不信賴,同時,營銷系統與收入、扣款直接相關的特性,也要求棱鏡必須做到足夠精确。

2. 實時性,實時系統的監測系統自然也需要滿足實時性,不然在使用者投訴後,再收到異常報警也沒有任何意義。

3. 對應用盡可能透明。阿裡媽媽的營銷系統有數十、上百個拓撲,如果更新十分困難的話,也必然會阻礙棱鏡的推廣。對于棱鏡,非常幸運的一點是,阿裡媽媽的多條業務線共用一套拓撲架構,不同的業務在這套架構下,通過不同的配置得到适用于自己的業務邏輯,故而棱鏡的改動可以集中在這個拓撲架構中,業務不需要關心。

![棱鏡系統的總體設計架構]

棱鏡-分布式實時計算的跟蹤校驗系統

  圖2.1展示了棱鏡系統的總體架構。其中Spout/Bolt[A-C]是要監控的某個拓撲進行流式處理的多個分布式元件。Dispatcher和updated是storm通路的外部更新系統,也在棱鏡的監控範圍内。ODPS(Open Data Processing Service)是阿裡巴巴研發的海量離線資料處理平台,提供了批量結構化資料的存儲和計算服務,棱鏡的跟蹤記錄、主動校驗計算、曆史資料查詢等都在ODPS平台上進行。從資料流的角度看,在storm等叢集上收集到ODPS原始trace資料首先通過準實時merge将同屬于一條消息的所有trace聚集到一起,再通過消息校驗發現異常消息、觸發報警,詳細的資料流處理将在2.3節中介紹。

  Spout/Bolt在接收和發射(emit)消息之後各打一條trace日志,每條日志以key-value形式記錄下SeqID(每條消息唯一的主鍵,在各個bolt間不變,用于對齊),execTime(在storm中打點時的時刻,精确到毫秒),appName(拓撲名),clusterName(叢集名稱),boltName(spout或者bolt的名稱), 機器ID以及一些其他自定義的個性化、多元度的資訊。

舉例來講,對于如圖2.1中的拓撲結構所要處理的某條消息來說,它會在Spout/Bolt[A-C]的入口、出口各打一條trace日志,共八條,這八條日志組成該條消息的處理路徑。

  如2.2節所述,每一條消息在storm中進行處理時,都會産生多條散布在各台機器上的trace資料。 接下來需要對這些Trace資料進行收集、對齊和完整性校驗。整個流程包含以下幾個步驟:

1、 使用分布式系統日志收集工具TimeTunnel将storm各節點上的trace日志收集到ODPS上,表中每一行是一條原始的Trace日志。

2、 對原始Trace資料進行解析、分列,并存儲于一張split表。這張表在查詢定位問題時使用,由于進行了分列,可以按照各種條件組成sql語句進行查詢。

3、 将Trace資料按照消息主鍵(SeqID)進行對齊,我們稱這個過程為merge流程。經過對齊,同一條消息的所有trace資料就被合并到一起,形成了一條消息的處理路徑(tracing path)。

4、 對每條消息的處理路徑進行完整性校驗(見2.4),如果發現有處理不完整的情況,則觸發報警。

以上步驟全部在ODPS以準實時的方式(小batch處理)進行處理,batch時間間隔可以進行調整。

  所謂主動校驗,就是檢查每條消息的處理路徑是否完整,是否走完了storm中預期要經過的所有bolt。同時,校驗時還必須考慮到以下幾種特殊情況

1、 可能有重傳。在消息處理出現問題時,storm會通過重發消息,防止瞬時故障造成的影響。

2、 可能有消息分裂。在storm中,一個bolt可以emit多個消息,我們稱這種情況為消息分裂(1分N)。

3、 可能有主動丢棄,這種情況下消息處理流程提前中止為正常情況。

為了解決上述三個問題,在棱鏡的主動檢驗中,采用了如下算法:

1、 對消息處理路徑上的trace進行排序,找到最後一次重傳的所有trace日志,在主動校驗中僅考慮最後一次重傳。

2、 對最後一次重傳中每種spout/bolt入口、出口的trace日志進行計數,檢視是否有消息分裂的情況。如果有,則流程後方bolt的trace數也必須與之吻合。

3、 對于提前中止的情況,再檢查3.3節中将要介紹的ErrorCode,如果ErrorCode也表示異常,才認為該消息處理路徑真的出現異常。

  利用2.1節中所述的架構,棱鏡還提供了debug tracing或者稱為即時tracing的功能。有些時候,開發同學需要線上上檢視某條消息處理時的debug日志(預設關閉)。這在以前隻能通過重新開機拓撲,打開debug日志選項,再到storm各節點上grep才能檢視。

在棱鏡中,由于已經有了日志收集,日志分列的架構,通過添加一些截獲debug日志輸出的代碼,就簡便地實作了這個功能。現在,開發同學隻要在Storm的輸入消息體裡加入debug=true的選項,棱鏡就會把這條消息的所有debug日志都收集到split表中,供開發同學友善地查詢。

棱鏡-分布式實時計算的跟蹤校驗系統

  現在考慮2.3節中的merge流程。在棱鏡的進行中,為保持實時性,對這一聚合過程采取了分小batch處理的方式。例如,本次處理0分到5分的資料,下次處理5分到10分的資料。但是,這種時間區間劃分方式會導緻某些同屬一條消息的處理路徑被切分到不同batch。圖3.1給出了這一問題的圖形化描述,其中,每個彩色長方形代表一條消息的處理路徑,長方形上沿對應最早的spout的execTime時間,下沿對應最後一條trace日志的execTime時間。黑線代表批處理時間區間的某個邊緣(如下邊緣)的可能劃分位置,從圖中可以看出,不管這個時間邊緣劃在哪裡,都會導緻某條消息處理路徑被一分為二。

為解決這一問題,我們将merge流程劃分為兩個階段,分别稱為merge1和merge2。在merge1階段,以15分鐘為一個時間區間進行一次聚合,這樣部分位于區間邊緣的消息路徑(tracing path)将不可避免地被切分到兩個區間。是以在merge1做消息聚合時,将本次處理區間内同一path的每條trace的execTime統一設定為該path所有trace中最小的execTime,這樣一來path在時間線上的表示也就由“方塊”壓縮成了“直線”,是以在merge2劃分時間區間時就不會再遇到時間區間邊緣的劃分問題。之後在merge2階段,以merge1時間區間的中點為邊緣再進行一次跨merge1分區的聚合操作,将merge1時被劃分到不同分區的同一消息路徑重新聚集到一起。

  在2.3節介紹的主動校驗算法中,需要對消息路徑上的trace進行排序,找出最後一次重傳的所有trace。理論上,這隻需要按每條trace的execTime大小排序就可以了。但是,作為一個分布式系統,storm各台機器間的時間戳會有最多5毫秒的誤差,這會打亂排序的順序。

或者,既然我們知道消息流過spout/bolt的順序,那按這個順序進行排序不是也可以嗎?這在正常情況下的确可以。不過重傳會導緻這種排序算法失靈。

為此,我們為每一次重傳引入一個唯一的UUID,它在spout中通過函數System.nanotime()獲得,可以精确到納秒。這樣,在多次重傳間就可以利用execTime+UUID得到每次重傳發生的相對位置,在一次重傳内,再利用Bolt間的相對位置确定排序順序。

  對于有些消息來說,沒有走完整套消息處理流程是正常情況。為了不産生誤報,我們在棱鏡中定義了一套傳回值ErrorCode,用來表征處理流程中的消息丢棄是否符合預期。隻要相關業務線插件按照這套ErrorCode上報自己的處理結果,棱鏡就可以提供精準的主動校驗。

  圖4.1列出了兩個拓撲使用棱鏡前後的性能對比。可以看出,棱鏡造成的時延增加在16%以内,QPS下降約在5%。

棱鏡-分布式實時計算的跟蹤校驗系統

  目前,棱鏡項目已經在阿裡媽媽的搜尋營銷、展示營銷、定向廣告等多個業務場景的多個storm拓撲上得到了廣泛的應用,取得了豐碩的成果。但是,棱鏡的應用場景絕不僅僅局限于storm,任何具有分布式、消息流式處理(實時或非實時的)架構的系統都可以通過接入類棱鏡的trace收集(timetunnel) + ODPS + 監控資料流pipeline的外部監控系統獲得曆史消息查詢和消息處理實時監測的好處,令這些系統由黑盒變白盒,為發現問題、定位問題提供友善。

  棱鏡上線以後,取得了激動人心的效果。消息丢失的問題得到了全面修複,日均丢消息數量從之前的280餘條降為現在的接近0條,相當于每年減少數百萬的财物損失。調查、定位問題的效率也大幅提升了20倍以上,例如淘寶直通車線上的某個問題,之前定位共花費了3人日,現在定位類似問題隻需要簡單執行一條指令就可以快速複現。由于有了主動監測報警,新出現的消息丢失可以得到快速發現和立即解決,相關投訴減少90%以上,提升了客戶滿意度。曆史消息處理路徑查詢也變得簡單友善,圖6.1和6.2展示了棱鏡提供的console和WebUI兩種查詢工具的列印效果。利用這一工具,業務同學可以簡便、快速地查詢最近20天内storm所有消息的處理路徑。

棱鏡-分布式實時計算的跟蹤校驗系統
棱鏡-分布式實時計算的跟蹤校驗系統

  同時,利用這些沉澱下的資料,我們每天進行一次日消息處理量的全量統計,用郵件、網頁報表的形式将統計結果展示給各業務方,及時發現消息處理量的異常波動。

  本文介紹了棱鏡這一分布式實時系統的跟蹤校驗系統,以及我們在開發中遇到的困難和相應解決方案。目前,棱鏡系統已經在阿裡媽媽内部得到了廣泛應用,使用方在不修改代碼的情況下就可以享受到棱鏡帶來的曆史消息快速查詢的好處。

棱鏡的上線,讓Storm由黑盒變成了白盒,為阿裡媽媽的開發人員及時發現和定位問題提供了極大的幫助。通過小batch的批處理方案,棱鏡做到了精确的準實時跟蹤校驗。據我們所知,這也是目前業界首創的解決方案。

是以,我們今天将棱鏡的架構和工程中的難點介紹出來,希望可以為其他分布式流處理系統的跟蹤校驗方案提供一些借鑒。