蘇寧大數據離線任務開發調度平臺實踐:任務調度模塊架構設計

作爲國內最大的電商平臺之一,蘇寧每天要處理數量巨大的數據。爲了更快速高效地處理這些數據,蘇寧調度平臺採取了哪些措施呢?

本文是蘇寧大數據離線任務開發調度平臺實踐系列文章之上篇,詳解蘇寧的任務調度模塊。

目 錄

1.緒言 1

2.設計目標與主要功能 2

3.專業術語 3

4.調度架構設計 5

5.服務重啓和任務狀態恢復 6

5.1 Master Active 組合服務 7

5.2 Master HA高可用設計 7

5.3 Recover任務狀態恢復設計 7
6.Web API接口服務 9
7.後續 10

1.緒言

在上一篇文章《蘇寧大數據離線任務開發調度平臺實踐》中,從用戶交互功能、任務調度、任務執行、任務運維和對外服務等幾方面,宏觀層面進行了理論和實踐的概述。

產品的用戶功能重點需要把握用戶實際的任務開發運維需求,合理的規劃設計產品功能,在使用和運維上便於用戶操作,降低用戶的開發使用成本。簡單的說就是主要保證用戶任務、任務流等關鍵元數據的配置信息的準確性,以及任務狀態的查詢和干預能力,技術上實現不存在難點,在此不再詳細說明。

任務執行模塊側重於任務被領取後,如何根據任務類型選擇不同的執行器(Executer)提交任務執行,並將任務的執行狀態及時準確的返回,由任務調度服務根據返回狀態做相應的下一步處理,除此以外還涉及到任務資源加載、任務配置解析與轉換、自身健康狀態檢查與彙報、worker進程與任務子進程通信、任務隔離、對外接口服務等,這塊將在後面一節再跟大家詳細分享。

任務運維模塊主要關注平臺的自身穩定性、健壯性等各個指標的監控與預警、平臺任務執行異常的監控、任務運行診斷分析、動態擴縮容和應急降級等方面,涉及到的內容也很多,後續章節會陸續跟大家分享。

今天我們重點詳細闡述蘇寧大數據離線任務調度開發平臺的核心模塊—任務調度模塊的架構設計以及開發實踐過程中的關鍵功能點。

2.設計目標與主要功能

調度模塊的核心目標要保證任務能夠按照用戶配置的調度時間、依賴關係準實時調度和執行,同時也允許用戶根據實際需要隨時啓動和停止任務調度,調整任務執行計劃。所謂準時實調度,指的是調度模塊會按照各個上線的任務流的調度時間生成調度執行計劃,當觸發時間到了,平臺會按照調度執行計劃精確的生成任務流實例和任務實例。但是在任務執行上,並不保證準實時的分配機器執行。實際上平臺以整體資源使用情況爲最高原則,並按照一定的限流策略控制任務的執行,比如:任務優先級、任務組併發度、平臺任務併發數、任務特定執行時間等因素。在保證平臺資源允許的情況下,儘量按時執行任務。爲了保障任務的實時性,必須保障任務資源的可用性和計劃可控性。

調度模塊的主要核心服務功能包括以下幾點:

服務重啓和任務狀態恢復功能

在調度服務重啓、主備切換後,系統狀態以及任務運行狀態能否準確的恢復。比如,主節點崩潰或維護期間,發生狀態變更的任務在主節點恢復以後,能否正確更新狀態等等。

Web API接口服務

用戶通過Web控制後臺管理作業,而Web控制後臺與Master服務器之間的交互透過Rest服務來執行,Rest服務也可以給Web控制後臺以外的其它系統提供服務(用於支持外部系統和調度系統的對接)。另外爲了便於監控和調查分析調度異常和問題,提供Master內存關鍵信息的查詢和人工干預的接口能力。

數據信息緩存服務

緩存上線任務流、任務、事件、系統配置、服務器的關鍵元數據信息,這些信息一般在任務流上線後不會經常發生變更,沒必要實時從數據庫中讀取。並對外提供這些元數據信息的同步接口服務,保證緩存信息與數據庫的一致性。

