一、前言
1、什么是XXLJob?
xxl-job是一個分布式的任務調度平臺,他的優點是上手簡單,開發迅速,開箱即用,也是個輕量級的任務調度平臺。
xxl-job框架主要用于處理分布式的定時任務,其主要由調度中心和執行器組成。
- 調度模塊(調度中心):
負責管理調度信息,按照調度配置發出調度請求,自身不承擔業務代碼。調度系統與任務解耦,提高了系統可用性和穩定性,同時調度系統性能不再受限于任務模塊;
支持可視化、簡單且動態的管理調度信息,包括任務新建,更新,刪除,GLUE開發和任務報警等,所有上述操作都會實時生效,同時支持監控調度結果以及執行日志,支持執行器Failover。 - 執行模塊(執行器):
負責接收調度請求并執行任務邏輯。任務模塊專注于任務的執行等操作,開發和維護更加簡單和高效;
接收“調度中心”的執行請求、終止請求和日志請求等。

2、XXLJob的原理
執行器的注冊與發現
執行器的注冊發現主要是關系兩張表:
xxl_job_registry:執行器的實例表,保存實例信息和心跳信息。
xxl_job_group:每個服務注冊的實例表。
執行器啟動線程每隔30秒向注冊表xxl_job_registry請求一次,更新執行器的心跳信息,調度中心啟動線程每隔30秒檢測一次xxl_job_registry,將超過90秒還沒有收到心跳的實例信息從xxl_job_registry刪除,并更新xxl_job_group服務的實例列表信息。
調度中心調用執行器
調度中心通過循環不停的:
1、關閉自動提交事務
2、利用mysql的悲觀鎖,其他事務無法進入
select * from xxl_job_lock where lock_name = 'schedule_lock' for update
3、讀取數據庫中的xxl_job_info:記錄定時任務的相關信息,該表中有trigger_next_time字段表示下一次任務的觸發時間。拿到距離當前時間5s內的任務列表,分為三種情況處理:
- 對于當前時間-任務的下一次觸發時間>5,直接調過不執行,重置trigger_next_time的時間。(超過5s)
- 對于任務的下一次觸發時間<當前時間<任務的下一次觸發時間+5的任務(不超過5s的):
- 開線程處理執行觸發邏輯,根據當前時間更新下一次任務觸發時間
- 如果新的任務下一次觸發時間-當前時間<5,放到時間輪中,時間輪是一個map:
private volatile static Map<Integer, List> ringData = new ConcurrentHashMap<>(); - 根據新的任務下一次觸發時間更新下下一次任務觸發時間
- 對于任務的下一次觸發時間>當前時間,將其放入時間輪中,根據任務下一次觸發時間更新下下一次任務觸發時間
4、commit提交事務,同時釋放排他鎖
執行器的操作:
1、執行器接收到調度中心的調度信息,將調度信息放到對應的任務的等待隊列中
2、執行器的任務處理線程從任務隊列中取出調度信息,執行業務邏輯,將結果放入一個公共的等待隊列中(每個任務都有一個單獨的處理線程和等待隊列,任務信息放入該隊列中)
3、執行器有一個專門的回調線程定時批量從結果隊列中取出任務結果,并且回調告知調度中心
3、XXLJob和quartz的對比
quartz采用api的方式調用任務,不方便,但是xxl-job使用的是管理界面。
quartz比xxl-job代碼侵入更強
quartz調度邏輯和QuartzJobBean耦合在一個項目中,當任務增多,邏輯復雜的時候,性能會受到影響
quartz底層以搶占式獲取db鎖并且由搶占成功的節點運行,導致節點負載懸殊非常大;xxl-job通過執行器實現協同分配式運行任務,各個節點比較均衡。
二、操作
2、如何使用
準備階段
源碼倉庫地址:https://github.com/xuxueli/xxl-job
中央倉庫地址:
<!-- http://repo1.maven.org/maven2/com/xuxueli/xxl-job-core/ -->
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
<version>${最新穩定版本}</version>
</dependency>
快速入門
解壓,idea打開后,發現目錄結構是這樣的:

1)、文件介紹:
doc :文檔資料
xxl-job-admin :調度中心,項目源碼
xxl-job-core :公共Jar依賴
xxl-job-executor-samples :執行器,Sample示例項目(大家可以在該項目上進行開發,也可以將現有項目改造生成執行器項目)
2)、初始化數據庫,運行doc/db/tables_xxl_job.sql中的sql生成數據庫和表,如圖(注釋是沒有的,我根據自己的理解加上去的):

