zoukankan      html  css  js  c++  java
  • 使用Elastic Job的时候报“Job conflict with register center”,如何处理?

    昨天,有群友反应根据之前这篇《使用Elastic Job实现定时任务》文章编写测试定时任务的时候,报了类似下面的这个错误:

    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来写的例子做测试,同时之前有同事(也是DD的读者)也写过类似的任务,因为配置的任务名称是拷贝的,所以出现了任务名称相对,但实现类不同的情况。

    实际上,如果我们在一个大一些的团队做开发的时候,只要存在多系统的话,那么定时任务的重名其实是很有可能发生。比如:很多应用都可能存在一些定时清理某些资源的任务,就很可能起一样的名字,然后注册到同一个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基础教程》点击直达!,欢迎收藏与转发!如果学习过程中如遇困难?可以加入我们Spring技术交流群,参与交流与讨论,更好的学习与进步!

    代码示例

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

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

    欢迎关注我的公众号:程序猿DD,分享外面看不到的干货与思考!

  • 相关阅读:
    Android 编程下 Eclipse 恢复被删除的文件
    Android 编程下背景图片适配工具类
    Android 编程下 Managing Your App's Memory
    Android 编程下代码之(QQ消息列表滑动删除)
    Android 编程下 Canvas and Drawables
    Android 编程下 AlarmManager
    Android 编程下去除 ListView 上下边界蓝色或黄色阴影
    Java 编程下字符串的 16 位、32位 MD5 加密
    C#枚举类型和int类型相互转换
    MVC和普通三层架构的区别
  • 原文地址:https://www.cnblogs.com/didispace/p/15078642.html
Copyright © 2011-2022 走看看