JobScheduler是elastic-job作業調度的關鍵類,也是起始類,在包com.dangdang.ddframe.job.lite.api下。調度任務的執行需要包含兩大步驟:任務的配置和任務的注冊。JobScheduler的構造函數除了任務配置和注冊相關信息之外還有事件和監聽。后兩者是elastic-job的擴展功能,我們后續再介紹。
任務的配置
由於內部使用quartz作為任務調度框架,任務的配置的相關的基礎信息也是和quartz一致的。elastic-job的任務配置類在quartz的基礎上(執行方法,cron表達式等)額外封裝了分片策略,監控作業相關參數以及與注冊中心的時間誤差秒數等配置項。
任務的注冊
elastic-job是通過zookeeper進行任務協調和故障轉移的,任務的注冊也就是把任務注冊到zookeeper里面去。任務的注冊包含在任務的啟動過程中。根節點是項目的名稱,下面一級是任務的名稱。任務一旦創建則不能修改任務的名稱,如果修改名稱將視為新的任務,創建新的節點。任務名稱節點下又包含5個數據子節點,分別是config, instances, leader, servers和sharding。如下圖:
1. config節點:
任務的配置信息,包含執行類,cron表達式,分片算法類,分片數量,分片參數等等。config節點的數據是通過ConfigService持久化到zookeeper中去的。默認狀態下,如果你修改了Job的配置比如cron表達式,分片數量等是不會更新到zookeeper上去的,除非你把參數overwrite修改成true。
2. instances節點:
同一個Job下的elastic-job的部署實例。一台機器上可以啟動多個Job實例,也就是Jar包。instances的命名是IP+@-@+PID。
3. leader節點:
任務實例的主節點信息,通過zookeeper的主節點選舉,選出來的主節點信息。下面的子節點分為election
,sharding
和failover三個子節點。分別用於主節點選舉,分片和失效轉移處理。election下面的instance節點顯式了當前主節點的實例ID:jobInstanceId。latch節點也是一個永久節點用於選舉時候的實現分布式鎖。sharding節點下面有一個臨時節點,necessary,
是否需要重新分片的標記。如果分片總數變化,或任務實例節點上下線或啟用/禁用,以及主節點選舉,都會觸發設置重分片標記,主節點會進行分片計算。
4. servers節點:
任務實例的信息,主要是IP地址,任務實例的IP地址。如果多個任務實例在同一台機器上運行則只會出現一個IP子節點。可在IP地址節點寫入DISABLED表示該任務實例禁用。 在新的cloud native架構下,servers節點大幅弱化,僅包含控制服務器是否可以禁用這一功能。為了更加純粹的實現job核心,servers功能未來可能刪除,控制服務器是否禁用的能力應該下放至自動化部署系統。
5. sharding節點:
任務的分片信息,子節點是分片項序號,從零開始,至分片總數減一。分片個個數是在任務配置中設置的。分片項序號的子節點存儲詳細信息。每個分片項下的子節點用於控制和記錄分片運行狀態。最主要的子節點就是instance。舉例來說,上圖有三個分片,每個分片下面有個instance的節點,也就說明了這個分片在哪個instance上運行。如上文所說如果分片總數變化,或任務實例節點上下線或啟用/禁用,以及主節點選舉,都會觸發設置重分片標記,主節點會進行分片計算。分片計算的結果也就體現在這instance上。
上文介紹的節點信息並不全面,還有一些會在特定的情況下出現的臨時節點,更多詳細的介紹可以請參看官方文檔:http://dangdangdotcom.github.io/elastic-job/elastic-job-lite/03-design/lite-design/
任務的啟動
任務的啟動過程,就是任務實例和zookeeper進行交互的過程。每個實例在啟動過程中,會把自身的信息注冊到zookeeper中去。並完成選舉和分片策略的設置,也就是完成上文一些zookeeper節點的創建和持久化。
整個啟動的過程都在JobScheduler.init()方法中完成。其中最重要的方法registerStartUpInfo完成了監聽,選舉持久化數據,以及設置分片標志位(為了任務執行是主節點進行分片算法)等工作。init()方法中完成了配置和注冊之后,相關的參數被傳遞給了JobScheduleController類,這個類就是quartz的封裝。之前配置的任務執行類和cron表達式被轉換成JobDetail和Trigger這兩個quartz的類,然后通過quartz的scheduler.start觸發任務。等待任務的執行。
整體流程圖如下:
任務的執行
任務的執行依賴於quartz job的觸發。elastic-job的LiteJob類繼承自quartz的Job類,在任務觸發的時候,添加額外的邏輯處理。LiteJob的執行器AbstractElasticJobExecutor有兩個具體的實現,SimpleJobExecutor和DataflowJobExecutor,各自執行SimpleJob和DataflowJob兩種Job類型。Job觸發的時候,SimpleJobExecutor或者DataflowJobExecutor會被new一次,重新從緩存中加載Job配置並執行。
LiteJob把任務的執行分為執行前,執行(業務代碼的執行),和執行后三個階段。在執行前階段中主要實現分片策略的執行(shardingIfNecessary方法),記錄事件,執行監聽事件等等。而執行后階段主要處理錯過執行的相關任務以及執行監聽事件。
整個執行流程圖如下: