使用Elastic Job的namespace配置,防止任务名称的冲突

昨天,有群友反应根据之前这篇《使用Elastic Job实现定时任务》(https://blog.didispace.com/spring-boot-learning-2-7-2/)文章编写测试定时任务的时候,报了类似下面的这个错误:

Caused by: org.apache.shardingsphere.elasticjob.infra.exception.JobConfigurationException: Job conflict with register center. The job 'my-simple-job' in register center's class is 'com.didispace.chapter72.MySimpleJob', your job class is 'com.didispace.chapter74.MySimpleJob'
 at org.apache.shardingsphere.elasticjob.lite.internal.config.ConfigurationService.checkConflictJob(ConfigurationService.java:86) ~[elasticjob-lite-core-3.0.0.jar:3.0.0]
 at org.apache.shardingsphere.elasticjob.lite.internal.config.ConfigurationService.setUpJobConfiguration(ConfigurationService.java:70) ~[elasticjob-lite-core-3.0.0.jar:3.0.0]
 at org.apache.shardingsphere.elasticjob.lite.internal.setup.SetUpFacade.setUpJobConfiguration(SetUpFacade.java:66) ~[elasticjob-lite-core-3.0.0.jar:3.0.0]
 at org.apache.shardingsphere.elasticjob.lite.internal.schedule.JobScheduler.<init>(JobScheduler.java:84) ~[elasticjob-lite-core-3.0.0.jar:3.0.0]
 at org.apache.shardingsphere.elasticjob.lite.api.bootstrap.impl.ScheduleJobBootstrap.<init>(ScheduleJobBootstrap.java:36) ~[elasticjob-lite-core-3.0.0.jar:3.0.0]
 at org.apache.shardingsphere.elasticjob.lite.spring.boot.job.ElasticJobBootstrapConfiguration.registerClassedJob(ElasticJobBootstrapConfiguration.java:101) ~[elasticjob-lite-spring-boot-starter-3.0.0.jar:3.0.0]
 at org.apache.shardingsphere.elasticjob.lite.spring.boot.job.ElasticJobBootstrapConfiguration.constructJobBootstraps(ElasticJobBootstrapConfiguration.java:84) ~[elasticjob-lite-spring-boot-starter-3.0.0.jar:3.0.0]
 at org.apache.shardingsphere.elasticjob.lite.spring.boot.job.ElasticJobBootstrapConfiguration.createJobBootstrapBeans(ElasticJobBootstrapConfiguration.java:57) ~[elasticjob-lite-spring-boot-starter-3.0.0.jar:3.0.0]
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_151]
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_151]
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_151]
 at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_151]
 at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:389) ~[spring-beans-5.3.8.jar:5.3.8]
 at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:333) ~[spring-beans-5.3.8.jar:5.3.8]
 at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:157) ~[spring-beans-5.3.8.jar:5.3.8]
 ... 17 common frames omitted

根据错误消息Job conflict with register center. The job 'my-simple-job' in register center's,初步判断是ZooKeeper中存储的任务配置出现冲突:任务名一样,但实现类不同。

经过一番交流,原来他是使用公司测试环境的ZooKeeper来写的例子做测试,同时之前有同事也写过类似的任务,因为配置的任务名称是拷贝的,所以出现了任务名称相对,但实现类不同的情况。

实际上,如果我们在一个大一些的团队做开发的时候,只要存在多系统的话,那么定时任务的重名其实是很有可能发生。比如:很多应用都可能存在一些定时清理某些资源的任务,就很可能起一样的名字,然后注册到同一个ZooKeeper,最后出现冲突。那么有什么好办法来解决这个问题吗?

方法一:任务创建的统一管理

最原始的处理方法,就是集中的管理任务创建流程,比如:可以开一个Wiki页面,所有任务在这个页面上登记,每个人登记的时候,可以查一下想起的名字是否已经存在。如果存在了就再想一个名字,并做好登记。

这种方法很简单,也很好理解。但存在的问题是,当任务非常非常多的时候,这个页面内容就很大,维护起来也是非常麻烦的。

方法二:巧用Elastic Job的namespace属性来隔离任务名称

回忆一下之前第一篇写定时任务的时候,关于注册中心的配置是不是有下面两项:

elasticjob.reg-center.server-lists=localhost:2181
elasticjob.reg-center.namespace=didispace

第一个elasticjob.reg-center.server-lists不多说,就是ZooKeeper的访问地址。这里要重点讲的就是第二个参数elasticjob.reg-center.namespace

其实在ZooKeeper中注册任务的时候,真正冲突的并不纯粹是因为任务名称,而是namespace + 任务名称,全部一样,才会出现问题。所以,是不是引入把每个应用创建的任务都设定一个独立的namespace,那么是不是就隔离了呢?

继续思考一下,每个应用是不是肯定有一些属性是肯定不一样的呢?最后,我给出了下面这样的建议:

spring.application.name=chapter74

elasticjob.reg-center.server-lists=localhost:2181
elasticjob.reg-center.namespace=${spring.application.name}

即:将定时任务服务的elasticjob.reg-center.namespace设置为当前Spring Boot应用的名称一致spring.application.name

通常,我们在规划各个Spring Boot应用的时候,都会做好唯一性的规划,这样未来注册到Eureka、Nacos等注册中心的时候,也可以保证唯一。利用好这个唯一参数,也可以方便的帮我们把各个应用的定时任务也都隔离出来,也就解决了文章开头,我们所说的场景了。

记得自己动手写一写,这样体会更深哦!如果碰到问题,可以拉取文末的代码示例对比一下是否有地方配置不一样。下一篇,我们还将继续介绍关于定时任务的一些高级内容。关注我,收藏本系列教程《Spring Boot 2.x基础教程》:http://blog.didispace.com/spring-boot-learning-2x/

学习过程中如遇困难,加入Spring技术交流群,参与讨论

关注我回复「加群」,加入Spring技术交流群

代码示例

本文的完整工程可以查看下面仓库中的chapter7-4目录:

  • Github:https://github.com/dyc87112/SpringBoot-Learning/tree/master/2.x

  • Gitee:https://gitee.com/didispace/SpringBoot-Learning/tree/master/2.x

如果您觉得本文不错,欢迎Star支持,您的关注是我坚持的动力!

往期推荐

用谷歌搜索技术问题一定比用百度好?也未必...

好多大咖曾看他的书学习Java,如今这个男人的新作来了!

Lombok!代码简洁神器还是代码“亚健康”元凶?

IntelliJ IDEA官方宣布中文汉化包正式发布

令人笑喷的56个代码注释,你写过多少?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值