深入大數(shù)據(jù)平臺(tái)心臟:餓了么調(diào)度系統(tǒng)全解
隨著餓了么在大數(shù)據(jù)應(yīng)用的不斷深入,需要解決任務(wù)數(shù)量增長(zhǎng)快、任務(wù)多樣化、任務(wù)關(guān)系復(fù)雜、任務(wù)執(zhí)行效率低及任務(wù)失敗不可控等問(wèn)題。
餓了么大數(shù)據(jù)平臺(tái)現(xiàn)狀:每天完成大數(shù)據(jù)任務(wù)計(jì)算 54000+;節(jié)點(diǎn)集群 85 臺(tái)。
開(kāi)源解決方案
Ooize
Ooize 基于工作流調(diào)度引擎,是雅虎的開(kāi)源項(xiàng)目,屬于 Java Web 應(yīng)用程序。由 Oozie Client 和 Oozie Server 兩個(gè)組件構(gòu)成。
Oozie Server 運(yùn)行于 Java Servlet 容器(Tomcat)中的 Web 程序。工作流必須是一個(gè)有向無(wú)環(huán)圖,實(shí)際上 Oozie 就相當(dāng)于 Hadoop 的一個(gè)客戶端。
當(dāng)用戶需要執(zhí)行多個(gè)關(guān)聯(lián)的 MR 任務(wù)時(shí),只需要將 MR 執(zhí)行順序?qū)懭?workflow.xml,然后使用 Oozie 提交本次任務(wù),Oozie 會(huì)托管此任務(wù)流。
AzKaban
AzKaban 是一套簡(jiǎn)單的任務(wù)調(diào)度服務(wù),是 Linkedin 的開(kāi)源項(xiàng)目,開(kāi)發(fā)語(yǔ)言為 Java,包括 Web Server、DB Server、Executor Server。
它用于在一個(gè)工作流內(nèi)以一個(gè)特定的順序運(yùn)行一組工作和流程,定義了一種 KV 文件格式來(lái)建立任務(wù)之間的依賴(lài)關(guān)系,并提供一個(gè)易于使用的 Web 用戶界面維護(hù)和跟蹤你的工作流。
AirFlow
AirFlow 是一個(gè)編排、調(diào)度和監(jiān)控 Workflow 的平臺(tái),由 Airbnb 開(kāi)源,現(xiàn)在在 Apache Software Foundation 孵化。
AirFlow 將 Workflow 編排為 tasks 組成的 DAGs,調(diào)度器在一組 Workers 上按照指定的依賴(lài)關(guān)系執(zhí)行 tasks。
同時(shí),AirFlow 提供了豐富的命令行工具和簡(jiǎn)單易用的用戶界面以便用戶查看和操作,并且 AirFlow 提供了監(jiān)控和報(bào)警系統(tǒng)。
餓了么調(diào)度系統(tǒng)特性
餓了么調(diào)度系統(tǒng)特性如下:
- 任務(wù)創(chuàng)建簡(jiǎn)單,執(zhí)行頻率支持 cron 表達(dá)式。
- 任務(wù)拆分為多種任務(wù)類(lèi)型,支持 19 種任務(wù)類(lèi)型(計(jì)算、推送、抽取、檢測(cè))。
- 任務(wù)依賴(lài)配置簡(jiǎn)單,支持不同周期匹配,提供推薦依賴(lài),DAG VIEW 功能。
- 調(diào)度與執(zhí)行支持 HA,平滑發(fā)布,宕機(jī)恢復(fù),負(fù)載均衡,監(jiān)控告警,故障排查,快速擴(kuò)容,資源隔離。
支持任務(wù)類(lèi)型:
- 計(jì)算:Hive、Spark、PySpark、MR、Kylin。
- 推送:MySQL 推送、HBase 推送、Redis 推送、Cassandra 推送、HiveToX 推送、MySQL 多推。
- 抽?。簲?shù)據(jù)抽取。
- 檢測(cè):Dal-slave 檢測(cè)、數(shù)據(jù)質(zhì)量檢測(cè)、Edsink 檢測(cè)、抽取數(shù)據(jù)檢測(cè)、數(shù)據(jù)有效期、導(dǎo)入導(dǎo)出校驗(yàn)。
- 其他:郵件定時(shí)任務(wù)。
餓了么調(diào)度系統(tǒng)整體架構(gòu)
餓了么調(diào)度系統(tǒng)整體架構(gòu)包括如下 5 個(gè)部分:
- Web 服務(wù):主要提供任務(wù)創(chuàng)建、實(shí)例管理、任務(wù)依賴(lài)管理、Worker 控制、任務(wù)監(jiān)控告警等。
- 調(diào)度執(zhí)行:主要由主備 Scheduler 和多個(gè) Worker 節(jié)點(diǎn)組成,負(fù)責(zé)任務(wù)的調(diào)度與執(zhí)行。
- 基礎(chǔ)服務(wù):提供了 Eless 自助發(fā)布,ELK 故障排查,Huskar 配置中心,Etrace 埋點(diǎn)監(jiān)控,DOG 告警等功能。
- 底層服務(wù):提供 Hive、Spark、Presto、Kylin、Hadoop 支持。
- 公共設(shè)施:包括 MySQL、Redis、Zookeeper。
任務(wù)運(yùn)行過(guò)程如上圖:
- Web Service 提供的 API 創(chuàng)建任務(wù)和依賴(lài)關(guān)系,將任務(wù)信息存入 MySQL。
- Scheduler 定時(shí)生成第二天所有任務(wù)實(shí)例,并定時(shí)輪詢(xún)檢查并改變?nèi)蝿?wù)狀態(tài)為 Ready(是否到了執(zhí)行時(shí)間,是否依賴(lài)已完成)。
- Worker 啟動(dòng)時(shí)注冊(cè)信息至 Zookeeper,并定時(shí)上報(bào)機(jī)器狀態(tài)給 Scheduler。
- Scheduler 的 ZkWorkerManager 監(jiān)聽(tīng) Zookeeper,獲取 Worker 的注冊(cè)信息。
- 獲取 Ready 的任務(wù),TaskPacketFactory 將任務(wù)構(gòu)造成 TaskPacket,使用對(duì)應(yīng)的 SubmitPolicy 投遞任務(wù)給 Worker。
- Worker 通過(guò) Thrift 接收任務(wù),將任務(wù)解析成 InterpreterContext,交給對(duì)應(yīng)的 Interpreter 執(zhí)行,最終由 Docker 運(yùn)行任務(wù)。
- Docker 執(zhí)行情況返回給 Worker,Worker 回調(diào)給 Scheduler 將狀態(tài)寫(xiě)入 MySQL。
餓了么調(diào)度系統(tǒng)功能
任務(wù)依賴(lài)
任務(wù)依賴(lài)通過(guò)如下兩種方式配置:
推薦依賴(lài):是通過(guò)任務(wù)執(zhí)行完將表和列的信息存入 MySQL,由餓了么血緣系統(tǒng)根據(jù)表的關(guān)聯(lián)進(jìn)行推薦。
手動(dòng)依賴(lài):則是人為通過(guò)界面設(shè)置表的依賴(lài)關(guān)系。依賴(lài)關(guān)系支持不同周期的任務(wù)依賴(lài),偏移量支持表達(dá)式【,】【~】。
失敗快速自動(dòng)重試
當(dāng)任務(wù)執(zhí)行失敗時(shí),系統(tǒng)自動(dòng)重新調(diào)起,默認(rèn)重試 3 次;當(dāng)任務(wù)投遞過(guò)程中,節(jié)點(diǎn)因資源緊張拒絕投遞,調(diào)度會(huì)根據(jù)負(fù)載均衡策略嘗試投遞另一臺(tái)機(jī)器。
自助故障排查
任務(wù)執(zhí)行錯(cuò)誤故障排查:節(jié)點(diǎn)提供 HTTP 服務(wù),將任務(wù)執(zhí)行的日志通過(guò) HTTP 返回給 Web Service 并展示到界面上,提供用戶自助排查?;蛘咄ㄟ^(guò)頁(yè)面上的連接訪問(wèn)餓了么錯(cuò)誤分析平臺(tái)(Grace)自動(dòng)分析。
任務(wù)非執(zhí)行錯(cuò)誤排查:任務(wù)調(diào)度和執(zhí)行通過(guò) Flume 將任務(wù)日志進(jìn)行收集,通過(guò)在 ELK 上搜索全局 ID 即可查看調(diào)度和執(zhí)行情況。
監(jiān)控告警
任務(wù)監(jiān)控告警:根據(jù)用戶設(shè)置的告警規(guī)則和告警頻率,對(duì)任務(wù)執(zhí)行超過(guò)完成時(shí)間和失敗的進(jìn)行手機(jī)、郵件、釘釘告警。
故障監(jiān)控和告警:調(diào)度和執(zhí)行節(jié)點(diǎn)進(jìn)行 Etrace 埋點(diǎn),通過(guò)對(duì)接收、執(zhí)行、回調(diào)等關(guān)鍵點(diǎn)進(jìn)行監(jiān)測(cè),當(dāng)指標(biāo)低于其他節(jié)點(diǎn)時(shí)間窗口平均值時(shí),進(jìn)行告警。
調(diào)度&執(zhí)行
調(diào)度主備自動(dòng)切換
調(diào)度器通過(guò)向 Zookeeper 注冊(cè),并隨機(jī)選舉出 Leader 提供調(diào)度服務(wù)。非 Leader 服務(wù)監(jiān)聽(tīng) Leader 狀態(tài)并 Wait,當(dāng) Leader 出現(xiàn)故障,立即切換為 Leader 角色提供服務(wù)。
宕機(jī)恢復(fù)、自我修復(fù)
當(dāng)所有調(diào)度都宕機(jī)時(shí),調(diào)度服務(wù)未恢復(fù)期間,Worker 執(zhí)行節(jié)點(diǎn)回調(diào)會(huì)出現(xiàn)異常。
此時(shí)任務(wù)狀態(tài)會(huì)存入本地文件數(shù)據(jù)庫(kù),并定時(shí)重試回調(diào)。當(dāng)調(diào)度服務(wù)恢復(fù)時(shí),任務(wù)狀態(tài)恢復(fù)正常。
當(dāng) Worker 執(zhí)行節(jié)點(diǎn)宕機(jī)時(shí),節(jié)點(diǎn)上的任務(wù)會(huì)處于運(yùn)行中。當(dāng)節(jié)點(diǎn)重啟時(shí),Worker 會(huì)自我修復(fù)運(yùn)行中的任務(wù),將節(jié)點(diǎn)上未調(diào)起的任務(wù)重新調(diào)起,已經(jīng)運(yùn)行中的任務(wù)通過(guò)讀取 Docker 執(zhí)行完寫(xiě)入本地的狀態(tài)文件進(jìn)行恢復(fù)。
平滑發(fā)布
當(dāng) Worker 節(jié)點(diǎn)進(jìn)行版本升級(jí)時(shí),運(yùn)行中的任務(wù)進(jìn)行自我修復(fù),同上。
資源隔離和快速擴(kuò)容
通過(guò) Docker 限制每個(gè)任務(wù)的 Memory 和 CPU 資源使用;將依賴(lài)的底層服務(wù)打包成鏡像,擴(kuò)容時(shí)便可以很方便的構(gòu)建需要的環(huán)境。
節(jié)點(diǎn)故障維護(hù)
當(dāng)節(jié)點(diǎn)發(fā)生故障或需要維護(hù)時(shí),Worker 執(zhí)行節(jié)點(diǎn)通過(guò) Web 界面即可進(jìn)行上線下線服務(wù),下線后認(rèn)為不再接收任務(wù),但不影響節(jié)點(diǎn)上運(yùn)行中的任務(wù)運(yùn)行。
曾國(guó)欽,餓了么大數(shù)據(jù)平臺(tái)資深研發(fā),目前負(fù)責(zé)餓了么大數(shù)據(jù)平臺(tái)調(diào)度架構(gòu)設(shè)計(jì)、架構(gòu)重構(gòu)、方案落地等工作。擁有多年的項(xiàng)目研發(fā)和架構(gòu)經(jīng)驗(yàn),曾是微盟支付結(jié)算分布式系統(tǒng)架構(gòu)改造落地的推動(dòng)者。