天天看點

Spring Boot 2.x基礎教程:使用Elastic Job的namespace防止任務名沖突

昨天,有群友反應根據之前這篇 《使用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,最後出現沖突。 那麼有什麼好辦法來解決這個問題嗎?

https://blog.didispace.com/spring-boot-learning-2-7-4/#%E6%96%B9%E6%B3%95%E4%B8%80%EF%BC%9A%E4%BB%BB%E5%8A%A1%E5%88%9B%E5%BB%BA%E7%9A%84%E7%BB%9F%E4%B8%80%E7%AE%A1%E7%90%86 方法一:任務建立的統一管理

最原始的處理方法,就是集中的管理任務建立流程,比如:可以開一個Wiki頁面,所有任務在這個頁面上登記,每個人登記的時候,可以查一下想起的名字是否已經存在。如果存在了就再想一個名字,并做好登記。

這種方法很簡單,也很好了解。但存在的問題是,當任務非常非常多的時候,這個頁面内容就很大,維護起來也是非常麻煩的。

https://blog.didispace.com/spring-boot-learning-2-7-4/#%E6%96%B9%E6%B3%95%E4%BA%8C%EF%BC%9A%E5%B7%A7%E7%94%A8Elastic-Job%E7%9A%84namespace%E5%B1%9E%E6%80%A7%E6%9D%A5%E9%9A%94%E7%A6%BB%E4%BB%BB%E5%8A%A1%E5%90%8D%E7%A7%B0 方法二:巧用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技術交流群

,參與交流與讨論,更好的學習與進步!

https://blog.didispace.com/spring-boot-learning-2-7-4/#%E4%BB%A3%E7%A0%81%E7%A4%BA%E4%BE%8B 代碼示例

本文的完整工程可以檢視下面倉庫中的

chapter7-4

目錄:

如果您覺得本文不錯,歡迎

Star

支援,您的關注是我堅持的動力!