分布式任务调度平台一站式讲解
文章目錄
- 一、傳統的定時任務
- 1. 傳統的定時任務存在那些缺點
- 2. 定時任務集群冪等性問題
- 二、傳統定時任務的實現方案
- 2.1. 多線程
- 2.2. TimeTask
- 2.3. 線程池
- 2.4. SpringBoot注解形式
- 2.5. 基于Quartz
- 三、分布式任務調度平臺架構設計原理
- 3.1. xxl-job項目模塊講解
- 3.2. 最佳實戰
- 3.3. Xxl-job定時任務框架實現原理
- 四、常見面試題
- 4.1. XXL-JOB與ElasticJob區別之間區別
- 4.2. 分布式任務調度分片集群策略原理
- 4.3. 如何保證任務調度平臺高可用問題
XXL開源社區
一、傳統的定時任務
1. 傳統的定時任務存在那些缺點
傳統任務調度存在的缺陷
- 1.業務邏輯與定時任務邏輯放入在同一個Jar包中,如果定時任務邏輯掛了也會影響到業務邏輯;
- 2.如果服務器集群的情況下,可能存在定時任務邏輯會重復觸發執行;
- 3.定時任務執行非常消耗cpu的資源,可能會影響到業務線程的執行
2. 定時任務集群冪等性問題
定時任務集群,如何保證定時任務冪等性問題
如何在集群中,保證我們的定時任務只會觸發一次
- 1.將業務邏輯和定時任務邏輯完全分開部署,實現解耦、只對業務邏輯實現集群,不對我們的定時任務邏輯集群;—定時任務單機版本 缺點無法實現高可用的問題;
- 2.對我們Jar包加上一個開關,項目啟動的時候讀取該開關 如果為true的情況下則加載定時任務類,否則情況下就不加載該定時任務類;–缺點無法實現高可用的問題;
- 3.在數據庫加上一個主鍵能夠創建成功,則觸發定時任務,否則就不觸發定時任務, 高可用的問題;
- 4.分布式鎖實實現,只要jar能夠拿到分布式鎖就能夠執行定時任務,否則情況下不執行;
總結:以上的方案都是屬于規模比較小的項目,在微服務架構中應該采用分布式任務調度平臺。
二、傳統定時任務的實現方案
多線程形式、timetask、線程池、springboot注解形式、quartz
2.1. 多線程
基于多線程方式實現
package com.gblfy;public class ThreadTask {public static void main(String[] args) {new Thread(new Runnable() {@Overridepublic void run() {while (true) {try {Thread.sleep(1000);System.out.println("定時任務觸發...");} catch (InterruptedException e) {}}}}).start();} }2.2. TimeTask
package com.gblfy;import java.util.Timer; import java.util.TimerTask;public class TimerTaskDemo {public static void main(String[] args) {TimerTask timerTask = new TimerTask() {@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + "定時任務觸發");}};// 天數long delay = 0;// 耗秒數long period = 1000;new Timer().scheduleAtFixedRate(timerTask, delay, period);} }2.3. 線程池
package com.gblfy;import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit;public class ScheduledExecutorServiceDemo {public static void main(String[] args) {Runnable runnable = new Runnable() {@Overridepublic void run() {System.out.println("定時任務觸發..");}};ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10);scheduledExecutorService.scheduleAtFixedRate(runnable, 1, 1, TimeUnit.SECONDS);} }2.4. SpringBoot注解形式
package com.gblfy;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.scheduling.annotation.EnableScheduling;@EnableScheduling @SpringBootApplication public class ScheduledTaskApplication {public static void main(String[] args) {SpringApplication.run(ScheduledTaskApplication.class, args);}} package com.gblfy;import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component;@Component public class UserScheduled {@Scheduled(cron = "0/1 * * * * *")public void taskUserScheduled() {System.out.println("定時任務觸發...");}}2.5. 基于Quartz
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- quartz --><dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</artifactId><version>2.3.2</version></dependency><dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz-jobs</artifactId><version>2.3.2</version></dependency>MyJob
package com.gblfy.job;import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException;public class MyJob implements Job {@Overridepublic void execute(JobExecutionContext context) throws JobExecutionException {System.out.println("quartz MyJob date:" + System.currentTimeMillis());} }QuartzTest
package com.gblfy.job;import org.quartz.*; import org.quartz.impl.StdSchedulerFactory;import java.util.Date;public class QuartzTest {public static void main(String[] args) throws SchedulerException {//1.創建Scheduler的工廠SchedulerFactory sf = new StdSchedulerFactory();//2.從工廠中獲取調度器實例Scheduler scheduler = sf.getScheduler();//3.創建JobDetailJobDetail jb = JobBuilder.newJob(MyJob.class).withDescription("this is a ram job") //job的描述.withIdentity("ramJob", "ramGroup") //job 的name和group.build();//任務運行的時間,SimpleSchedle類型觸發器有效long time = System.currentTimeMillis() + 3 * 1000L; //3秒后啟動任務Date statTime = new Date(time);//4.創建Trigger//使用SimpleScheduleBuilder或者CronScheduleBuilderTrigger t = TriggerBuilder.newTrigger().withDescription("").withIdentity("ramTrigger", "ramTriggerGroup")//.withSchedule(SimpleScheduleBuilder.simpleSchedule()).startAt(statTime) //默認當前時間啟動.withSchedule(CronScheduleBuilder.cronSchedule("0/2 * * * * ?")) //兩秒執行一次.build();//5.注冊任務和定時器scheduler.scheduleJob(jb, t);//6.啟動 調度器scheduler.start();} }三、分布式任務調度平臺架構設計原理
3.1. xxl-job項目模塊講解
xxl-job-admin—分布式任務調度中心平臺
xxl-job-core—源碼實現部分
xxl-job-executor-samples–執行器項目 定時任務模塊項目
執行器模塊:(注冊中心)存放實際執行我們定時任務項目模塊IP和端口信息;
分布式任務調度中心(Nginx):負責所有執行器執行定時任務的分配;
3.2. 最佳實戰
定時任務與業務邏輯實現解耦,分開部署。
定時任務是一個單獨的項目。
gblfy-member—會員服務接口
member-job----負責會員服務定時任務
3.3. Xxl-job定時任務框架實現原理
建議:配置定時任務規則的時候,建議提前5-10s;
常用分布式任務調度框架
Xxl-job、elasticjob、SpringAlibaba Cloud SchedulerX
XXL-Job Admin如何實現集群
四、常見面試題
4.1. XXL-JOB與ElasticJob區別之間區別
XXL-JOB內置定時任務調度中心,ElasticJob借助于zookeeper作為注冊中心
4.2. 分布式任務調度分片集群策略原理
執行器集群部署時,任務路由策略選擇”分片廣播”情況下,一次任務調度將會廣播觸發對應集群中所有執行器執行一次任務,同時系統自動傳遞分片參數;可根據分片參數開發分片任務;
“分片廣播” 以執行器為維度進行分片,支持動態擴容執行器集群從而動態增加分片數量,協同進行業務處理;在進行大數據量業務操作時可顯著提升任務處理能力和速度。
“分片廣播” 和普通任務開發流程一致,不同之處在于可以獲取分片參數,獲取分片參數進行分片業務處理。
4.3. 如何保證任務調度平臺高可用問題
調度中心集群(可選):
調度中心支持集群部署,提升調度系統容災和可用性。
調度中心集群部署時,幾點要求和建議:
-
1.DB配置保持一致;
-
2.集群機器時鐘保持一致(單機集群忽視);
-
建議:推薦通過nginx為調度中心集群做負載均衡,分配域名。調度中心訪問、執行器回調配置、調用API服務等操作均通過該域名進行。
執行器集群(可選):
執行器支持集群部署,提升調度系統可用性,同時提升任務處理能力。
執行器集群部署時,幾點要求和建議:
- 1.執行器回調地址(xxl.job.admin.addresses)需要保持一致;執行器根據該配置進行執行器自動注冊等操作。
- 2.同一個執行器集群內AppName(xxl.job.executor.appname)需要保持一致;調度中心根據該配置動態發現不同集群的在線執行器列表。
總結
以上是生活随笔為你收集整理的分布式任务调度平台一站式讲解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: nacos集成dubbo实现远程服务调用
- 下一篇: ElasticSearch 文档的添加、