昨天有群友反映,在根据之前的文章《使用Elastic Job实现定时任务》编写测试定时任务时,报了类似如下的错误:Causedby:org.apache.shardingsphere.elasticjob.infra.exception。JobConfigurationException:作业与注册中心冲突。注册中心类中的工作'my-simple-job'是'com.didispace.chapter72.MySimpleJob',你的工作类是org.apache.shardingsphere.elasticjob.lite.internal中的'com.didispace.chapter74.MySimpleJob'。config.ConfigurationService.checkConflictJob(ConfigurationService.java:86)~[elasticjob-lite-core-3.0.0.jar:3.0.0]在org.apache.shardingsphere.elasticjob.lite.internal.config。ConfigurationService.setUpJobConfiguration(ConfigurationService.java:70)~[elasticjob-lite-core-3.0.0.jar:3.0.0]在org.apache.shardingsphere.elasticjob.lite.internal.setup.SetUpFacade.setUpJobConfiguration(SetUpFacade.java:66)~[elasticjob-lite-core-3.0.0.jar:3.0.0]在org.apache.shardingsphere.elasticjob.lite.internal.schedule.JobScheduler.(JobScheduler.java:84)~[elasticjob-lite-core-3.0.0.jar:3.0.0]在org.apache.shardingsphere.elasticjob.lite.api.bootstrap.impl.ScheduleJobBootstrap.(ScheduleJobBootstrap.java:36)~[elasticjob-lite-core-3.0.0.jar:3.0.0]在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]在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]在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]在sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMe方法)~[na:1.8.0_151]在sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)~[na:1.8.0_151]在sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)~[na:1.8.0_151]在java.lang.reflect.Method.invoke(Method.java:498)~[na:1.8.0_151]在org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:389)~[spring-beans-5.3.8.jar:5.3.8]在org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:333)~[spring-beans-5.3.8.jar:5.3.8]在org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:157)~[spring-beans-5.3.8.jar:5.3.8]...17省略公共框架根据错误消息Jobconflictwith注册中心。注册中心的作业'my-simple-job',初步判断是ZooKeeper中保存的任务配置存在冲突:任务名称相同,但实现类不同。经过一番沟通,原来他是用公司测试环境的ZooKeeper我自己写了一个例子来测试,之前有个同事(也是DD的读者)也写过类似的任务,因为复制了配置的任务名,所以有一种情况任务名称是相对的,但是实现类不同。事实上,如果我们在更大的团队中开发,只要有多个系统,其实很有可能会出现定时任务的重复。例如:很多应用程序可能有一些定时清理某些资源的任务,所以它们很可能重名,然后注册到同一个ZooKeeper,最后就产生了冲突。那么有什么好的方法可以解决这个问题呢?方法一:任务创建统一管理最原始的处理方式是集中管理任务创建过程,例如:你可以打开一个Wiki页面,所有的任务都在这个页面注册。大家注册的时候可以查看自己想到的名字是否已经存在。如果存在,请考虑另一个名称并注册。这种方法简单易懂。但是问题是当任务很多的时候,这个页面的内容就非常庞大,维护起来很麻烦。方法二:巧妙地利用ElasticJob的namespace属性来隔离任务名称。回想一下我在上一篇刚开始写定时任务的时候,注册中心的配置有没有下面两项:elasticjob.reg-center.server-lists=localhost:2181elasticjob.reg-center.namespace=didispace第一项elasticjob.reg-center.server-lists就不多说了,就是ZooKeeper的访问地址。这里重点是第二个参数elasticjob.reg-center.namespace。其实在ZooKeeper注册任务的时候,真正的冲突并不是单纯的因为任务名,而是命名空间+任务名,都是一样的,这样才会有问题。所以,我们只需要将每个应用创建的任务隔离在自己独立的命名空间中,这样就不会和其他应用发生冲突了吗?最后给了如下建议:spring.application.name=chapter74elasticjob.reg-center.server-lists=localhost:2181elasticjob.reg-center.namespace=${spring.application.name}也就是定时任务elasticjob服务的.reg-center.namespace设置为与当前SpringBoot应用程序名称相同的spring.application.name。通常我们在规划每一个SpringBoot应用的时候,都会规划唯一性,这样以后我们在Eureka、Nacos等注册中心注册的时候,也能保证唯一性。利用好这个独特的参数,还可以方便的帮我们隔离各个应用的定时任务,解决了我们文章开头提到的场景。本系列教程《Spring Boot 2.x基础教程》直接点击!,欢迎收藏转发!如果你在学习过程中遇到困难?大家可以加入我们的Spring技术交流群,参与交流讨论,更好的学习进步!代码示例本文的完整工程可以在如下仓库的chapter7-4目录查看:Github:https://github.com/dyc87112/SpringBoot-Learning/Gitee:https://gitee.com/didispace/SpringBoot-Learning/如果您觉得这篇文章不错,欢迎Star支持,您的关注是我坚持的动力!欢迎关注我的:程序员DD,分享别处看不到的知识和思考