緩存任務流實例、任務實例、事件實例等中間狀態信息,同時持久化到數據庫中。便於在任務狀態切換、任務依賴執行快速找到對應的運行中的關鍵數據。並在任務實例數上升一定量級以後可以快速的從內存中緩存的中間狀態數據完成依賴檢查和觸發執行邏輯,降低對數據庫因爲頻繁訪問造成的壓力。

任務調度服務

主要負責上線任務流的配置檢查、生成任務流執行計劃、按照執行計劃生成任務流與任務實例,生成任務實例狀態機和節點之間的依賴觸發關係。除了這些系統調用主要功能外,還提供人工干預任務執行的服務功能,比如:任務流上下線、任務補數據、任務重跑、任務殺死、失敗重試等

任務狀態機管理

任務流按照調度服務的執行計劃會在每個調度週期內生成需要執行的任務流實例和任務實例信息,這些實例在調度過程中存在多種臨時狀態,並具備一定的生命週期。狀態切換的時候觸發一定的業務邏輯,比如:任務實例由新建狀態切換到待分配狀態,由待分配狀態切換到已分配狀態,由執行中狀態切換到執行結束狀態都可能需要完成一定的處理。這裏我們採用了狀態機的管理機制來確保任務執行狀態的持續性和完整性。

任務狀態分析服務

任務實例在調度過程中存在多種臨時狀態的切換,每次狀態切換必須成功才能保證狀態變化的持續性和完整性,從而保證任務實例從生成到結束的完整生命週期。如果狀態切換過程中發生意外或者長時間停滯在某個狀態不變,可能會導致調度異常和用戶使用恐慌,爲了準確及時的分析任務實例的狀態停滯原因,需要在任務狀態生成和切換的時候進行檢查校驗,把不能切換的原因及時記錄,便於分析問題。

任務狀態發佈服務

平臺上的任務處理的是數據,數據處理的及時性和準確性對業務系統是有極大的影響。而平臺的任務運行狀態往往只會記錄在本平臺數據庫中,外部系統無法感知。在很多場景下,業務系統需要根據任務的執行狀態來執行自己的特定業務邏輯,通過傳統的任務狀態查詢接口又存在延遲性和性能問題,比如:任務狀態的變更,執行時間長短會因爲多種因素而變得不確定;多個外部系統調用平臺接口可能會導致平臺自身壓力的不確定性。可以在任務實例生成和狀態切換的時候,將任務實例狀態按照用戶的配置要求,及時的發佈出去,業務系統根據需要進行訂閱,確保任務狀態更新的及時性,又降低對平臺的侵入和壓力。

任務分配與流控服務

主要負責滿足執行條件的任務實例的分配,以及在任務執行高峯、資源緊張的情況下如何智能有效的進行相應的流控。在以整體資源使用情況爲最高原則,並按照一定的限流策略控制任務的執行,比如:任務優先級、任務組併發度、平臺任務併發數、任務特定執行時間等因素。在保證平臺資源允許的情況下,儘量按時執行任務。爲了保障任務的實時性,必須保障任務資源的可用性和計劃可控性。

事件觸發服務

主要解決複雜業務場景裏,跨任務流依賴、跨系統平臺依賴的調度執行問題。比如:平臺內部多個系統多個任務流之間的依賴調度,以及外部業務系統在某種條件下需要通知調度平臺執行自己的任務。另外需要解決各種頻率之間的依賴關係,比如:天依賴天、天依賴小時、周月依賴天等.

主機健康監控服務

負責管理可以執行任務的機器資源,並根據各機器的健康度合理的分配任務。主要包括:worker機器的發現與管理、worker機器的健康度評估、worker檢活、主機黑白名單(加入黑名單的機器不能領取和執行任務)等

異步更新服務

