深度解析 | 基于DAG的分布式任务调度平台:Maat
?
阿里妹導讀:搜索中臺建設過程中,單個系統不再能滿足復雜業務的需求,更多時候需要多個子系統互相協作,異步地按照指定流程完成一項特定的功能。例如一個應用的上線流程依次需要調用配置同步模塊、監控模塊、資源更新模塊、冒煙模塊、引擎創建模塊,流程的運行中又有分支判斷、上下文傳遞、失敗重試等需求。基于這種需求,Maat將各類流程化的任務集中管理,各個任務節點以分布式的方式運行在不同容器內,保證流程高效穩定地運行。
背景
什么是Maat?
Maat是一個基于開源項目Airflow的流程調度系統,它支持用戶自定義地組裝流程節點,流程可以在用戶指定的時間觸發(支持crontab格式),或由用戶手動觸發。
Maat的所有節點分布式地運行在Hippo上,由Drogo調度。用戶可以創建自己的調度節點和執行節點,達到資源隔離的目的。
用戶可以通過配置的方式安裝自己執行節點的運行環境,也可以配置執行節點的副本數。
下圖展示了一個任務的一次調度流程:
為什么要做Maat?
我們在項目的開發過程中,經常遇到一些流程化/定時調度的需求,如上線發布流程、定時分析任務流程等。對于這些流程化的調度任務,我們嘗試過自己開發了一套流程調度系統,也嘗試過接入集團的工作流,但難免會遇到一些問題:
- 業務代碼和調度代碼耦合嚴重,修改流程基本需要入侵到代碼級別,業務代碼的發布影響調度。
- 對于這些調度任務,沒有一個統一管控的系統,難以管理和追溯。
- 多分支的復雜流程不能很好支持,上下文傳遞場景不能很好支持。
- 缺少可視化的UI,用戶使用不友好。
技術選型
定時任務&流程任務的調度是一個通用的需求,集團內的產品如D2、工作流,開源的產品如Airflow、Quartz等。
★ D2
D2是基于ODPS生態的一套流程調度系統,承載集團基于ODPS數據產出的調度任務。支持用戶自定義編寫腳本,支持定時任務觸發和手動觸發(補運行的方式),適合基于數據狀態的任務流程調度(如根據數據的產出執行任務流),由D2團隊專門維護,有較好的UI。
但它有一些不足:
- D2的DAG調度是一張大圖,每天需要運行的每個節點及拓撲關系是根據前一天的全局的拓撲關系計算得出的,所以新創建/修改的任務理論上只能第二天生效,如果想立即生效需要采用補運行的方式。業務上經常會有任務的變動(如任務配置或調度時間),或手動觸發一個調度的場景(如隨時發生的上線流程、全量流程),使用D2對業務不是很靈活,也不符合D2的使用場景。
- 不支持流程上下文的傳遞,業務上對上下文的傳遞比較強烈,經常有上個節點產出某個值,下個節點需要使用。
- 缺乏對搜索生態的支持。搜索技術部整個底層架構有自己的一套生態,如調度(Hippo,Drago)、報警(Kmon)。使用D2,不能充分享受搜索技術生態帶來的好處,對于之后的單元化部署也會帶來問題。
★ 工作流
集團工作流是集團審批流程的一個通用調度引擎,很多產品的審批流程都是基于集團工作流的,同時它也可以作為一個簡易的任務調度流程使用,我們在Maat之前也使用集團工作流作為我們流程任務的調度引擎。它支持手動觸發,支持以HSF的方式調用外部系統,支持上下文傳遞。但它在配置上較為復雜,且支持外部系統的調用方式有限。
★ Quartz
Quartz是Java開源的任務調度框架。它支持分布式調度、支持任務持久化、支持定時任務,但不支持流程調度,且任務配置需要耦合在調度系統中,任務的熱加載需要做一些改造。
★ Airflow
開源項目Airflow是一套分布式的流程調度系統,它的優勢如下:
- 業務代碼和調度系統解耦,每個業務的流程代碼以獨立的Python腳本描述,里面定義了流程化的節點來執行業務邏輯,支持任務的熱加載。
- 完全支持crontab定時任務格式,可以通過crontab格式指定任務何時進行。
- 支持復雜的分支條件,每個節點單獨設定觸發時機,如父節點全部成功時執行、任意父節點成功時執行。
- 有一套完整的UI,可視化展現所有任務的狀態及歷史信息。
- 外部依賴較少,搭建容易,僅依賴DB和rabbitmq。
- 有同學問到Luigi與Airflow的對比,個人感覺都是基于pipline的一個任務調度系統,功能也大同小異,Airflow屬于后來居上,功能更強,找到一篇同類產品的對比。
經過一段時間的調研,我們選用Airflow作為我們的原型開發一套分布式任務調度系統,它功能全面,基本滿足業務需求,在功能上擴展相對方便,外部依賴較少,和搜索生態對接相對容易。
原生Airflow的問題
Airflow可以解決流程調度中面臨的許多問題,但直接將原生的Airflow用于生產,仍面臨一些問題:
- 原生Airflow雖然支持分布式,但由于依賴本地狀態,不能直接部署在drogo上。
- 缺乏合適的監控手段,需要結合kmon完善監控和報警設施。
- 缺乏用戶友好的編輯手段,用戶需要了解Airflow的原理和細節。
- 大量任務運行時,調度的性能急劇下降。
- 分布式模式下,原生Airflow存在一些bug。
Maat架構
Maat架構:
業務層
任何流程式調度及定時觸發的需求均可以通過Maat創建應用,Maat提供了可視化編輯頁面及豐富的api,用戶可以方便地創建編輯流程模板,設置復雜的分支邏輯,Maat會在調度時按照運行時的狀態決定流程的流轉路徑。
目前接入Maat的應用場景包括Tisplus、Hawkeye、Kmon、容量平臺、離線組件平臺、Opensearch
管控層
由于原生Airflow的管控比較簡單,是基于描述任務流程dag的Python腳本調度,用戶要進行任務的創建、更新、運行需要深入學習Airflow原理才能上手,并且之后維護只能基于文件操作,非常不便。因此Maat在外層封裝一層管控系統Maat Console,降低運維及用戶學習的成本。
下圖是Maat管控系統Aflow的操作界面:
★ 模板管理
在任務流程調度的場景中,常見的情況是:不同任務執行的流程基本一致,只有個別參數不同。因此Maat提出了基于模板管理的任務流程,用戶在模板管理中定義一個流程的運行模板,對于其中未確定的部分用變量表示。當生成具體任務時,由具體變量和模板渲染出具體的任務。當模板修改時,可以將模板生效到所有依賴該模板的任務。
模板管理預設了幾種任務節點,用戶可以自由選擇不同的任務節點組裝模板流程。
★ 應用管理
管理所有具體的流程調度任務,包括任務使用的模板、變量的值、報警信息、任務觸發crontab等,用戶在通過模板創建應用后,后續可以通過應用管理繼續維護任務的運行。
★ 隊列管理
由于Maat上運行的任務所屬應用各不相同,不同應用運行環境也不相同,另外不同應用也希望達到集群隔離的目的。為了實現這個功能Maat提供了隊列的管理,指定隊列的任務節點會被調度到相應隊列的機器上,相應隊列的機器也只會運行指定隊列的任務節點。
另外,隊列上也可以指定并發數,表示當前隊列上最多同時有多少個任務運行,確保機器上同時運行的任務不會太多導致負載過高,超出并發的任務會被掛起直到資源釋放。
核心模塊
Maat核心模塊完成了任務調度的整個流程。核心模塊的每個節點都獨立運行在機器上,啟動上互相不依賴,通過DB保存數據狀態,通過MQ或FaaS完成消息的分發。
★ Web Api Service
Web Api Service提供了豐富的與外部交互的Api,包括任務增刪改、歷史任務狀態、任務狀態修改、任務的觸發、任務的重試等接口。
另外原生Airflow提供的web展示功能也是由該角色完成。
★ Scheduler
scheduler是Maat關鍵角色,它決定了任務何時被調度運行,也決定一次任務運行中,哪些節點可以被執行。被判定執行的節點會被scheduler通過MQ或FaaS發送給worker執行。
隨著任務的增多,單一的scheduler負載過高導致調度周期增長,為了減輕scheduler的壓力,Maat將scheduler按照業務拆分。不同業務的任務有獨立的scheduler負責調度,發送任務到指定的Worker上。
★ Scheduler性能優化
原生Airflow的調度邏輯吞吐量較低,當任務量增多時,調度周期會很長,一些任務多的Scheduler延遲到達1分鐘左右。我們參考社區最新的實現,對原生調度邏輯進行優化,將原先阻塞的調度方式拆分為多個進程池,全異步地完成可執行任務的生產->提交->輪詢操作。經過壓測原先調度周期為30s-40s的場景降低為5s左右。
★ Worker
worker為具體執行任務的角色,worker會接受scheduler發出的任務,在worker上執行節點中描述的具體任務。worker多副本部署,任務會在任意一個對等的worker上機器,當worker資源不足時,可以動態擴容。
由于不同隊列任務所需的基礎環境不同,如Python、Java、Hadoop、zk等,不同隊列的worker角色啟動參數有配置上的差異,不同隊列的worker啟動時會按照配置中描述的資源完成部署安裝。
worker上任務完成后會回寫db,scheduler察覺到當前任務狀態變化后會繼續任務的調度。
★ Distributers
任務分發層負責將scheduler需要調度的任務發送到指定的Worker上。目前Maat同時使用原生Celery+Rabbitmq的方式和搜索生態FaaS的方式實現任務分發。
★ Celery + RabbitMQ
原生Airflow使用Celery + RabbitMQ完成消息從Scheduler到Worker的分發。
Scheduler將需要運行的任務發送到MQ中,發送到MQ中包含任務對應的隊列信息。Worker從MQ獲取消息時,僅獲取相應隊列任務,拉取到對應Worker上執行。MQ在Maat中以rabbitmq實現,MQ和其他角色一樣,也是獨立部署的。
Celery + Rabbitmq的模型對消息隊列中的任務進行持久化,所有的任務狀態也進行持久化,內存Queue的性能滿足大部分場景的需求。但由于Maat基于二層調度Drogo部署,任何部署節點都要求無狀態的,而消息隊列MQ因為保存消息狀態顯然不滿足這個要求,所以我們選擇使用搜索生態的FaaS框架作為Celery + RabbitMQ的替代方案。
★ FaaS
FaaS:FaaS(Function as a Service)是基于搜索生態實現的ServerLess框架,Maat將其作為執行器。Maat的所有任務都抽象成function,任務執行時則調用相應的function,完成后返回任務狀態。目前已完成與FaaS的初步對接,期望未來能基于FaaS做更多優化。如:多樣化的任務執行方式,可以將輕量級的任務函數化,將重量級的任務服務化;任務資源動態調整,甚至某些任務可以執行時分配資源,完成后即釋放。
對于Maat來講,FaaS支持任務從生產者到消費者的分發,內置消息Queue,提供任務狀態接口,同時FaaS自身保證消息不對丟失,后續還具備根據消費者負載自動擴縮容的功能。
★ 基礎組件
- DB:使用集團IDB,負責Maat信息的持久化,包括任務信息、任務運行歷史、任務運行狀態、節點運行歷史、節點運行狀態等。
- OSS:由于上drogo導致機器遷移的風險,所有日志不能存放在本地,因此所有節點運行日志存放在oss上,需要查看日志上從oss上獲取。
- Kmon:完成監控集群運行狀態及任務失敗的報警功能。
- Drogo:完成Maat所有節點的docker容器化部署。
Maat平臺的優勢
可視化編輯及通用的節點類型
Maat提供了一個管控平臺Aflow,用戶可以方便地編輯流程節點,管理所有的模板和任務,詳細見上文的[管控層]。
除此之外,Maat還提供了豐富的通用節點類型。原生Airflow支持許多不同種類的節點類型,這些節點可以執行不同類型的任務。在與用戶的接觸中,Maat針對用戶的使用習慣與需求,對一些節點進行封裝,同時開發了幾種新的節點類型,可以滿足大部分用戶的需求。
- Bash節點:直接在worker上執行簡單的bash操作,由于bash通常需要依賴其他資源,實際使用較少,參照“帶資源的Bash節點”;
- Http節點:該節點支持http調用,調度時發送http請求觸發其他系統,同時該節點提供一個輪詢的http接口,觸發成功后輪詢其他系統是否成功,成功時才繼續運行;
- 帶資源的Bash節點:與普通Bash節點不同的是,該節點附帶一些資源(如jar包、bash腳本、Python腳本等),節點運行時會先將資源下載到本地,然后執行bash腳本;
- 分支節點:該節點根據之前節點的運行結果或初始傳入的參數決定分之后的節點走哪個分支。
Drogo化部署
Maat服務有多種角色,每種角色都需要不同的運行環境,為了維護這些運行環境,對運維同學來說絕對是個噩夢,這種情況下上hippo成為Maat運維最好的選擇。drogo作為基于二層調度服務的管控平臺,為Maat各個節點部署在hippo上成為可能。具體來說,Drogo化的優勢如下:
- 低成本增加新節點。上Drogo前,有新增節點的需求時,每次都需要準備運行資源,重新寫部署腳本,而每個節點的腳本都要運維同學自己維護。上Drogo后,所有這些部署信息保存在Drogo平臺上,有新的的節點也只需要將之前類似的部署信息復制,稍加修改即可。
- 擴容簡單。上Drogo前,某類任務水位太高,為這類任務擴容,每次都需要準備機器、準備環境、調試運行參數,可能需要半天到一天的時間。上Drogo后,調整副本數,Drogo會自動擴容。
- 有效防止機器遷移帶來的服務中斷。上Drogo前,機器出現問題后,只能另找機器擴容,對于某些只能單點運行的節點,只能燒香祈禱機器不掛了。上Drogo后,機器遷移后,會Drogo會自動分配一臺機器將服務拉起,對于可中斷的服務,單節點部署也不用擔心機器掛了導致服務消失了。
下圖展示了目前Drogo上部署的Maat各個角色:
由于原生Airflow的一些節點是有狀態的,需要依賴本地一些文件,機器遷移會導致這些節點的狀態丟失,我們對Maat做了一些修改,保證機器遷移不會丟失運行狀態:
- 之前的調度依賴本地Python dag文件,機器遷移導致本地文件丟失。我們做了修改,所有dag保存在db,依賴db中保存的信息調度,保證機器遷移后,dag信息也不會丟失。
- 由于基于本地文件,web service和scheduler讀寫的都是同一份dag文件,導致原生Airflow的scheduler和web service角色必須綁定運行。以db中信息調度后,web service和scheduler可以單獨部署。
- 由于原來日志文件保存在本地,機器遷移會導致日志文件丟失。我們改造后,將日志文件保存在oss遠端,每次讀取日志從遠端讀取。
分集群管理
由于不同任務隔離的需求,Maat基于Airflow原生的隊列管理擴展不同任務的集群管理功能,不同類型的任務可以創建自己的scheduler和worker,創建應用時可以使用指定的scheduler調度或運行在指定worker上(如果不指定由默認scheduler和worker調度)。
集群的配置參數包括以下信息:
- worker部署配置:該worker依賴的資源,drogo啟動時會將任務運行需要的資源部署到worker機器上,機器遷移時也會使用這份部署配置重新分配資源。
- worker個數:控制worker角色的個數。
- 集群并發數:控制集群中正在運行的并發數,防止任務運行過多導致下游系統壓力過大。
- scheduler:目前每個集群只有一個scheduler,后續會改造成支持多個scheduler調度節點。
監控&報警
★ 平臺監控報警
為了掌握平臺的運行狀況,Maat在各個節點的關鍵步驟向kmon匯報metric信息,metric異常狀態下會發送報警給開發同學。也可以根據這些metric信息判斷當前集群的負載狀況,對任務負載較高的節點進行優化。
★ 任務報警
對于具體任務,Maat支持在每個任務節點運行異常的情況下發送報警,如節點運行異常、任務未按時運行、任務運行超時等。用戶可以在管控平臺設置報警條件及報警接收人。
平臺現狀
Maat是一個通用基于Dag的任務調度系統,服務于集團內部和云上的許多場景:
- 搜索中臺Tisplus:調度Tisplus的上線流程及其他需要定時觸發的任務;
- Hawkeye:定時調度Hawkeye的分析任務;
- 搜索監控平臺Kmon:支持kmon的監控托管服務及報警處理流程;
- 搜索容量預估平臺Torch:支持容量預估流程的管控;
- 搜索離線平臺Bahamut:支持離線組件平臺發布流程、全量流程;
- Opensearch:一些算法場景的離線任務;
- Tpp:推薦場景的流程調度任務。
Maat線上集群任務執行現狀(2018.8.13數據):
- 日均調度任務:3000+個
- 日均運行任務:24K+次
隨著更多應用場景的接入,平臺能力將會接受進一步的考驗。
未來展望
隨著業務的接入和數據規模的增大,Maat平臺也需要進一步提升用戶體驗,提升平臺穩定性。
- 與Aflow進一步結合,在管控平臺上一站式完成集群的創建、配置、部署。
- 提供更加豐富的報警選項,進一步加強錯誤的反饋機制。
- 隨著任務數量的增多,一些調度上的缺陷逐漸體現出來,對于這些缺陷做進一步優化。
- 和FaaS深度合作,為各類任務創建單獨的FaaS服務,降低資源利用率。
加入我們
搜索中臺從0到1建設已經走過了3年,但它離我們心目中讓天下沒有難用的搜索的遠大愿景還離的非常遠,在這個前行的道路上一定會充滿挑戰,無論是業務視角的SaaS化能力、搜索算法產品化、云端devops&aiops,還是業務建站等都將遇到世界級的難題等著我們去挑戰。
所以,無論是web開發,引擎開發還是算法同學,
歡迎訪問:https://job.alibaba.com/zhaopin/position_detail.htm?trace=qrcode_share&positionCode=GP037395
加入阿里搜索中臺團隊我們一起做最牛X的搜索中臺,讓天下沒有難用的搜索。
?
每天一篇技術文章,
看不過癮?
關注“阿里巴巴機器智能”,
發現更多AI干貨。
總結
以上是生活随笔為你收集整理的深度解析 | 基于DAG的分布式任务调度平台:Maat的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一张图,看懂阿里云的“飞天”史
- 下一篇: 领域驱动设计,盒马技术团队这么做