數據庫中表介紹:
- xxl_job_group:執行器信息表,維護任務執行器信息;
- xxl_job_info:調度擴展信息表: 用于保存XXL-JOB調度任務的擴展信息,如任務分組、任務名、機器地址、執行器、執行入參和報警郵件等等;
- xxl_job_lock:任務調度鎖表;
- xxl_job_log:調度日志表: 用于保存XXL-JOB任務調度的歷史信息,如調度結果、執行結果、調度入參、調度機器和執行器等等;
- xxl_job_log_report:調度日志報表:用戶存儲XXL-JOB任務調度日志的報表,調度中心報表功能頁面會用到;
- xxl_job_logglue:任務GLUE日志:用于保存GLUE更新歷史,用于支持GLUE的版本回溯功能;
- xxl_job_registry:執行器注冊表,維護在線的執行器和調度中心機器地址信息;
- xxl_job_user:系統用戶表;
3)、調度中心配置及部署
調度中心配置文件地址:/xxl-job/xxl-job-admin/src/main/resources/application.properties
### 調度中心JDBC鏈接
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=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
### 報警郵箱
spring.mail.host=smtp.qq.com
spring.mail.port=25
spring.mail.username=xxx@qq.com
spring.mail.password=xxx
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
4)、啟動xxl-job-admin

調度中心訪問地址:http://localhost:8080/xxl-job-admin ,默認登錄賬號 “admin/123456”, 登錄后運行界面如下圖所示。

5)、執行器配置及部署
pom中jar包的引入:
<!-- xxl-job-core -->
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
<version>${project.parent.version}</version>
</dependency>
執行器配置及說明
### 調度中心部署根地址 [選填]:如調度中心集群部署存在多個地址則用逗號分隔。執行器將會使用該地址進行"執行器心跳注冊"和"任務結果回調";為空則關閉自動注冊;
xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin
### 執行器通訊TOKEN [選填]:非空時啟用;
xxl.job.accessToken=
### 執行器AppName [選填]:執行器心跳注冊分組依據;為空則關閉自動注冊
xxl.job.executor.appname=xxl-job-demo
### 執行器注冊 [選填]:優先使用該配置作為注冊地址,為空時使用內嵌服務 ”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
執行器中的XxlJobConfig將根據配置文件中配置生成XxlJobSpringExecutor:
@Bean
public XxlJobSpringExecutor xxlJobExecutor() {
logger.info(">>>>>>>>>>> xxl-job config init.");
XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
xxlJobSpringExecutor.setAppname(appname);
xxlJobSpringExecutor.setIp(ip);
xxlJobSpringExecutor.setPort(port);
xxlJobSpringExecutor.setAccessToken(accessToken);
xxlJobSpringExecutor.setLogPath(logPath);
xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);
return xxlJobSpringExecutor;
}
6)、定時任務編寫**
在項目中集成xxl-job-core 依賴之后,在指定的包下創建一個job類,使用XxlJob注解將該方法標注成定時方法。如圖(不要忘了加上@Component):

7)、在調度中心任務管理中添加調度任務**

從上到下解釋:
Cron:Cron表達式,來定義任務什么時候執行,表達式不熟悉的這里也有表達式生成器。

運行模式:運行模式主要分為 Bean模式以及方法模式。Bean模式主要是以jobHandler方式維護在執行器端;需要結合JobHandler屬性匹配執行器中的任務。
方法模式:為Job方法添加注解 “@XxlJob(value=“自定義jobhandler名稱”, init = “JobHandler初始化方法”, destroy = “JobHandler銷毀方法”)”,注解value值對應的是調度中心新建任務的JobHandler屬性的值

JobHandler:當選的是Bean模式時才會讓填,主要是填你的執行方法名。
任務參數:當你的定時方法需要傳參時,就可以在這里進行傳參。沒有可不填。
三、小結
xxl-job給我的感覺就是很小,因為他真的沒有什么復雜的東西在里面,學習起來很簡單,開發也很簡單。
但是xxl-job也很強大,他會將任務的調度執行,和業務代碼分開,符合我們開發的解耦,代碼入侵很少。
另外,本文參考:https://blog.csdn.net/weixin_44713306/article/details/127751024
浙公網安備 33010602011771號