马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
使命调度的背景
在业务系统中有很多如许的场景:
1、账单日大概还款日上午 10 点,给每个名誉卡客户发送账单关照,还款关照。如 何判断客户的账单日、还款日,完成关照的发送?
2、银行业务系统,夜间要完成跑批的一系列流程,清理数据,下载文件,解析文件, 对账整理、切换结算日期等等。怎样触发一系列流程的执行?
3、金融机构跟人民银行二代支付系统对接,人民银行要求低于 5W 的金额(小额支付)半个小时打一次包发送,以缓解并发压力。以是,银行的跨行转账分成了多个流程: 录入、复核、发送。怎样把半个小时以内的所有数据一次性发送?
类似于这种 1、基于准确的时刻大概固定的时间隔断触发的使命,大概 2、有批量数据需要处理,大概 3、要实现两个动作解耦的场景,我们都可以用使命调度来实现。
使命调度的需求分析
1)可以界说触发的规则,比如基于时刻、时间隔断、表达式。
2)可以界说需要执行的使命。比如执行一个脚本大概一段代码。使命和规则是分开的。
3)会合管理设置,持久设置。不消把规则写在代码里面,可以看到所有的使命设置,方便维护。重启之后使命可以再次调度——设置文件大概设置中央。
4)支持使命的串行执行,比方执行 A 使命后再执行 B 使命再执行 C 使命。
5)支持多个使命并发执行,互不干扰(比方 ScheduledThreadPoolExecutor)。
6)有本身的调度器,可以启动、中断、制止使命。
7)容易集成到 Spring。
使命调度工具对比
条理举例特点操纵系统Linux crontab <br>Windows 筹划使命只能执行简单脚本大概命令数据库MySQL、Oracle可以操纵数据。不能执行 Java 代码工具Kettle可以操纵数据,执行脚本。没有会合设置开发语言JDK Timer、ScheduledThreadPoolTimer:单线程<br>JDK1.5 之后:ScheduledThreadPool(Cache、Fiexed、Single):没有会合设置,日程管理不够机动容器Spring Task、@Scheduled不支持集群分布式框架XXL-JOB,Elastic-Job @Scheduled 也是用 JUC 的 ScheduledExecutorService 实现的Scheduled(cron = “0 15 10 15 * ?”)
1、 ScheduledAnnotationBeanPostProcessor 的 postProcessAfterInitialization 方法将@Scheduled 的方法包装为指定的 task添加到 ScheduledTaskRegistrar 中
2、 ScheduledAnnotationBeanPostProcessor 会监听 Spring 的容器初始化事件,在 Spring 容器初始化完成后进行TaskScheduler 实现类实例的查找,若发现有 SchedulingConfigurer 的实现类实例,则跳过 3
3、 查找 TaskScheduler 的实现类实例默认是通过类型查找,若有多个实现则会查找名字为"taskScheduler"的实现 Bean,若没有找到则在 ScheduledTaskRegistrar 调度使命的时间会创建一个 newSingleThreadScheduledExecutor,将TaskScheduler 的实现类实例设置到 ScheduledTaskRegistrar 属性中
4、 ScheduledTaskRegistrar 的 scheduleTasks 方法触发使命调度
5、 真正调度使命的类是 TaskScheduler 实现类中的 ScheduledExecutorService,由 J.U.C 提供
下面谨慎介绍一款可以完成使命调度的工具===>Quartz
Quartz 根本介绍
官网:http://www.quartz-scheduler.org/
Quartz 的意思是石英,像石英表一样准确。
Quartz is a richly featured, open source job scheduling library that can be integrated within virtually any Java application - from the smallest stand-alone application to the largest e-commerce system. Quartz can be used to create simple or complex schedules for executing tens, hundreds, or even tens-of-thousands of jobs; jobs whose tasks are defined as standard Java components that may execute virtually anything you may program them to do. The Quartz Scheduler includes many enterprise-class features, such as support for JTA transactions and clustering.
Quatz 是一个特性丰富的,开源的使命调度库,它险些可以嵌入所有的 Java 程序,从很小的独立应用程序到大型商业系统。Quartz 可以用来创建成百上千的简单的大概复杂的使命,这些使命可以用来执行任何程序可以做的事变。Quartz 拥有很多企业级的特性,包括支持 JTA 事件和集群。
Quartz 是一个老牌的使命调度系统,98 年构思,01 年发布到 sourceforge。现在更新比力慢,因为已经非常成熟了。
https://github.com/quartz-scheduler/quartz
Quartz 的目标就是让使命调度更加简单,开发职员只需要关注业务即可。他是用 Java 语言编写的(也有.NET 的版本)。Java 代码能做的任何事变,Quartz 都可以调度。
特点:
准确到毫秒级别的调度
可以独立运行,也可以集成到容器中
支持事件(JobStoreCMT )
支持集群
支持持久化
引入依赖
- <dependency>
- <groupId>org.quartz-scheduler</groupId>
- <artifactId>quartz</artifactId>
- <version>2.3.0</version>
- </dependency>
复制代码 默认设置文件
org.quartz.core 包下,有一个默认的设置文件,quartz.properties。当我们没有界说一个同名的设置文件的时间,就会利用默认设置文件里面的设置。
- org.quartz.scheduler.instanceName: DefaultQuartzScheduler
- org.quartz.scheduler.rmi.export: false
- org.quartz.scheduler.rmi.proxy: false
- org.quartz.scheduler.wrapJobExecutionInUserTransaction: false org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
- org.quartz.threadPool.threadCount: 10
- org.quartz.threadPool.threadPriority: 5 org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true org.quartz.jobStore.misfireThreshold: 60000
- org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore
复制代码 创建 Job
实现唯一的方法 execute(),方法中的代码就是使命执行的内容。此处仅输出字符串。
- public class MyJob implements Job {
- public void execute(JobExecutionContext context) throws JobExecutionException {
- System.out.println("假发在哪里买的");
- }
- }
复制代码 在测试类 main()方法中,把 Job 进一步包装成 JobDetail。
必须要指定 JobName 和 groupName,两个合起来是唯一标识符。
可以携带 KV 的数据(JobDataMap),用于扩展属性,在运行的时间可以从 context 获取到
- JobDetail jobDetail = JobBuilder.newJob(MyJob1.class)
- .withIdentity("job1", "group1")
- .usingJobData("msb","我爱涛哥")
- .usingJobData("moon",5.21F)
- .build();
复制代码 创建 Trigger
在测试类 main()方法中,基于 SimpleTrigger 界说了一个每 2 秒钟运行一次、不停重复的 Trigger:
- Trigger trigger = TriggerBuilder.newTrigger()
- .withIdentity("trigger1", "group1")
- .startNow()
- .withSchedule(SimpleScheduleBuilder.simpleSchedule()
- .withIntervalInSeconds(2)
- .repeatForever())
- .build();
复制代码 创建 Scheduler
在测试类 main()方法中,通过 Factory 获取调度器的实例,把 JobDetail 和 Trigger绑定,注册到容器中。
Scheduler 先启动后启动无所谓,只要有 Trigger 到达触发条件,就会执行使命。
- SchedulerFactory factory = new StdSchedulerFactory();
- Scheduler scheduler = factory.getScheduler();
- scheduler.scheduleJob(jobDetail, trigger);
- scheduler.start();
复制代码 注意这里,调度器一定是单例的。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |