1. 程式人生 > >分散式定時任務排程平臺Elastic-Job技術詳解

分散式定時任務排程平臺Elastic-Job技術詳解

        在我們的專案當中,使用定時任務是避免不了的,我們在部署定時任務時,通常只部署一臺機器。部署多臺機器時,同一個任務會執行多次。比如給使用者傳送郵件定時任務,每天定時的給使用者下發郵件。如果部署了多臺,同一個使用者將傳送多份郵件。只部署一臺機器,可用性又無法保證。Elastic-Job框架可以幫助解決定時任務在叢集部署情況下的協調排程問題,保證任務不重複不遺漏的執行。

        Elastic-Job是噹噹網在2015年開源的一個分散式排程解決方案,由兩個相互獨立的子專案Elastic-Job-Lite和Elastic-Job-Cloud組成。在這裡,主要對Elastic-Job-Lite技術做分析。

Elastic-Job-Lite架構圖

        Elastic-Job-Lite框架使用zookeeper作為註冊中心,從架構圖可以看出,Elastic-Job-Lite框架通過監聽器感知zookeeper資料的變化,並做相應的處理;運維平臺也僅是通過讀取zk資料展現作業狀態,或更新zk資料修改全域性配置。運維平臺和Elastic-Job-Lite沒有直接關係,完全解耦合。Elastic-Job-Lite並不直接提供資料處理的功能,框架只會將分片項分配至各個執行中的作業伺服器,分片項與真實資料的對應關係需要開發者在應用程式中自行處理。

Elastic-Job-Lite節點圖

        想要了解Elastic-Job-Lite技術原理,應該先了解它在zookeeper上的節點情況。註冊中心在定義的名稱空間下,建立作業名稱節點,用於區分不同作業,所以作業一旦建立則不能修改作業名稱,如果修改名稱將視為新的作業。作業名稱節點下又包含5個數據子節點,分別是config, instances, sharding, servers和leader。config節點儲存作業配置資訊,以JSON格式儲存;instances節點儲存作業執行例項資訊,子節點是當前作業執行例項的主鍵;sharding節點儲存作業分片資訊,子節點是分片項序號,從零開始,至分片總數減一;servers節點儲存作業伺服器資訊,子節點是作業伺服器的IP地址;leader節點儲存作業伺服器主節點資訊,分為election,sharding和failover三個子節點,分別用於主節點選舉,分片和失效轉移處理。更詳細的節點說明請看上圖或Elastic-Job官方文件。

        Elastic-Job-Lite原始碼由兩個入口,一個是JobSchedule類的init方法,當啟動服務時,程式會進入該方法,進行任務的初始化等操作;另一個是LiteJob類,它實現了Quartz框架的Job介面,當定時任務啟動時,會進入該實現類,完成失效轉移項執行、重新分片、獲取並執行本機任務項、錯過任務重觸發等操作。

作業啟動流程圖

        Elastic-Job-Lite初始化的入口是JobSchedule,應用伺服器啟動時,會呼叫JobSchedule的init方法,開啟作業啟動流程。首先新增或更新作業配置資訊,並將配置資訊持久化到zk上;接著建立quartz排程器,作業的排程執行依賴quartz技術;然後啟動所有的監聽器,包括leader選舉監聽、失效轉移監聽、分片監聽等,併發起主節點選舉,將leader節點資訊set到leader/election/instance節點下;然後將伺服器資訊、例項資訊註冊到zk上,並且在leader/sharding下建立necessary節點,作為重新分片的標記;最後由quartz排程器根據cron表示式排程執行。

作業執行流程圖

        Elastic-Job-Lite執行器的入口是實現了Job介面的LiteJob類,當任務排程執行時,進入LiteJob類的execute方法。在這裡完成一系列的操作,包括獲取失效轉移分片項,如果沒有分配的失效轉移項,則判斷是否需要重新分片,然後獲取分配給自己的分片項,然後判斷當前分片項是否正在running,如果否,則執行任務項;如果是,則在sharding/[item]下新增misfire節點,標示該分片項錯過執行,等待分片項執行結束後,再觸發misfire的分片項執行。

總結:

1. Elastic-Job-Lite框架的任務處理、執行等都是針對的分片項,也就是說quartz排程執行面向的是定時任務的分片項,而不是定時任務本身。如果我們不打算對定時任務分片,那麼可以把分片數設為1,這樣在sharding節點下建立1個分片項0,0分片項將會被分配給一個instance,並啟動執行。

2. Elastic-Job-Lite是提供失效轉移功能的,即當正在執行的任務項遇到程序退出或機器宕機等故障,該任務項應該轉移到某空閒伺服器執行。但是,該功能存在bug:(1)失效轉移只能在同一機器上不同例項間完成,跨機器無效;(2)沒有判斷機器宕機時任務項是否正在執行狀態,而是隻要遇到宕機,即使任務項沒有開始執行,也被轉移到其他機器上執行一遍,導致重複執行。

3. Elastic-Job-Lite是預分片,不是動態分片,即Elastic-Job-Lite是在服務啟動時就完成分片項的建立和分配,並儲存在zk節點上,而不是定時任務在每次啟動時,根據機器的處理能力,重新分配任務項,例如:任務比較繁忙的機器不參與新一輪的任務項分配。這樣做的目的是對zk弱依賴,如果進行真正的動態分片,對於秒級的定時任務將會產生很大影響,因為每次任務啟動,應用伺服器都要跟zookeeper進行通訊,並執行重新分片的邏輯,頻繁的通訊,對於秒級定時任務,會錯過很多次執行