平臺中存在大量的持久化操作,比如:任務實例的生成與狀態更新、事件的觸發實例生成、任務流的啓停狀態、任務運行狀態原因分析等。有些持久化操作需要伴隨業務邏輯同步更新,確保操作的事務完整性,比如:任務流上下線、任務實例的狀態切換,必須保證內存和數據庫一致性。有些操作則不要求高度一致性和實時性,甚至有些數據的更新錯誤或者丟失也可以忽略不計。同步更新在確保事務、數據的完整和一致性外,帶來了平臺性能的一定下降。而異步更新服務可以提高平臺的運行性能和併發能力,這些低有求的操作和數據同步服務就可以採用異步更新服務來完成。比如:任務運行狀態停滯原因分析、任務狀態的對外發布等

3.專業術語

蘇寧大數據離線任務開發調度平臺具有和業內同款平臺產品的共性,也具備自己的特殊性和專業性。在理解和使用我們的平臺之前,需要了解平臺常見的專業術語,以免造成理解和使用上的分歧。

image
image

任務流實例的中間運行狀態,主要包括:待調度、執行中、執行失敗、執行成功。

任務實例的中間運行狀態,主要包括:待調度、待分配、已分配、已領取、參數檢查錯誤、資源準備失敗、執行中、殺死、執行失敗、失敗重試、執行成功、忽略失敗。

4.調度架構設計

從系統架構的角度出發,模塊化的設計有利於功能隔離,降低組件耦合度和單個組件的複雜度,提升系統的可拓展性,一定程度上有利於提升系統穩定性,但帶來的問題是開發調試會更加困難,從這個角度來說又不利於穩定性的改進。所以各個功能模塊拆不拆,怎麼拆往往是需要權衡考慮的。

平臺採用常見的主從式架構,按照功能模塊劃分清晰,職責單一而不緊耦合,避免繁重複雜的業務耦合設計。調度模塊在系統架構上分爲web接口服務、重啓恢復服務、數據緩存服務、任務狀態發佈服務、事件觸發服務、異步更新服務、任務調度服務、任務狀態機管理、任務分配服務、主機健康監控服務以及任務實例狀態監聽服務等十幾個主要服務功能。每個服務模塊負責的功能清晰,互相耦合度低,具有良好的擴展性、穩定性和容錯性。調度的整體架構設計如下圖所示。

image
調度模塊涉及到多種功能服務,這些功能服務內部涉及到大量複雜的、交互的事件處理、狀態轉換,同時,這些事件調度和狀態轉換又對實時性和效率提出了極高的要求。可以想見,沒有一個規整的、通用型良好的調度器,平臺代碼無論是對讀者,還是對開發者,都將變成一場災難,同時平臺的運行效率也會變得無法忍受。統一的、設計良好的、通用的和共用的調度器,對於調度模塊不同組件的開發者來說是一種解脫,大大降低了平臺在事件調度、狀態轉換的底層出錯的可能性,提高了代碼穩定性和可讀性。

如何組裝、如何進行有效的接口調用來支撐平臺百萬級的任務高效穩定的執行。在組裝設計上需要慎重選型。一般多服務調用分爲函數調用和事件驅動兩種模式。

相比於基於函數調用的編程模型,這種編程方式具有異步、併發等特點,更加高效,因此更加適合大型分佈式系統。調度模塊的十幾個服務之間的大部分服務調用也基本是基於事件驅動的編程模型進行設計。開發實踐過程中,Hadoop的核心調度器AsyncDispatcher的設計和實現同Hadoop狀態機一樣,這個通用調度器設計得十分通用,完美可擴展可重用,我們在自己的項目中完全可以使用Hadoop的調度器實現我們自己的事件調度邏輯。

5.服務重啓和任務狀態恢復

該服務主要是將調度模塊的所有服務組件進行統一的註冊和管理,並按照平臺的業務邏輯順序進行順序初始化和啓動。並通過HAService服務往ZK搶注Master的服務器節點目錄,來完成主備Master的狀態切換。通過RecoverService服務完成 從數據庫中同步任務流、任務、事件等元數據信息和任務實例、事件實例等實例信息的內存恢復操作。根據任務實例的數據庫和zk中保存的狀態進行任務狀態機的創建和後續狀態的持續觸發操作。

