使用Elastic Job的分片配置加速任务执行和提高资源利用率
上一篇,我们介绍了如何使用Elastic Job实现定时任务。解决了使用@Scheduled
来实现时候存在的竞争问题,同时也实现了定时任务的高可用执行。
然而,还有一类问题是我们在做定时任务时候容易出现的,就是任务执行速度时间过长;同时,为了实现定时任务的高可用,还启动了很多任务实例,但每个任务执行时候就一个实例在跑,资源利用率不高。
所以,接下来我们就来继续介绍,使用Elastic Job的分片配置,来为任务执行加加速,资源利用抬抬高的目标!
动手试试
建议直接下载文末仓库中的chapter7-2
工程,然后在这个基础上进行修改。当然,如果你对如何使用Elastic Job还不输入,那么先前往上一篇做个知识铺垫,再继续下面的内容!
第一步:创建一个分片执行的任务
@Slf4j
@Service
public class MyShardingJob implements SimpleJob {@Override
public void execute(ShardingContext context) {
switch (context.getShardingItem()) {
case 0:
log.info("分片1:执行任务");
break;
case 1:
log.info("分片2:执行任务");
break;
case 2:
log.info("分片3:执行任务");
break;
}
}}
这里通过
switch
来判断当前任务上下文的sharding-item值来执行不同的分片任务。sharding-item的值取决于后面将要配置的分片总数,但注意是从0开始计数的。 这里仅采用了日志打印的方式,来展示分片效果,真正实现业务逻辑的时候,一定记得根据分片数量对执行任务也要做分片操作的设计。比如:你可以根据批量任务的id求摩的方式来区分不同分片处理不同的数据,以避免重复执行而出现问题。第二步:在配置文件中,设置配置任务的实现类、执行表达式、以及将要重要测试的分片总数参数
elasticjob.jobs.my-sharding-job.elastic-job-class=com.didispace.chapter73.MyShardingJob
elasticjob.jobs.my-sharding-job.cron=0/5 * * * * ?
elasticjob.jobs.my-sharding-job.sharding-total-count=3
这里设置为3,所以任务会被分为3个分片,每个分片对应第一步中一个switch的分支。
运行与测试 单实例运行
在完成了上面的代码之后,尝试启动上面实现的第一个实例。
此时,我们可以看到,每间隔5秒,这个实例会打印这样的日志:
2021-07-21 17:42:00.122INFO 63478 --- [main] .s.b.j.ScheduleJobBootstrapStartupRunner : Starting ElasticJob Bootstrap.
2021-07-21 17:42:00.126INFO 63478 --- [main] org.quartz.core.QuartzScheduler: Scheduler my-sharding-job_$_NON_CLUSTERED started.
2021-07-21 17:42:00.126INFO 63478 --- [main] .s.b.j.ScheduleJobBootstrapStartupRunner : ElasticJob Bootstrap started.
2021-07-21 17:42:05.254INFO 63478 --- [-sharding-job-1] com.didispace.chapter73.MyShardingJob: 分片1:执行任务
2021-07-21 17:42:05.254INFO 63478 --- [-sharding-job-3] com.didispace.chapter73.MyShardingJob: 分片3:执行任务
2021-07-21 17:42:05.254INFO 63478 --- [-sharding-job-2] com.didispace.chapter73.MyShardingJob: 分片2:执行任务
2021-07-21 17:42:10.011INFO 63478 --- [-sharding-job-4] com.didispace.chapter73.MyShardingJob: 分片1:执行任务
2021-07-21 17:42:10.011INFO 63478 --- [-sharding-job-5] com.didispace.chapter73.MyShardingJob: 分片2:执行任务
2021-07-21 17:42:10.011INFO 63478 --- [-sharding-job-6] com.didispace.chapter73.MyShardingJob: 分片3:执行任务
每次任务都被拆分成了3个分片任务,就如我上文中所说的,每个分片对应一个switch的分支。由于当前情况下,我们只启动了一个实例,所以3个分片任务都被分配到了这个唯一的实例上。
双实例运行
接下来,我们再启动一个实例(注意使用-Dserver.port来改变不同的端口,不然本地会启动不成功)。此时,两个实例的日志出现了变化:
实例1的日志:
2021-07-21 17:44:50.190INFO 63478 --- [ng-job_Worker-1] com.didispace.chapter73.MyShardingJob: 分片2:执行任务
2021-07-21 17:44:55.007INFO 63478 --- [ng-job_Worker-1] com.didispace.chapter73.MyShardingJob: 分片2:执行任务
2021-07-21 17:45:00.010INFO 63478 --- [ng-job_Worker-1] com.didispace.chapter73.MyShardingJob: 分片2:执行任务
实例2的日志:
2021-07-21 17:44:50.272INFO 63484 --- [-sharding-job-1] com.didispace.chapter73.MyShardingJob: 分片1:执行任务
2021-07-21 17:44:50.273INFO 63484 --- [-sharding-job-2] com.didispace.chapter73.MyShardingJob: 分片3:执行任务
2021-07-21 17:44:55.009INFO 63484 --- [-sharding-job-3] com.didispace.chapter73.MyShardingJob: 分片1:执行任务
2021-07-21 17:44:55.009INFO 63484 --- [-sharding-job-4] com.didispace.chapter73.MyShardingJob: 分片3:执行任务
随着实例数量的增加,可以看到分片的分配发生了变化。这也就意味着,当一个任务开始执行的时候,两个任务执行实例都被利用了起来,这样我们的任务执行和资源利用的效率就可以得到优化。
你也可以尝试再继续启动实例和关闭实例来观察任务的动态分配,怎么样?这样写定时任务是不是方便多了? 一定记得自己动手写一写,这样体会更深哦!如果碰到问题,可以拉取文末的代码示例对比一下是否有地方配置不一样。下一篇,我们还将继续介绍关于定时任务的一些高级内容。
本系列教程《Spring Boot 2.x基础教程》点击直达!,欢迎收藏与转发!如果学习过程中如遇困难?可以加入我们Spring技术交流群,参与交流与讨论,更好的学习与进步!
代码示例 本文的完整工程可以查看下面仓库中的
chapter7-3
目录:- Github:https://github.com/dyc87112/SpringBoot-Learning/
- Gitee:https://gitee.com/didispace/SpringBoot-Learning/
Star
支持,您的关注是我坚持的动力!欢迎关注我的公众号:程序猿DD,分享其他地方看不到的知识与思考
推荐阅读
- 由浅入深理解AOP
- 【译】20个更有效地使用谷歌搜索的技巧
- mybatisplus如何在xml的连表查询中使用queryWrapper
- MybatisPlus|MybatisPlus LambdaQueryWrapper使用int默认值的坑及解决
- MybatisPlus使用queryWrapper如何实现复杂查询
- iOS中的Block
- Linux下面如何查看tomcat已经使用多少线程
- 使用composer自动加载类文件
- android|android studio中ndk的使用
- 使用协程爬取网页,计算网页数据大小