本文主要介紹分布式任務調度平台XXL-JOB(v2.1.0版本),包括功能特性、實現原理、優缺點、同類框架比較等
基本介紹
項目開發中,常常以下場景需要分布式任務調度:
- 同一服務多個實例的任務存在互斥時,需要統一協調
- 定時任務的執行需要支持高可用、監控運維、故障告警
- 需要統一管理和追蹤各個服務節點定時任務的運行情況,以及任務屬性信息,例如任務所屬服務、所屬責任人
因此,XXL-JOB應運而生:
XXL-JOB是一個開源的輕量級分布式任務調度平台,其核心設計目標是開發迅速、學習簡單、輕量級、易擴展、開箱即用,其中“XXL”是主要作者,大眾點評許雪里名字的縮寫
自2015年開源以來,已接入數百家公司的線上產品線,接入場景涉及電商業務,O2O業務和大數據作業等
功能特性
主要功能特性如下:
-
簡單靈活
提供Web頁面對任務進行管理,管理系統支持用戶管理、權限控制;
支持容器部署;
支持通過通用HTTP提供跨平台任務調度; -
豐富的任務管理功能
支持頁面對任務CRUD操作;
支持在頁面編寫腳本任務、命令行任務、Java代碼任務並執行;
支持任務級聯編排,父任務執行結束后觸發子任務執行;
支持設置任務優先級;
支持設置指定任務執行節點路由策略,包括輪詢、隨機、廣播、故障轉移、忙碌轉移等;
支持Cron方式、任務依賴、調度中心API接口方式觸發任務執行 -
高性能
調度中心基於線程池多線程觸發調度任務,快任務、慢任務基於線程池隔離調度,提供系統性能和穩定性;
任務調度流程全異步化設計實現,如異步調度、異步運行、異步回調等,有效對密集調度進行流量削峰; -
高可用
任務調度中心、任務執行節點均 集群部署,支持動態擴展、故障轉移
支持任務配置路由故障轉移策略,執行器節點不可用是自動轉移到其他節點執行
支持任務超時控制、失敗重試配置
支持任務處理阻塞策略:調度當任務執行節點忙碌時來不及執行任務的處理策略,包括:串行、拋棄、覆蓋策略 -
易於監控運維
支持設置任務失敗郵件告警,預留接口支持短信、釘釘告警;
支持實時查看任務執行運行數據統計圖表、任務進度監控數據、任務完整執行日志;
系統設計
1 設計思路
將調度行為抽象形成“調度中心”公共平台,而平台自身並不承擔業務邏輯,“調度中心”負責發起調度請求;
將任務抽象成分散的JobHandler,交由“執行器”統一管理,“執行器”負責接收調度請求並執行對應的JobHandler中業務邏輯;
因此,“調度”和“任務”兩部分可以相互解耦,提高系統整體穩定性和擴展性;
2 系統組成
-
調度模塊(調度中心): 負責管理調度信息,按照調度配置發出調度請求,自身不承擔業務代碼。調度系統與任務解耦,提高了系統可用性和穩定性,同時調度系統性能不再受限於任務模塊; 支持可視化、簡單且動態的管理調度信息,包括任務新建,更新,刪除,任務報警等,所有上述操作都會實時生效,同時支持監控調度結果以及執行日志,支持執行器Failover
-
執行模塊(執行器): 負責接收調度請求並執行任務邏輯。任務模塊專注於任務的執行等操作,開發和維護更加簡單和高效; 接收“調度中心”的執行請求、終止請求和日志請求等
3 工作原理
- 任務執行器根據配置的調度中心的地址,自動注冊到調度中心
- 達到任務觸發條件,調度中心下發任務
- 執行器基於線程池執行任務,並把執行結果放入內存隊列中、把執行日志寫入日志文件中
- 執行器的回調線程消費內存隊列中的執行結果,主動上報給調度中心
- 當用戶在調度中心查看任務日志,調度中心請求任務執行器,任務執行器讀取任務日志文件並返回日志詳情
4 HA設計
4.1 調度中心高可用
調度中心支持多節點部署,基於數據庫行鎖保證同時只有一個調度中心節點觸發任務調度,參考com.xxl.job.admin.core.thread.JobScheduleHelper#start
Connection conn = XxlJobAdminConfig.getAdminConfig().getDataSource().getConnection();
connAutoCommit = conn.getAutoCommit();
conn.setAutoCommit(false);
preparedStatement = conn.prepareStatement( "select * from xxl_job_lock where lock_name = 'schedule_lock' for update" );
preparedStatement.execute();
# 觸發任務調度
# 事務提交
conn.commit();
4.2 任務調度高可用
-
路由策略
調度中心基於路由策略路由選擇一個執行器節點執行任務,XXL-JOB提供了如下路由策略保證任務調度高可用:
忙碌轉移策略: 下發任務前向執行器節點發起rpc心跳請求查詢是否忙碌,如果執行器節點返回忙碌則轉移到其他執行器節點執行(參考 com.xxl.job.admin.core.route.strategy.ExecutorRouteBusyover)
故障轉移策略: 下發任務前向執行器節點發起rpc心跳請求查詢是否在線,如果執行器節點沒返回或者返回不可用則轉移到其他執行器節點執行 (參考com.xxl.job.admin.core.route.strategy.ExecutorRouteFailover) -
阻塞處理策略
當執行器節點存在多個相同任務id的任務未執行完成,則需要基於阻塞策略對任務進行取舍:
串行策略:默認策略,任務進行排隊、丟棄舊任務策略、丟棄新任務策略
(參考:com.xxl.job.core.biz.impl.ExecutorBizImpl#run)
同類框架比較
特性 | quartz | elastic-job-lite | xxl-job | LTS |
---|---|---|---|---|
依賴 | MySQL、jdk | jdk、zookeeper | mysql、jdk | jdk、zookeeper、maven |
高可用 | 多節點部署,通過競爭數據庫鎖來保證只有一個節點執行任務 | 通過zookeeper的注冊與發現,可以動態的添加服務器 | 基於競爭數據庫鎖保證只有一個節點執行任務,支持水平擴容。可以手動增加定時任務,啟動和暫停任務,有監控 | 集群部署,可以動態的添加服務器。可以手動增加定時任務,啟動和暫停任務。有監控 |
任務分片 | × | √ | √ | √ |
管理界面 | × | √ | √ | √ |
難易程度 | 簡單 | 簡單 | 簡單 | 略復雜 |
高級功能 | - | 彈性擴容,多種作業模式,失效轉移,運行狀態收集,多線程處理數據,冪等性,容錯處理,spring命名空間支持 | 彈性擴容,分片廣播,故障轉移,Rolling實時日志,GLUE(支持在線編輯代碼,免發布),任務進度監控,任務依賴,數據加密,郵件報警,運行報表,國際化 | 支持spring,spring boot,業務日志記錄器,SPI擴展支持,故障轉移,節點監控,多樣化任務執行結果支持,FailStore容錯,動態擴容。 |
版本更新 | 半年沒更新 | 2年沒更新 | 最近有更新 | 1年沒更新 |
使用
快速上手
具體如何快速上手使用,官方文檔:http://www.xuxueli.com/xxl-job/ 已經介紹得比較詳細和清楚,不再贅述
注意事項
- 1 時鍾同步問題
調度中心和任務執行器需要時間同步,同步時間誤差需要在3分鍾內,否則拋出異常
參考:com.xxl.rpc.remoting.provider.XxlRpcProviderFactory#invokeService
if (System.currentTimeMillis() - xxlRpcRequest.getCreateMillisTime() > 3*60*1000) {
xxlRpcResponse.setErrorMsg("The timestamp difference between admin and executor exceeds the limit.");
return xxlRpcResponse;
}
-
2 時區問題
任務由調度中心觸發,按照在調度中心設置任務的cron表達式觸發時,需要注意部署調度中心的機器所在的時區,按照該時區定制化cron表達式 -
3 任務執行中服務宕掉問題
調度中心完成任務下發,執行器在執行任務的過程中,如果執行器突然服務宕掉,會導致任務的執行問題在調度中心是執行中,調度中心並不會發起失敗重試。即使任務設置了超時時間,執行器宕掉導致導致任務長時間未執行完成,調度中心界面也不會看到任務超時,因為任務超時是由執行器檢測的並上報給調度中心的
因此遇到任務長時間未執行完成,可以關注是否發生了執行器突然服務宕掉
-
4 優雅停機問題
執行器執行任務基於線程池異步執行,當需要重啟時需要注意線程池中還有未執行完成任務的問題,需要優雅停機,可以直接基於XxlJobExecutor.destroy()優雅停機,注意該方法在v2.0.2之前的版本存在bug導致無法優雅停機,v2.0.2及之后的版本才修復(參考:https://github.com/xuxueli/xxl-job/issues/727) -
5 失敗重試問題
當執行器節點部分服務不可用,例如節點磁盤損壞,但在調度中心仍然處於在線時,調度中心仍可能基於路由策略(包括故障轉移策略)路由到該未下線的節點,並不斷重試,不斷失敗,導致重試次數耗盡。所以路由策略盡量不要采用固定化策略,例如固定第一個、固定最后一個
總結
XXL-JOB上手還是比較簡單,項目源碼還是比較整潔,容易讀懂,學習之后可以更加深入理解分布式系統設計、網絡通信、多線程協同處理等知識點,推薦閱讀