5.1 Master Active 組合服務

如前文所述,調度模塊包括了十幾個核心功能服務,如何有效的管理和協同這些服務的起停順序、服務之間的調度關係,我們在Java設計模式上採用了組合模式(Composite),將這十幾個服務按照調度的業務關係進行了組合包裝。

Hadoop Yarn的CompositeService提供了一個比較好的組合封裝服務,包括服務的註冊(添加和移出)、服務的初始化和啓停操作,這些服務被順序的保存在一個List對象中,各個服務會按照順序進行逐個初始化和啓停。調度模塊的這十幾個關鍵服務統一打包在MasterActiveService中。

5.2 Master HA高可用設計

高可用性H.A.(High Availability)指的是通過儘量縮短因日常維護操作(計劃)和突發的系統崩潰(非計劃)所導致的停機時間,以提高系統和應用的可用性。HA系統是目前企業防止核心計算機系統因故障停機的最有效手段。

在HA方面,按照準實時的設計目標,平臺並沒有打算做到秒級別的崩潰恢復速度,系統崩潰時,只要能在分鐘級別範圍內,重建系統狀態,就基本能滿足系統的設計目標需求。

所以其實高可用性設計的重點,關鍵在於重建的過程中,系統的狀態能否準確的恢復。比如,主節點崩潰或維護期間,發生狀態變更的任務在主節點恢復以後,能否正確更新狀態等等。而雙機熱備份無縫切換,目前來看實現難度較大(太多流程需要考慮原子操作,數據同步和避免競爭衝突),實際需求也不強烈,通過監控,自動重啓和雙機冷備的方式來加快系統重建速度,基本也就足夠了。

本平臺在設計的時候採用了“主從方式”實現HA,主要設計要點:

(1)一個狀態管理功能模塊

實現一個zkFailover,常駐在每一個Master服務節點內,每一個failover負責監聽自己所在節點,利用zk進行狀態標識。當需要進行狀態切換時,由zkFailover實現狀態切換,切換時需要注意防止brain split現象發生。

(2)對外服務方式

除了HAService服務外,只能有一個Master節點可以託管和執行其他所有服務。另外一個節點只能啓動HAService監聽主節點的狀態。只有主節點停止服務後,才能啓動其他服務進行工作。

5.3 Recover任務狀態恢復設計

在調度服務重啓、主備切換後,系統狀態以及任務運行狀態能否準確的恢復。比如,主節點崩潰或維護期間,發生狀態變更的任務在主節點恢復以後,能否正確更新狀態等等是一個任務調度平臺的重要功能和考覈指標。

Recover不僅需要恢復各種實例信息的元數據信息和狀態信息,確保每個任務實例狀態切換的連續性、完整性和正確性,還要保證每個任務流內部各個節點之間按照依賴關係及時的觸發和正確執行。在某些場景下, 還需要對因爲調度服務停止期間遺漏的任務流和任務實例進行補償。

第一步完成任務配置相關的元數據信息的恢復。

即從數據庫中同步必要的元數據信息到調度內存中。元數據信息在數據庫中不是存放了一份,爲什麼還要從數據庫中同步一份到調度的內存中呢?在任務量很少的情況下每次讀寫數據庫不會對數據庫造成壓力。但是在任務量上升,任務實例的生成量和狀態切換的量成幾何級上升,隨着對數據庫的讀寫TPS也會上升。這樣一方面可能會造成數據庫的壓力偏大,另一方面如果數據庫服務不穩定、網絡抖動等外部因素而導致調度服務卡住。

在大多數情況下,任務流一旦上線後不會輕易發生變更。如果有部分變動,可以通過Master的web接口同步內存和數據庫的配置信息。爲了保證狀態的一致統一,和任務相關的信息變更,無論是用戶發起的作業配置修改,還是執行器反饋的作業狀態變更,都會提交給Master節點同步寫入到數據庫。具體參考下圖。

