基本介紹
項目開發中,經常如下場景須要分佈式任務調度:git
所以,XXL-JOB應運而生:XXL-JOB是一個開源的輕量級分佈式任務調度平臺,其核心設計目標是開發迅速、學習簡單、輕量級、易擴展、開箱即用,其中「XXL」是主要做者,大衆點評許雪裏名字的縮寫自2015年開源以來,已接入數百家公司的線上產品線,接入場景涉及電商業務,O2O業務和大數據做業等多線程
功能特性
主要功能特性以下:app
- 簡單靈活提供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)
使用
1 快速上手
具體如何快速上手使用,官方文檔:http://www.xuxueli.com/xxl-job/ 已經介紹得比較詳細和清楚,再也不贅述分佈式
2 注意事項
- 1 時鐘同步問題 調度中心和任務執行器須要時間同步,同步時間偏差須要在3分鐘內,不然拋出異常 參考:com.xxl.rpc.remoting.provider.XxlRpcProviderFactory#invokeService
if (System.currentTimeMillis() - xxlRpcRequest.getCreateMillisTime() > 3*60*1000) {
ide
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上手仍是比較簡單,項目源碼仍是比較整潔,容易讀懂,學習以後能夠更加深刻理解分佈式系統設計、網絡通訊、多線程協同處理等知識點,推薦閱讀