1.簡介
1.1概述
XXL-JOB是一個輕量級分布式任務調度框架,其核心設計目標是開發迅速、學習簡單、輕量級、易拓展。代碼開源,目前已接入多家公司線上產品,比較典型的有大眾點評,優信二手車,一加手機等。
1.2特性
簡單:支持通過Web頁面對任務進行CRUD操作,操作簡單;
動態:支持動態修改任務狀態、暫停/恢復任務,以及終止運行中任務,即時生效;
調度中心HA:調度采用中心式設計,“調度中心”基于集群Quartz實現,可保證調度中心HA;
執行器HA(分布式):任務分布式執行,任務“執行器”支持集群部署,可保證任務執行HA;
任務Failover:執行器集群部署時,任務路由策略選擇“故障轉移”情況下調度失敗時將會平滑切換執行器進行Failover;
一致性:“調度中心”通過DB鎖保證集群分布式調度的一致性,一次任務調度只會觸發一次執行;
自定義任務參數:支持在線配置調度任務入參,即時生效;
調度線程池:調度系統多線程觸發調度運行,確保調度精確執行,不被堵塞;
彈性擴容縮容:一旦有新執行器上線或者下線,下次調度時將會重新分配任務;
郵件報警:任務失敗時支持郵件報警,支持配置多郵件地址群發報警郵件;
狀態監控:支持實時監控任務進度;
Rolling執行日志:支持在線查看調度結果,并且支持以Rolling方式實時查看執行器輸出的完整的執行日志;
GLUE:提供Web IDE,支持在線開發任務邏輯代碼,動態發布,實時編譯生效,省略部署上線的過程。支持30個版本的歷史版本回溯;
數據加密:調度中心和執行器之間的通訊進行數據加密,提升調度信息安全性;
任務依賴:支持配置子任務依賴,當父任務執行結束且執行成功后將會主動觸發一次子任務的執行,多個子任務用逗號分隔;
推送maven中央倉庫:將會把最新穩定版推送到maven中央倉庫,方便用戶接入和使用;
任務注冊:執行器會周期性自動注冊任務,調度中心將會自動發現注冊的任務并觸發執行。同時,也支持手動錄入執行器地址;
路由策略:執行器集群部署時提供豐富的路由策略,包括:第一個、最后一個、輪詢、隨機、一致性Hash、最不經常使用、最近最久未使用、故障轉移、忙碌轉移等;
1.3下載
源碼倉庫地址
https://github.com/xuxueli/xxl-jobDownload
中央倉庫地址
2.項目實踐
2.1初始化“調度數據庫”
數據庫環境:Mysql5.6+
初始化SQL腳本tables_xxl_job.sql,正常情況下應該生成16張表。
調度中心支持集群部署,集群情況下各節點務必連接同一個Mysql示例
導入源碼
xxl-job-admin:調度中心
xxl-job-executor:執行器
xxl-job-executor-sample-springboot:Springboot版本,通過Springboot管理執行器
2.2部署“調度中心”
調度中心配置:/xxl-job/xxl-job-admin/src/main/resources/xxl-job-admin.properties
配置內容說明:
>>>>>郵箱地址無效需自行配置
>>>>>dispatchertask為數據庫名稱
部署項目
正確配置后,將項目編譯打包(war)部署在tomcat(/webapps目錄下),修改tomcat配置文件,如下,即代表調度中心部署成功。
調度中心訪問地址http://localhost:8080/xxl-job-admin,登錄后運行界面如下圖所示
3.部署執行器項目
3.1配置文件和配置類
確認pom文件引入了xxl-job-core的maven依賴,添加執行器配置:
Addresses:調度中心部署根地址,執行器將會使用該地址進行執行器心跳注冊和任務結果回調
Appname:執行器心跳注冊分組依據,即同一個集群下的執行器appname必須一致
Ip:默認為空表示自動獲取IP,也可以手動設置
Port:執行器默認端口9999,集群下的執行器要配置不同的端口
AccessToken:執行器通訊Token,非空時啟用,進行數據加密
注:日志基于logback,logback的使用請另找出處。
Config配置
3.2執行器集群
執行器支持集群部署,提升調度系統可用性,同時提升任務處理能力
集群部署唯一要求為:保證集群中每個執行器的配置項“調度中心地址”保持一致,執行器根據配置進行執行器自動注冊等操作。
調度中心添加執行器
AppName:執行器配置中的Appname值,執行器會周期性以AppName為對象進行自動注冊。
名稱:執行器名稱,因為AppName限制字母數字等組成,可讀性不強,名稱為了提高執行器的可讀性
排序:執行器的排序,新增任務時,將會按照該排序讀取可用的執行器列表
注冊方式:調度中心獲取執行器地址的方式;
自動注冊:執行器自動進行執行器注冊,調度中心通過底層注冊表可以動態發現執行器地址
手動錄入:人工手動錄入執行器的地址信息,多地址逗號分隔,供調度中心使用
機器地址:“注冊方式”為手動錄入時有效,支持人工維護執行器的地址信息。
3.4新建任務
想要完成什么樣的功能,必須由開發者手動編寫實現,以“獲取所有航司數據”為例:
>>>>execute方法實現自己要執行的任務
運行執行器之后,即可在調度中心新增任務
執行器:任務的綁定的執行器,任務觸發調度時將會自動發現注冊成功的執行器
描述:任務的描述信息,便于任務管理
路由策略:當執行器集群部署時,提供豐富的路由策略,包括,
第一個:固定選擇第一個機器;
最后一個:固定選擇最后一個機器;
輪詢:執行器循環執行
隨機:隨機選擇在線的機器
一致性HASH:每個任務按照Hash算法固定選擇某一臺機器,且所有任務均勻散列在不同機器上
最不經常使用:使用頻率最低的機器優先被選舉
最近最久未使用:輪詢的倒序選用
故障轉移:按照順序依次進行心跳檢測,第一個心跳檢測成功的機器選定為目標執行器并發起調度
忙碌轉移:按照順序依次進行空閑檢測,第一個空閑檢測成功的機器選定為目標執行器并發起調度
Cron:觸發任務執行的Cron表達式
運行模式:
模式:任務以JobHandler方式維護在執行器端,需要結合“JobHandler”屬性匹配執行器中任務
JobHandler:運行模式為“Bean”時生效,對應執行器中新開發的JobHandler類@JobHandler注解自定義的value值
子任務Key:每個任務都擁有一個唯一的任務Key(任務Key可以從任務列表獲取),當本任務執行結束并且執行成功時,將會觸發子任務Key所對應的任務的一次主動調度。
阻塞處理策略:調度過于密集執行器來不及處理時的處理策略,
單機串行:調度請求進入單機執行器后,調度請求進入FIFO隊列并以串行方式運行;
丟棄后續調度:調度請求進入單機執行器后,發現執行器存在運行的調度任務,本次請求將會將丟棄并標記為失敗;
覆蓋之前調度:調度請求進入單機執行器后,發現執行器存在運行的調度任務,將會終止運行中的調度任務并清空隊列,然后運行本地調度任務
失敗處理策略:
失敗告警:調度失敗時,將會觸發失敗報警,如發送報警郵件;
失敗重試:調度失敗時,將會主動進行一次失敗重試調度,重試調度后仍然失敗將會觸發失敗告警。注意當任務以failover方式路由時,每次失敗重試將會觸發新一輪路由;
執行參數:任務執行所需的參數,多個參數時用逗號分隔,任務執行時將會把多個參數轉換為數組傳入
報警郵件:任務調度失敗時郵件通知的郵箱地址,支持配置多郵箱地址,配置多個郵箱地址時用逗號分隔
3.5Cron表達式詳細用法
Cron表達式的格式
{秒數}{分鐘}{小數}{日期}{月份}{星期}{年份{可為空}}? ? ??
| 字段 | 允許值 | 允許的特殊字符 |
| --------? | -----:? | :----: |
| 秒? ? ? ? | 0-59? ? |? , - * /? ? |
| 分? ? ? ? | 0-59? ? ? |? , - * /? |
| 小時? ? ? ? | 0-23? ? ? |? , - * /? |
| 日期? ? ? ? | 1-31? ? |? , - * ? / L W C? |
| 月份? ? ? | 1-12或者JAN-DEC? ? |? , - * /? |
| 星期? ? ? ? | 1-12或者JAN-DEC? ? |? , - * ? / L W C #? |
| 年? ? ? ? | 1970-2099? ? |? , - * /? |
秒
允許值范圍:0~59,不允許為空值
“*”代表每隔1秒鐘觸發
“,”代表在指定的秒數觸發,比如”0,15,45”代表0秒、15秒和45秒觸發
“-”代表在指定的范圍內觸發,比如”25-45”代表從25秒開始觸發到45秒結束觸發,每隔1秒觸發一次
“/”代表觸發步進,”/”前面的值代表初始值("*”等同”0”),后面的值代表偏移量,比如”0/20”或者”*/20”代表從0秒開始,每隔20秒觸發一次
特殊字符
“*”
“*”字符被用來指定所有的值。如:"*"在分鐘的字段域里表示“每分鐘”。
“?”
“?”字符只在日期域和星期域中使用。它被用來指定“非明確的值”。當你需要通過在這兩個域中的一個來指定一些東西的時候,它是有用的。
“-”
“-”字符被用來指定一個范圍。如:“10-12”在小時域意味著“10點、11點、12點”。
“,”
“,”字符被用來指定另外的值。如:“MON,WED,FRI”在星期域里表示”星期一、星期三、星期五”。
“/”
“/”字符用于指定增量。如:“0/15”在秒域意思是每分鐘的0,15,30和45秒。“5/15”在分鐘域表示每小時的5,20,35和50。符號“*”在“/”前面(如:*/10)等價于0在“/”前面(如:0/10)。記住一條本質:表達式的每個數值域都是一個有最大值和最小值的集合,如:秒域和分鐘域的集合是0-59,日期域是1-31,月份域是1-12。字符“/”可以幫助你在每個字符域中取相應的數值。如:“7/6”在月份域的時候只有當7月的時候才會觸發,并不是表示每個6月。
“W”
字符“W”只允許日期域出現。這個字符用于指定日期的最近工作日。例如:如果你在日期域中寫“15W”,表示:這個月15號最近的工作日。所以,如果15號是周六,則任務會在14號觸發。如果15號是周日,則任務會在周一也就是16號觸發。
“#”
字符“#”只允許在星期域中出現。這個字符用于指定本月的某某天。例如:“6#3”表示本月第三周的星期五(6表示星期五,3表示第三周)。
“C”
字符“C”允許在日期域和星期域出現。這個字符依靠一個指定的“日歷”。也就是說這個表達式的值依賴于相關的“日歷”的計算結果,如果沒有“日歷”關聯,則等價于所有包含的“日歷”。如:日期域是“5C”表示關聯“日歷”中第一天,或者這個月開始的第一天的后5天。星期域是“1C”表示關聯“日歷”中第一天,或者星期的第一天的后1天,也就是周日的后一天(周一)。