前言
Github:https://github.com/HealerJean
官方地址:分佈式任務調度平臺XXL-JOB
1、下載部署
1.1、下載
https://github.com/xuxueli/xxl-job
1.2、部署
1.2.1、目錄結構:
xxl-job-admin:調度中心
xxl-job-core:公共依賴
xxl-job-executor-samples:執行器Sample示例(選擇合適的版本執行器,可直接使用,也可以參考其並將現有項目改造成執行器)
:xxl-job-executor-sample-springboot:Springboot版本,通過Springboot管理執行器,推薦這種方式;
:xxl-job-executor-sample-spring:Spring版本,通過Spring容器管理執行器,比較通用;
:xxl-job-executor-sample-frameless:無框架版本;
:xxl-job-executor-sample-jfinal:JFinal版本,通過JFinal管理執行器;
:xxl-job-executor-sample-nutz:Nutz版本,通過Nutz管理執行器;
:xxl-job-executor-sample-jboot:jboot版本,通過jboot管理執行器;
1.2、SpringBoot選擇
除了SpringBoot,其他的對我來說沒有用,刪掉其他的,我只保留的SpringBoot
1.2.1、調度中心
統一管理任務調度平臺上調度任務,負責觸發調度執行,並且提供任務管理平臺。
1.2.1.1、properties
### web
server.port=8080
server.servlet.context-path=/xxl-job-admin
### actuator
management.server.servlet.context-path=/actuator
management.health.mail.enabled=false
### resources
spring.mvc.servlet.load-on-startup=0
spring.mvc.static-path-pattern=/static/**
spring.resources.static-locations=classpath:/static/
### freemarker
spring.freemarker.templateLoaderPath=classpath:/templates/
spring.freemarker.suffix=.ftl
spring.freemarker.charset=UTF-8
spring.freemarker.request-context-attribute=request
spring.freemarker.settings.number_format=0.##########
### mybatis
mybatis.mapper-locations=classpath:/mybatis-mapper/*Mapper.xml
#mybatis.type-aliases-package=com.xxl.job.admin.core.model
### datasource-pool
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.hikari.minimum-idle=10
spring.datasource.hikari.maximum-pool-size=30
spring.datasource.hikari.auto-commit=true
spring.datasource.hikari.idle-timeout=30000
spring.datasource.hikari.pool-name=HikariCP
spring.datasource.hikari.max-lifetime=900000
spring.datasource.hikari.connection-timeout=10000
spring.datasource.hikari.connection-test-query=SELECT 1
### 調度中心JDBC鏈接:鏈接地址請保持和 2.1章節 所創建的調度數據庫的地址一致
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/xxl_job?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
### 報警郵箱
spring.mail.host=smtp.163.com
spring.mail.port=25
[email protected]
spring.mail.password=Zhangyj..123
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory
### 調度中心通訊TOKEN [選填]:非空時啓用;
xxl.job.accessToken=
### 調度中心國際化配置 [必填]: 默認爲 "zh_CN"/中文簡體, 可選範圍爲 "zh_CN"/中文簡體, "zh_TC"/中文繁體 and "en"/英文;
xxl.job.i18n=zh_CN
## 調度線程池最大線程配置【必填】
xxl.job.triggerpool.fast.max=200
xxl.job.triggerpool.slow.max=100
### 調度中心日誌表數據保存天數 [必填]:過期日誌自動清理;限制大於等於7時生效,否則, 如-1,關閉自動清理功能;
xxl.job.logretentiondays=30
1.2.2:執行器項目
作用:負責接收“調度中心”的調度並執行;可直接部署執行器,也可以將執行器集成到現有業務項目中。
12.2.1、properties
# web port
server.port=8081
# no web
#spring.main.web-environment=false
# log config
logging.config=classpath:logback.xml
### 調度中心部署跟地址 [選填]:
# 如調度中心集羣部署存在多個地址則用逗號分隔。執行器將會使用該地址進行"執行器心跳註冊"和"任務結果回調";爲空則關閉自動註冊;
xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin
### 執行器通訊TOKEN [選填]:非空時啓用;XxlJobConfig
xxl.job.accessToken=
### 執行器AppName [選填]:執行器心跳註冊分組依據;爲空則關閉自動註冊
xxl.job.executor.appname=xxl-job-executor-sample
### 執行器註冊 [選填]:優先使用該配置作爲註冊地址,爲空時使用內嵌服務 ”IP:PORT“ 作爲註冊地址。從而更靈活的支持容器類型執行器動態IP和動態映射端口問題。
xxl.job.executor.address=
### 執行器IP [選填]:默認爲空表示自動獲取IP,多網卡時可手動設置指定IP,該IP不會綁定Host僅作爲通訊實用;地址信息用於 "執行器註冊" 和 "調度中心請求並觸發任務";
xxl.job.executor.ip=
### 執行器端口號 [選填]:小於等於0則自動獲取;默認端口爲9999,單機部署多個執行器時,注意要配置不同執行器端口;
# 這裏相當的重要,和上面應用的端口不同,也就是執行器通過下面的端口進行服務
xxl.job.executor.port=9999
### 執行器運行日誌文件存儲磁盤路徑 [選填] :需要對該路徑擁有讀寫權限;爲空則使用默認路徑;
xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler
### 執行器日誌文件保存天數 [選填] : 過期日誌自動清理, 限制值大於等於3時生效; 否則, 如-1, 關閉自動清理功能;
xxl.job.executor.logretentiondays=30
1.3、啓動:
1.3.1、啓動調度中心:xxl-job-admin
http://127.0.0.1:8080//xxl-job-admin
“admin/123456
2、定時器介紹
2.1、配置屬性
2.1.1、執行器
任務的綁定的執行器,任務觸發調度時將會自動發現註冊成功的執行器, 實現任務自動發現功能; 另一方面也可以方便的進行任務分組。每個任務必須綁定一個執行器, 可在 “執行器管理” 進行設置;
2.1.2、 任務描述
任務的描述信息,便於任務管理;
2.1.3、路由策略
當執行器集羣部署時,提供豐富的路由策略,包括;
FIRST(第一個) | 固定選擇第一個機器; |
LAST(最後一個) | 固定選擇最後一個機器; |
ROUND(輪詢) | |
RANDOM(隨機) | 隨機選擇在線的機器 |
CONSISTENT_HASH(一致性HASH) | 每個任務按照Hash算法固定選擇某一臺機器,且所有任務均勻散列在不同機器上。 |
LEAST_FREQUENTLY_USED(最不經常使用): | 使用頻率最低的機器優先被選舉; |
LEAST_RECENTLY_USED(最近最久未使用) | 最久未使用的機器優先被選舉 |
FAILOVER(故障轉移) | 按照順序依次進行心跳檢測,第一個心跳檢測成功的機器選定爲目標執行器併發起調度; |
BUSYOVER(忙碌轉移) | 按照順序依次進行空閒檢測,第一個空閒檢測成功的機器選定爲目標執行器併發起調度; |
SHARDING_BROADCAST(分片廣播) | 廣播觸發對應集羣中所有機器執行一次任務,同時系統自動傳遞分片參數;可根據分片參數開發分片任務; |
2.1.4、Cron
觸發任務執行的Cron表達式;
2.1.5、運行模式
BEAN模式 | 任務以JobHandler方式維護在執行器端;需要結合 “JobHandler” 屬性匹配執行器中任務; |
---|---|
GLUE模式 | 任務以源碼方式維護在調度中心;任務以JobHandler方式維護在執行器端;需要結合 “JobHandler” 屬性匹配執行器中任務; |
GLUE模式(Java) | 該模式的任務實際上是一段繼承自IJobHandler的Java類代碼並 “groovy” 源碼方式維護,它在執行器項目中運行,可使用@Resource/@Autowire注入執行器裏中的其他服務; |
GLUE模式(Shell) | 該模式的任務實際上是一段 “shell” 腳本; |
GLUE模式(Python) | 該模式的任務實際上是一段 “python” 腳本; |
GLUE模式(PHP) | 該模式的任務實際上是一段 “php” 腳本; |
GLUE模式(NodeJS) | 該模式的任務實際上是一段 “nodejs” 腳本; |
GLUE模式(PowerShell) | 該模式的任務實際上是一段 “PowerShell” 腳本; |
2.1.6、JobHandler
運行模式爲 “BEAN模式” 時生效,對應執行器中新開發的JobHandler類“@JobHandler”註解自定義的value值;
2.1.7、阻塞處理策略
調度過於密集執行器來不及處理時的處理策略;
如果當前任務還沒執行完成,又來了任務的處理策略 。我們一定要儘可能避免此類情況
阻塞處理策略 | |
---|---|
單機串行(默認) | 調度請求進入單機執行器後,調度請求進入FIFO隊列並以串行方式運行; |
丟棄後續調度 | 調度請求進入單機執行器後,發現執行器存在運行的調度任務,本次請求將會被丟棄並標記爲失敗; |
覆蓋之前調度 | 調度請求進入單機執行器後,發現執行器存在運行的調度任務,將會終止運行中的調度任務並清空隊列,然後運行本地調度任務; |
2.1.9、子任務Id
每個任務都擁有一個唯一的任務ID(任務ID可以從任務列表獲取),當本任務執行結束並且執行成功時,將會觸發子任務ID所對應的任務的一次主動調度。
2.1.10、任務超時時間
支持自定義任務超時時間,任務運行超時將會主動中斷任務,同下面調度日誌裏面的終止任務;
2.1.11、失敗重試次數
支持自定義任務失敗重試次數,當任務失敗時將會按照預設的失敗重試次數主動進行重試;
2.1.12、負責人
任務的負責人;
2.1.13、報警郵件
任務調度失敗時郵件通知的郵箱地址,支持配置多郵箱地址,配置多個郵箱地址時用逗號分隔;
2.1.14、執行參數
任務執行所需的參數
3、BEAN模式
任務以JobHandler方式維護在執行器端;需要結合 “JobHandler” 屬性匹配執行器中任務
3.1、方法形式
3.1.1、執行器項目
package com.xxl.job.executor.service.jobhandler.bean;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.annotation.XxlJob;
import com.xxl.job.core.log.XxlJobLogger;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
/**
* XxlJob開發示例(Bean模式)
* <p>
* 開發步驟:
* 1、在Spring Bean實例中,開發Job方法,方式格式要求爲 "public ReturnT<String> execute(String param)"
* 2、爲Job方法添加註解 "@XxlJob(value="自定義jobhandler名稱", init = "JobHandler初始化方法", destroy = "JobHandler銷燬方法")",註解value值對應的是調度中心新建任務的JobHandler屬性的值。
* 3、執行日誌:需要通過 "XxlJobLogger.log" 打印執行日誌;
*/
@Component
@Slf4j
public class BeanMethodXxlJob {
/**
* 1、簡單任務示例(Bean模式)
*/
@XxlJob("demoJobHandler")
public ReturnT<String> demoJobHandler(String param) throws Exception {
log.info("任務【demoJobHandler】開始執行, 請求參數:{}", param);
//任務調度器日誌
XxlJobLogger.log("XXL-JOB, 請求參數:{}", param);
return ReturnT.SUCCESS;
}
/**
* 2、生命週期任務示例:任務初始化與銷燬時,支持自定義相關邏輯;
*/
@XxlJob(value = "demoJobHandler2", init = "init", destroy = "destroy")
public ReturnT<String> demoJobHandler2(String param) throws Exception {
log.info("任務【demoJobHandler2】開始執行, 請求參數:{}", param);
//任務調度器日誌
XxlJobLogger.log("XXL-JOB, Hello World.");
return ReturnT.SUCCESS;
}
public void init() {
log.info("任務【demoJobHandler2】開始執行 init");
}
public void destroy() {
log.info("任務【demoJobHandler2】開始執行 destroy");
}
}
3.1.2、調度中心頁面操作
3.1.2.1、demoJobHandler
0 */1 * * * ? 每分鐘執行一次
3.1.2.2、demoJobHandler2
4、GLUE(java)模式
任務以源碼方式維護在調度中心;該模式的任務實際上是一段繼承自IJobHandler的Java類代碼並 “groovy” 源碼方式維護,它在執行器項目中運行,可使用@Resource/@Autowire注入執行器裏中的其他服務;
4.1、GLUE模式(Java)
4.1.1、glueJobHandle
4.1.1.1、創建
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-jp2MWFgF-1591086758306)(https://raw.githubusercontent.com/HealerJean/HealerJean.github.io/master/blogImages/image-20200514173938394.png)]
package com.xxl.job.service.handler;
import com.xxl.job.core.log.XxlJobLogger;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.IJobHandler;
public class DemoGlueJobHandler extends IJobHandler {
@Override
public ReturnT<String> execute(String param) throws Exception {
XxlJobLogger.log("GlueJob 請求參數:{}", param);
return ReturnT.SUCCESS;
}
}
4.1.1.2、查看日誌
2020-05-14 17:41:57 [com.xxl.job.core.thread.JobThread#run]-[124]-[Thread-19]
----------- xxl-job job execute start -----------
----------- Param:HealerJean
2020-05-14 17:41:57 [com.xxl.job.core.handler.impl.GlueJobHandler#execute]-[26]-[Thread-19] ----------- glue.version:1589449244000 -----------
2020-05-14 17:41:57 [sun.reflect.NativeMethodAccessorImpl#invoke0]-[-2]-[Thread-19] GlueJob 請求參數:HealerJean
2020-05-14 17:41:57 [com.xxl.job.core.thread.JobThread#run]-[164]-[Thread-19]
----------- xxl-job job execute end(finish) -----------
----------- ReturnT:ReturnT [code=200, msg=null, content=null]
2020-05-14 17:41:57 [com.xxl.job.core.thread.TriggerCallbackThread#callbackLog]-[191]-[xxl-job, executor TriggerCallbackThread]
----------- xxl-job job callback finish.
[Load Log Finish]
5、操作指南
5.1、執行器管理
AppName: 是每個執行器集羣的唯一標示AppName, 執行器會週期性以AppName爲對象進行自動註冊。可通過該配置自動發現註冊成功的執行器, 供任務調度時使用;
名稱:執行器的名稱, 因爲AppName限制字母數字等組成,可讀性不強, 名稱爲了提高執行器的可讀性;
排序:執行器的排序, 系統中需要執行器的地方,如任務新增, 將會按照該排序讀取可用的執行器列表;
註冊方式:調度中心獲取執行器地址的方式
1、自動註冊:執行器自動進行執行器註冊,調度中心通過底層註冊表可以動態發現執行器機器地址
2、手動錄入:人工手動錄入執行器的地址信息,多地址逗號分隔,供調度中心使用;
機器地址:"註冊方式"爲"手動錄入"時有效,支持人工維護執行器的地址信息;`
5.2、調度日誌
調度時間:"調度中心"觸發本次調度並向"執行器"發送任務執行信號的時間;
調度結果:"調度中心"觸發本次調度的結果,200表示成功,500或其他表示失敗;
調度備註:"調度中心"觸發本次調度的日誌信息;
任務觸發類型:失敗重試觸發
調度機器:10.236.150.223
執行器-註冊方式:自動註冊
執行器-地址列表:[http://10.236.150.223:9999/]
路由策略:第一個
阻塞處理策略:單機串行
任務超時時間:0
失敗重試次數:3
>>>>>>>>>>>觸發調度<<<<<<<<<<<
觸發調度:
address:http://10.236.150.223:9999/
code:200
msg:null
執行時間:"執行器"中本次任務執行結束後回調的時間;
執行結果:"執行器"中本次任務執行的結果,200表示成功,500或其他表示失敗;
執行備註:"執行器"中本次任務執行的日誌信息
操作:
1、"執行日誌"按鈕:點擊可查看本地任務執行的詳細日誌信息;詳見“4.8 查看執行日誌”;
2、"終止任務"按鈕:僅針對執行中的任務。在任務日誌界面,點擊右側的“終止任務”按鈕,將會向本次任務對應的執行器發送任務終止請求,將會終止掉本次任務,同時會清空掉整個任務執行隊列。
任務終止時通過 “interrupt
” 執行線程的方式實現, 將會觸發 “InterruptedException
” 異常。因此如果JobHandler
內部catch
到了該異常並消化掉的話, 任務終止功能將不可用。
因此, 如果遇到上述任務終止不可用的情況, 需要在JobHandler中應該針對 “InterruptedException” 異常進行特殊處理 (向上拋出) , 正確邏輯如下:
try{
// do something
} catch (Exception e) {
if (e instanceof InterruptedException) {
throw e;
}
logger.warn("{}", e);
}
而且,在JobHandler中開啓子線程時,子線程也不可catch處理”InterruptedException”,應該主動向上拋出。
任務終止時會執行對應JobHandler的”destroy()”方法,可以藉助該方法處理一些資源回收的邏輯。
5.3、用戶管理
管理員:擁有全量權限,支持在線管理用戶信息,爲用戶分配權限,權限分配粒度爲執行器;
普通用戶:僅擁有被分配權限的執行器,及相關任務的操作權限;
6、總體設計
6.1、源碼目錄介紹
- /doc :文檔資料
- /db :“調度數據庫”建表腳本
- /xxl-job-admin :調度中心,項目源碼
- /xxl-job-core :公共Jar依賴
- /xxl-job-executor-samples :執行器,Sample示例項目(大家可以在該項目上進行開發,也可以將現有項目改造生成執行器項目)
6.2、調度數據庫
- xxl_job_lock:任務調度鎖表;
- xxl_job_group:執行器信息表,維護任務執行器信息;
- xxl_job_info:調度擴展信息表: 用於保存XXL-JOB調度任務的擴展信息,如任務分組、任務名、機器地址、執行器、執行入參和報警郵件等等;
- xxl_job_log:調度日誌表: 用於保存XXL-JOB任務調度的歷史信息,如調度結果、執行結果、調度入參、調度機器和執行器等等;
- xxl_job_log_report:調度日誌報表:用戶存儲XXL-JOB任務調度日誌的報表,調度中心報表功能頁面會用到;
- xxl_job_logglue:任務GLUE日誌:用於保存GLUE更新歷史,用於支持GLUE的版本回溯功能;
- xxl_job_registry:執行器註冊表,維護在線的執行器和調度中心機器地址信息;
- xxl_job_user:系統用戶表;
7、quartz的不足
問題一:調用API的的方式操作任務,不人性化;
問題二:需要持久化業務QuartzJobBean到底層數據表中,系統侵入性相當嚴重。
問題三:調度邏輯和QuartzJobBean耦合在同一個項目中,這將導致一個問題,在調度任務數量逐漸增多,同時調度任務邏輯逐漸加重的情況下,此時調度系統的性能將大大受限於業務;
問題四:quartz底層以“搶佔式”獲取DB鎖並由搶佔成功節點負責運行任務,會導致節點負載懸殊非常大;而XXL-JOB通過執行器實現“協同分配式”運行任務(其實也是樂觀鎖獲取任務),充分發揮集羣優勢,負載各節點均衡。
主要還是入侵比較嚴重吧。而且分佈式用XXLJob,更好,可以給多個分佈式系統節點提供服務