升級dubbo2.7.4.1版本平滑遷移到註冊中心nacos
前言
dubbo是一款非常優秀的服務治理型RPC框架,dubbo的優秀在於,龐大的架構體系、精湛的模塊設計、靈活的SPI設計、豐富的組件實現,博主做微服務技術選型考察dubbo時,非常驚嘆在那個年代別人就已經能夠產出如此優秀的項目,以至於後面每逢別人說想要學習架構設計時,我都會推薦他讀讀dubbo的代碼,學習下dubbo的架構設計原則。常說dubbo不僅僅是一款RPC框架,是因為他的服務治理特性相對於RPC通訊來說更加的突出,這個特性讓我在2017年選型的時候果斷選擇瞭他,那個時候dubbo官方還沒產出spring boot starter,而我們的項目大部分完成瞭從spring mvc改造到spring boot項目。為瞭簡化開發集成dubbo組件,我們基於dubbo2.5.6版本自研瞭一套spring-boot-dubbo-starter組件,並且自定義dubbo服務暴露和引入的註解, 自定義瞭dubbo的配置裝載方式。當時沒有專業的運維、搭建高可用zk也費資源,為瞭簡單方便少維護一個組件、當時我們直接選瞭redis(阿裡雲高可用實例)作為dubbo的註冊中心。以上就是我們這次升級dubbo的背景情況
為什麼升級到2.7.4.1?
從2.5.6到2.7.x,中間修復非常多的bug,帶來瞭非常多的新特性。
2.5.x版本不在作為一個保留維護的版本,目前主力維護的就2.6.x和2.7.x版本,還有探索版本3.0.也就是說即使2.5.x以後有問題瞭,官方也不會在修復瞭。
之所以選擇2.7.4.1版本,是因為經過研究瞭官方issue和關註瞭dubbo群裡的情況後,發現這個版本相對比較穩定,而且官方也推薦升級到這個版本。
為什麼遷移註冊中心到nacos?
目前redis註冊中心雖然經過瞭趟坑之後《dubbo使用redis註冊中心的系列問題》,趨於穩定瞭,但是因為太小眾,使用的人太少導致很多問題並沒有暴露出來(在升級的過程中又發現瞭一個redis註冊中心的問題), 如果繼續使用redis註冊中心,將會一直處在不斷自我趟坑的過程中無法自拔。
nacos是dubbo官方主推的註冊中心項目,雖然現在還在迭代磨合,但是一旦發現問題官方反應還是比較及時的。使用nacos人越來越多,相當於趟坑的人也多瞭,隱藏的bug就無處可藏瞭。而且nacos和dubbo有天生的血緣關系, 查看nacos近期的release情況,發現有幾個特意修復dubbo註冊的問題
nacos自帶瞭web管理控制臺,可以非常方便的查詢dubbo的註冊情況,可以作為一個簡易的dubbo治理中心來使用
兩種升級方案
由於我們目前維護瞭自己的spring-boot-dubbo-starter,所以在做升級時,我們產生瞭兩種不同的升級方案,並且都做瞭完整的驗證。
方案一:魔改官方的starter組件
為瞭做到開發側基本無感知升級到2.7.4.1版本,我們做瞭兩件事情
註解兼容
在做註解兼容時也考慮過兩個方案,一個是在自研的starter上做兼容dubbo2.7.4.1的處理,一個是在官方2.7.4.1的starter上兼容我們的處理。後面果斷選擇瞭後者,因為dubbo2.7.4.1版本對於我們來說是個黑盒子不知道有哪些改動,正向兼容難度比較大,反向兼容卻要容易的多。 我們將原來自研組件裡的自定義註解,保留包路徑完整的拷貝到官方的starter項目中,然後將 ReferenceAnnotationBeanPostProcessor和ServiceAnnotationBeanPostProcessor從dubbo的spring模塊中挪瞭出來,做瞭兼容自定義註解的處理。這個地方再次誇下 dubbo的設計,dubbo在捐贈給apache後,包名都改瞭,為瞭兼容老的alibaba包下的註解,服務暴露和服務引入都做瞭非常簡易的註解兼容設計。 得益於此,我們在做自定義註解兼容處理時非常輕松就搞定瞭。
ReferenceAnnotationBeanPostProcessor的構造器傳入自定義註解:
public ReferenceAnnotationBeanPostProcessor() { super(AutowiredDubbo.class, Reference.class, com.alibaba.dubbo.config.annotation.Reference.class); }
ServiceAnnotationBeanPostProcessor掃描時添加自定義註解支持
scanner.addIncludeFilter(new AnnotationTypeFilter(Service.class)); /** * Add the compatibility for legacy Dubbo's @Service * * The issue : https://github.com/apache/dubbo/issues/4330 * @since 2.7.3 */ scanner.addIncludeFilter(new AnnotationTypeFilter(com.alibaba.dubbo.config.annotation.Service.class)); // 兼容@DubboService註解 scanner.addIncludeFilter(new AnnotationTypeFilter(DubboService.class));
最後修改DubboAutoConfiguration中的服務暴露和服務引入處理器為我們魔改的實現即可
配置兼容
自研的自定義配置加載以spring.dubbo.打頭的,而官方是以dubbo.打頭的,區別如下:
自研的配置: spring.dubbo.application.name = xxx spring.dubbo.registry.address = xxx spring.dubbo.protocol.port = -1 官方starter配置 dubbo.application.name = xxx dubbo.registry.address = xxx dubbo.protocol.port = -1
為瞭做到配置兼容,修改瞭dubbo starter配置加載邏輯,去掉瞭spring.打頭,修改DubboUtils中的filterDubboProperties,如:
public static SortedMap filterDubboProperties(ConfigurableEnvironment environment) { SortedMap dubboProperties = new TreeMap<>(); Map properties = EnvironmentUtils.extractProperties(environment); for (Map.Entry entry : properties.entrySet()) { String propertyName = entry.getKey(); if (propertyName.startsWith(DUBBO_PREFIX + PROPERTY_NAME_SEPARATOR) && entry.getValue() != null) { dubboProperties.put(propertyName, entry.getValue().toString()); } if (propertyName.startsWith("spring." + DUBBO_PREFIX + PROPERTY_NAME_SEPARATOR) && entry.getValue() != null) { propertyName = propertyName.substring(7); dubboProperties.put(propertyName, entry.getValue().toString()); } } return Collections.unmodifiableSortedMap(dubboProperties); }
最後打包上傳到私服,開發隻需要升級下jar的版本,配置和代碼都不用動就可以升級到2.7.4.1版本的dubbo,可能魔改的地方不止上面貼的這些代碼,這裡隻是引出思路,這個方案到這裡結束瞭,這個方案的優點是對開發比較透明 因為遷移到nacos的步驟是一樣的,第二個方案會談到
方案二:直接使用官方的starter組件-最終采用的方案
最終討論下來,考慮到內部維護版本,當官方升級時聯動升級會比較麻煩,不如,直接痛一次全線改造代碼,改造配置,采用瞭官方的starter直接升級,這樣,後面有版本升級不用在投入人力維護自研的和官方的一致。
第一步:引入maven依賴
官方dubbo starter依賴
<dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>2.7.4.1</version> </dependency> <dependency> <groupId>com.alibaba.nacos</groupId> <artifactId>nacos-client</artifactId> <version>1.1.3</version> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency>
第二步:改造相關的註解
啟用dubbo時:@EnableDubbo 改成
@EnableDubbo【org.apache.dubbo.config.spring.context.annotation.EnableDubbo】
並建議添加scanBasePackages包路徑,如:
@EnableDubbo(scanBasePackages = "cn.keking.service")。
提高dubbo暴露服務和引入服務時的掃描速度
服務暴露時:
@DubboService 改成 @Service 【org.apache.dubbo.config.annotation.Service】
服務引入時:
@AutowiredDubbo 改成 @Reference 【org.apache.dubbo.config.annotation.Reference】,
這裡需要註意三點:
1、官方的starter默認的服務引入會校驗服務是否存在,不存在就拋異常,會影響應用啟動,可添加全局的配置,覆蓋默認行為,配置如下:dubbo.consumer.check=false
2、自研starter中@AutowiredDubbo 的timeout等參數的單位為秒,官方註解@Reference的參數單位為毫秒,如以前配置為timeout=30, 則在官方starter中隻有30毫秒的超時時間。
3、在使用多註冊中心時,dubbo會從兩個註冊中心同時引入服務,雖然你的URL是完全一樣的,也會在本地產生兩個服務實例,所以,當你的容錯模式為廣播模式(cluster="Broadcast")或者並行模式(cluster="Forking")時就會產生消費者一次觸發,生產者收到兩次的問題。而默認的集群策略為 Failover,會正常的走隨機負載的方式調用,不會有這種問題。如果有廣播模式、或者並行模式的使用,可以通過設置nacos註冊中心,隻註冊不消費。配置方式如下,等所以服務都遷移到nacos上後及時移除這個配置:
dubbo.registries.nacos.parameters.subscribe = false
第三步:修改dubbo的配置
去掉spring.前綴即可,註意,升級官方starter後,需要新增一個配置,用來設置redis的連接池大小,官方默認的8個,
dubbo.registries.redis.parameters.max.total = 200
下面示例瞭升級後的dubbo配置:
dubbo.application.name = xxx dubbo.protocol.port = -1 dubbo.provider.timeout = 300000 dubbo.consumer.check = false dubbo.registries.nacos.address = nacos://xxx:80 dubbo.registries.redis.address = redis://xxx:6379 dubbo.registries.redis.parameters.max.total = 200
平滑遷移到nacos註冊中心
利用dubbo支持多註冊中心的功能,分兩個階段完成平滑的從redis遷移到nacos,第一階段,全線升級修改配置為雙註冊中心,第二階段,摘掉redis註冊中心完成過渡,配置方式如下:
dubbo.registries.nacos.address=nacos://xxx:80 dubbo.registries.redis.address=redis://xx:6379
註意一些問題
使用redis註冊中心時,如果隻有一個redis實例,區分環境是通過redis的db來控制的,比如如下配置:
dubbo.registry.parameters.db.index = 2
而nacos註冊中心通過命名空間來區分的,具體配置如下:
dubbo.registry.parameters.namespace = xxxxxx
如果是多註冊中心配置,註意使用相關註冊中心前綴,比如:
dubbo.registries.nacos.parameters.namespace=adefa98f-f4d9-4af8-9eb3-e0cab5a39cc7
結語
dubbo升級的方案雖然簡單,但是真正升級平滑過渡不是一蹴而就的,期間還是遇到瞭很多問題,這是一個不斷優化穩定的過程。截止目前我們還沒全線鋪開上生產,隻是個別應用推上生產做驗證,升級有風險,需要小心又謹慎
以上就是升級dubbo2.7.4.1版本平滑遷移到註冊中心nacos的詳細內容,更多關於dubbo遷移到nacos的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- springboot使用nacos的示例詳解
- 使用SpringCloudAlibaba整合Dubbo
- Spring與Dubbo搭建一個簡單的分佈式詳情
- Java中dubbo+zookeeper微服務架構簡介
- spring cloud如何集成nacos配置中心