使用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個代碼註釋,你寫過多少?


本文分享自微信公衆號 - 程序猿DD(didispace)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章