image
第二步完成實例信息和任務狀態的恢復。

實例信息的恢復主要包括:任務流實例、任務實例、事件實例的狀態恢復,已經結束的任務流實例信息不作爲恢復的對象。這一步不僅僅的單純同步實例的信息到調度內存裏,更重要的是要恢復任務實例的狀態,確保任務執行按照計劃和依賴關係正確的執行下去。
任務流實例是按照任務流的執行計劃不斷生成的運行個體。當重啓掃描數據中“未執行結束”的任務流實例時,可能會存在大量的實例個體,執行恢復的時候,智能根據“未執行結束”的任務流實例個數啓動一定數量的線程,按照任務流實例進行切分,進行批量恢復。

第三步補償丟失的任務實例批次

Master調度重啓或者服務器宕機等因素造成任務調度計劃被打斷,再次恢復後需要對服務終止期間的丟失的任務實例進行補償,否則會造成某些任務執行計劃被錯過而沒有得到調度執行,引發數據故障。
根據故障恢復的時間長短,結合每個頻率的任務做出不同的補償措施。下表是根據不同頻率類型按照對應策略進行補償。

image

對於一些複雜的業務場景的任務,也不是必須要把所有遺漏的批次都補償完畢,可以適當補償一些遺漏批次,其他遺漏批次在服務重啓後人工補償。如果把歷史遺漏批次都補償,可能會因爲補償的實例數過多而導致當前批次被延後執行。

6.Web API接口服務

用戶通過Web控制後臺管理作業,而Web控制後臺與Master服務器之間的交互透過Rest服務來執行,Rest服務也可以給Web控制後臺以外的其它系統提供服務(用於支持外部系統和調度系統的對接)。另外爲了便於監控和調查分析調度異常和問題,提供Master內存關鍵信息的查詢和人工干預的接口能力。

考慮到調度模塊的代碼部署不依賴外部容器,比如:Tomcat、JBoss等,又要對外提供Web接口服務,因此在技術選型上需要注意這一點。目前市場上流行的SpringBoot、內嵌Jettty等其他Servlet容器方案都可以解決這個問題。我們的平臺使用的架構是Jersey+Guice+Jetty+ Mybatis,jersey作爲Rest服務框架,Guice作爲DI框架,使用內嵌Jetty作爲應用容器,Mybatis負責數據庫的持久化操作,並捨棄web.xml配置,這樣使得開發和部署十分輕量和簡單。

下圖是調度模塊裏各個服務、容器、上下文之間的訪問交互圖。

image

Master上下文承載了配置文件、註冊服務的查找與發現、元數據和實例數據信息以及各個服務的調用轉發器(Dispatcher)。其他服務組件通過Master上下文可以很方便的獲取系統配置信息,調用其他組件接口。Guice框架目前主要託管了數據庫相關操作類以及web服務接口類,被託管的服務類以單例的形式保存。整個調度模塊內嵌了Jetty容器,部署和啓動了WebServer服務,提供外部與Master內部服務的交互入口。

7.後續

上述文章講述了調度模塊的架構設計、恢復和web服務,後續文章會接着講述調度服務的設計細節。調度服務是整個調度模塊非常核心的服務組件,涉及到任務流上下線、任務狀態機管理、任務重跑補數據等運維操作,限於篇幅和時間問題,本次的調度模塊的分享先寫這麼多,後續會陸續對其他服務組件進行詳細闡述,敬請期待。

作者

桑強:蘇寧易購IT總部大數據平臺研發中心離線計算工具研發部經理。10年軟件行業從業背景,13年開始接觸大數據,有着5年多的大數據應用和平臺開發經驗。現在負責蘇寧大數據基礎工具平臺的研發工作,主要包括離線計算工具、實時計算工具、數據資產與質量平臺的架構、研發和項目管理等工作。在對接大數據底層和大數據業務線之間,如何做好平臺工具化,降低用戶使用難度,支撐大數據應用的實踐和研發上有着豐富的研發經驗。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章