一、前言
1睦袖、什么是分布式任務(wù)調(diào)度
任務(wù)調(diào)度是指基于給定的時間點(diǎn)烹棉,給定的時間間隔或者給定執(zhí)行次數(shù)自動的執(zhí)行任務(wù)攒霹。任務(wù)調(diào)度是是操作系統(tǒng)的重要組成部分,而對于實(shí)時的操作系統(tǒng)浆洗,任務(wù)調(diào)度直接影響著操作系統(tǒng)的實(shí)時性能催束。任務(wù)調(diào)度涉及到多線程并發(fā)、運(yùn)行時間規(guī)則定制及解析伏社、線程池的維護(hù)等諸多方面的工作抠刺。
WEB服務(wù)器在接受請求時,會創(chuàng)建一個新的線程服務(wù)摘昌。但是資源有限速妖,必須對資源進(jìn)行控制,首先就是限制服務(wù)線程的最大數(shù)目聪黎,其次考慮以線程池共享服務(wù)的線程資源罕容,降低頻繁創(chuàng)建、銷毀線程的消耗;然后任務(wù)調(diào)度信息的存儲包括運(yùn)行次數(shù)锦秒、調(diào)度規(guī)則以及運(yùn)行數(shù)據(jù)等露泊。一個合適的任務(wù)調(diào)度框架對于項(xiàng)目的整體性能來說顯得尤為重要。
2旅择、常見的任務(wù)調(diào)度框架有哪些惭笑?
我們在實(shí)際的開發(fā)工作中,或多或少的都會用到任務(wù)調(diào)度這個功能生真。常見的分布式任務(wù)調(diào)度框架有:cronsun沉噩、Elastic-job、saturn柱蟀、lts川蒙、TBSchedule、xxl-job长已、Quartz等派歌。
二、XXL-JOB
xxl-job是一個輕量級的分布式任務(wù)調(diào)度框架痰哨,其核心設(shè)計(jì)目標(biāo)是開發(fā)迅速、學(xué)習(xí)簡單匾嘱、輕量級斤斧、易擴(kuò)展。
xxl-job的設(shè)計(jì)思想為:
1霎烙、將調(diào)度行為抽象形成“調(diào)度中心”公共平臺撬讽,而平臺自身并不承擔(dān)業(yè)務(wù)邏輯,“調(diào)度中心”負(fù)責(zé)發(fā)起調(diào)度請求
2悬垃、將任務(wù)抽象成分散的JobHandler游昼,交由執(zhí)行器統(tǒng)一管理,執(zhí)行器負(fù)責(zé)接收調(diào)度請求并執(zhí)行對應(yīng)的JobHandler中業(yè)務(wù)邏輯
因此尝蠕,“調(diào)度”和“任務(wù)”可以互相解偶烘豌,提高系統(tǒng)整體的穩(wěn)定性和擴(kuò)展性。
xxl-job系統(tǒng)的組成分為:
1看彼、調(diào)度模塊(調(diào)度中心):負(fù)責(zé)管理調(diào)度信息廊佩,按照調(diào)度配置發(fā)出調(diào)度請求,自身不承擔(dān)業(yè)務(wù)代碼靖榕。調(diào)度系統(tǒng)與任務(wù)解耦标锄,提高了系統(tǒng)可用性和穩(wěn)定性,同時調(diào)度系統(tǒng)性能不再受限于任務(wù)模塊茁计;支持可視化料皇、簡單且動態(tài)的管理調(diào)度信息,包括任務(wù)新建,更新践剂,刪除鬼譬,GLUE開發(fā)和任務(wù)報(bào)警等,所有上述操作都會實(shí)時生效舷手,同時支持監(jiān)控調(diào)度結(jié)果以及執(zhí)行日志拧簸,支持執(zhí)行器Failover。
2男窟、執(zhí)行模塊(執(zhí)行器):負(fù)責(zé)接收調(diào)度請求并執(zhí)行任務(wù)邏輯盆赤。任務(wù)模塊專注于任務(wù)的執(zhí)行等操作,開發(fā)和維護(hù)更加簡單和高效歉眷;接收“調(diào)度中心”的執(zhí)行請求牺六、終止請求和日志請求等。
xxl-job有下面一些特點(diǎn):
簡單:支持通過Web頁面對任務(wù)進(jìn)行CRUD操作汗捡,操作簡單淑际,一分鐘上手;
動態(tài):支持動態(tài)修改任務(wù)狀態(tài)扇住、啟動/停止任務(wù)春缕,以及終止運(yùn)行中任務(wù),即時生效艘蹋;
調(diào)度中心HA(中心式):調(diào)度采用中心式設(shè)計(jì)锄贼,“調(diào)度中心”自研調(diào)度組件并支持集群部署,可保證調(diào)度中心HA女阀;
執(zhí)行器HA(分布式):任務(wù)分布式執(zhí)行宅荤,任務(wù)"執(zhí)行器"支持集群部署,可保證任務(wù)執(zhí)行HA浸策;
注冊中心: 執(zhí)行器會周期性自動注冊任務(wù), 調(diào)度中心將會自動發(fā)現(xiàn)注冊的任務(wù)并觸發(fā)執(zhí)行冯键。同時,也支持手動錄入執(zhí)行器地址庸汗;
彈性擴(kuò)容縮容:一旦有新執(zhí)行器機(jī)器上線或者下線惫确,下次調(diào)度時將會重新分配任務(wù);
路由策略:執(zhí)行器集群部署時提供豐富的路由策略夫晌,包括:第一個雕薪、最后一個、輪詢晓淀、隨機(jī)所袁、一致性HASH、最不經(jīng)常使用凶掰、最近最久未使用燥爷、故障轉(zhuǎn)移蜈亩、忙碌轉(zhuǎn)移等;
故障轉(zhuǎn)移:任務(wù)路由策略選擇"故障轉(zhuǎn)移"情況下前翎,如果執(zhí)行器集群中某一臺機(jī)器故障稚配,將會自動Failover切換到一臺正常的執(zhí)行器發(fā)送調(diào)度請求。
阻塞處理策略:調(diào)度過于密集執(zhí)行器來不及處理時的處理策略港华,策略包括:單機(jī)串行(默認(rèn))道川、丟棄后續(xù)調(diào)度、覆蓋之前調(diào)度立宜;
事件觸發(fā):除了"Cron方式"和"任務(wù)依賴方式"觸發(fā)任務(wù)執(zhí)行之外冒萄,支持基于事件的觸發(fā)任務(wù)方式。調(diào)度中心提供觸發(fā)任務(wù)單次執(zhí)行的API服務(wù)橙数,可根據(jù)業(yè)務(wù)事件靈活觸發(fā)尊流。
任務(wù)進(jìn)度監(jiān)控:支持實(shí)時監(jiān)控任務(wù)進(jìn)度;
Rolling實(shí)時日志:支持在線查看調(diào)度結(jié)果灯帮,并且支持以Rolling方式實(shí)時查看執(zhí)行器輸出的完整的執(zhí)行日志
分布式任務(wù)調(diào)度平臺XXL-JOB (xuxueli.com)
三崖技、使用xxl-job分布式定時任務(wù)
3.1 初始化數(shù)據(jù)庫
請下載項(xiàng)目源碼并解壓,獲取 “調(diào)度數(shù)據(jù)庫初始化SQL腳本” 并執(zhí)行即可钟哥。
Github地址: https://github.com/xuxueli/xxl-job
碼云地址:http://gitee.com/xuxueli0323/xxl-job
調(diào)度數(shù)據(jù)庫初始化SQL腳本” 位置為:
/xxl-job/doc/db/tables_xxl_job.sql
調(diào)度中心支持集群部署迎献,集群情況下各節(jié)點(diǎn)務(wù)必連接同一個mysql實(shí)例;
如果mysql做主從,調(diào)度中心集群節(jié)點(diǎn)務(wù)必強(qiáng)制走主庫;
3.2 部署調(diào)度中心
3.2.1 將下載的的xxl-job項(xiàng)目導(dǎo)入到IDEA中
xxl-job
doc SQL腳本
xxl-job-admin:調(diào)度中心
xxl-job-core:公共依賴
xxl-job-executor-samples:執(zhí)行器Sample示例(選擇合適的版本執(zhí)行器腻贰,可直接使用忿晕,也可以參考其并將現(xiàn)有項(xiàng)目改造成執(zhí)行器)
:xxl-job-executor-sample-springboot:Springboot版本,通過Springboot管理執(zhí)行器银受,推薦這種方式;
:xxl-job-executor-sample-frameless:無框架版本鸦采;
pom.xml
3.2.2 配置調(diào)度中心宾巍,主要配置調(diào)度中心的數(shù)據(jù)源
server.port=9990
server.servlet.context-path=/xxl-job-admin
### 調(diào)度中心JDBC鏈接,就是剛才創(chuàng)建的數(shù)據(jù)庫
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_pwd
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
### 報(bào)警郵箱
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
### 調(diào)度中心通訊TOKEN [選填]:非空時啟用渔伯;
xxl.job.accessToken=
### 調(diào)度中心國際化配置 [必填]: 默認(rèn)為 "zh_CN"/中文簡體, 可選范圍為 "zh_CN"/中文簡體, "zh_TC"/中文繁體 and "en"/英文顶霞;
xxl.job.i18n=zh_CN
## 調(diào)度線程池最大線程配置【必填】
xxl.job.triggerpool.fast.max=200
xxl.job.triggerpool.slow.max=100
### 調(diào)度中心日志表數(shù)據(jù)保存天數(shù) [必填]:過期日志自動清理;限制大于等于7時生效锣吼,否則, 如-1选浑,關(guān)閉自動清理功能;
xxl.job.logretentiondays=30
如果已經(jīng)正確進(jìn)行上述配置玄叠,可將 xxl-job-admin 項(xiàng)目編譯打包部署古徒。
調(diào)度中心訪問地址:http://localhost:8080/xxl-job-admin (該地址執(zhí)行器將會使用到,作為回調(diào)地址)
默認(rèn)登錄賬號 “admin/123456”, 登錄后運(yùn)行界面如下圖所示读恃。
調(diào)度中心支持集群部署隧膘,提升調(diào)度系統(tǒng)容災(zāi)和可用性代态。
調(diào)度中心集群部署時初斑,幾點(diǎn)要求和建議:
DB配置保持一致甫菠;
集群機(jī)器時鐘保持一致(單機(jī)集群忽視);
建議:推薦通過nginx為調(diào)度中心集群做負(fù)載均衡思犁,分配域名萨驶。調(diào)度中心訪問歉摧、執(zhí)行器回調(diào)配置、調(diào)用API服務(wù)等操作均通過該域名進(jìn)行腔呜。
3.3 創(chuàng)建執(zhí)行器項(xiàng)目
創(chuàng)建一個SpringBoot項(xiàng)目叁温,加入xxl-job-core” 的maven依賴
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
<version>2.3.0</version>
</dependency>
3.3.1 添加配置
server:
port: 8081
xxl:
job:
# 執(zhí)行器通訊TOKEN [選填]:非空時啟用;
accessToken:
# 調(diào)度中心部署跟地址 [選填]:如調(diào)度中心集群部署存在多個地址則用逗號分隔育谬。
#執(zhí)行器將會使用該地址進(jìn)行"執(zhí)行器心跳注冊"和"任務(wù)結(jié)果回調(diào)"券盅;為空則關(guān)閉自動注冊;
admin:
addresses: http://127.0.0.1:9990/xxl-job-admin
executor:
# 執(zhí)行器IP [選填]:默認(rèn)為空表示自動獲取IP膛檀,
# 多網(wǎng)卡時可手動設(shè)置指定IP锰镀,該IP不會綁定Host僅作為通訊實(shí)用;
# 地址信息用于 "執(zhí)行器注冊" 和 "調(diào)度中心請求并觸發(fā)任務(wù)"咖刃;
ip:
# 執(zhí)行器端口號 [選填]:小于等于0則自動獲扔韭;默認(rèn)端口為9999嚎杨,單機(jī)部署多個執(zhí)行器時花鹅,注意要配置不同執(zhí)行器端口;
port: 9999
# 執(zhí)行器注冊 [選填]:優(yōu)先使用該配置作為注冊地址枫浙,為空時使用內(nèi)嵌服務(wù) ”IP:PORT“ 作為注冊地址刨肃。從而更靈活的支持容器類型執(zhí)行器動態(tài)IP和動態(tài)映射端口問題。
address:
# 執(zhí)行器AppName [選填]:執(zhí)行器心跳注冊分組依據(jù)箩帚;為空則關(guān)閉自動注冊
appname: xxl-job-demo
# 執(zhí)行器運(yùn)行日志文件存儲磁盤路徑 [選填] :需要對該路徑擁有讀寫權(quán)限真友;為空則使用默認(rèn)路徑;
logpath: E:/log/xxl-job-demo
# 執(zhí)行器日志文件保存天數(shù) [選填] : 過期日志自動清理, 限制值大于等于3時生效; 否則, 如-1, 關(guān)閉自動清理功能紧帕;
logretentiondays: 30
3.3.2 配置執(zhí)行器組件
@Configuration
public class XxlJobConfig {
private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class);
@Value("${xxl.job.admin.addresses}")
private String adminAddresses;
@Value("${xxl.job.accessToken}")
private String accessToken;
@Value("${xxl.job.executor.appname}")
private String appname;
@Value("${xxl.job.executor.address}")
private String address;
@Value("${xxl.job.executor.ip}")
private String ip;
@Value("${xxl.job.executor.port}")
private int port;
@Value("${xxl.job.executor.logpath}")
private String logPath;
@Value("${xxl.job.executor.logretentiondays}")
private int logRetentionDays;
@Bean
public XxlJobSpringExecutor xxlJobExecutor() {
logger.info(">>>>>>>>>>> xxl-job config init.");
XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
xxlJobSpringExecutor.setAppname(appname);
xxlJobSpringExecutor.setAddress(address);
xxlJobSpringExecutor.setIp(ip);
xxlJobSpringExecutor.setPort(port);
xxlJobSpringExecutor.setAccessToken(accessToken);
xxlJobSpringExecutor.setLogPath(logPath);
xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);
return xxlJobSpringExecutor;
}
/**
* 針對多網(wǎng)卡盔然、容器內(nèi)部署等情況,可借助 "spring-cloud-commons" 提供的 "InetUtils" 組件靈活定制注冊IP是嗜;
*
* 1愈案、引入依賴:
* <dependency>
* <groupId>org.springframework.cloud</groupId>
* <artifactId>spring-cloud-commons</artifactId>
* <version>${version}</version>
* </dependency>
*
* 2、配置文件鹅搪,或者容器啟動變量
* spring.cloud.inetutils.preferred-networks: 'xxx.xxx.xxx.'
*
* 3站绪、獲取IP
* String ip_ = inetUtils.findFirstNonLoopbackHostInfo().getIpAddress();
*/
}
3.3.3 開發(fā)第一個任務(wù)
@Slf4j
@Component
public class TestJobHandler {
@XxlJob("productJobHandler")
public void productJobHandler() throws Exception {
log.info("test xxl-job productJobHandler....");
}
}
接下來去調(diào)度中心 添加執(zhí)行器,配置執(zhí)行器任務(wù)的觸發(fā)時間丽柿,打開調(diào)度中心 http://localhost:9990/xxl-job-admin/
點(diǎn)擊左側(cè)導(dǎo)航欄的 執(zhí)行器管理 新增
AppName就是剛才在執(zhí)行器項(xiàng)目中配置的執(zhí)行器AppName崇众,注冊方式選擇 自動注冊
添加任務(wù)
點(diǎn)擊左側(cè)導(dǎo)航欄的 任務(wù)管理 > 新增掂僵,執(zhí)行器選擇剛才添加的執(zhí)行器,JobHandler就是剛才在執(zhí)行器項(xiàng)目中@XxlJob("productJobHandler")注解中的值
CRON 選擇執(zhí)行的時間顷歌,這里是每米執(zhí)行一次锰蓬,還可以填寫郵箱,任務(wù)執(zhí)行出錯時會發(fā)郵件提醒
執(zhí)行任務(wù)眯漩,點(diǎn)擊剛才添加的這條記錄后面的操作按鈕下拉列表芹扭,啟動
總結(jié):
- bean模式分兩種:
- 一種是類上面,使用@JobHandler(value = "testJobHandler")
- 一種是方法上@XxlJob("testJobHandler")
參考:
分布式任務(wù)調(diào)度平臺XXL-JOB (xuxueli.com)