Dubbo對Spring Cloud說:來老弟,我要擁抱你

猿天地發表於2020-05-18

專案地址

https://github.com/yinjihuan/kitty-cloud

前言

Kitty Cloud 開源後有以為朋友在 GitHub 上給我提了一個 issues,問為什麼專案中要同時整合 Feign 和 Dubbo 兩個框架來呼叫服務。今天就來聊一聊這個問題,然後講下在 Kitty Cloud 中如何切換使用兩種呼叫方式。

為什麼要支援兩種協議?

關於支援兩種協議,我這個是一個開源專案,主要還是為了讓使用者有更多的選擇。當然框架本身不是我開發的,我只是使用者而已。

一種協議更統一化,兩種協議混著用也不是不可以,具體還是看實際需求。比如你們內部有個 ID 分發的服務,呼叫量很高,就是對效能有這極致的要求。那麼這個場景你就可以用 Rpc 來代替 Http 了。其他的正常使用 Http 協議就行,特殊場景的就用 Rpc 協議,互補而已。

用 Http 最好的點在於簡單,傳輸內容就是文字,除錯什麼的都很方便。比如我要單獨測試某個服務的介面,直接 PostMan 上呼叫這個 Http 介面就可以了,或者用 Swagger。

如果是 Dubbo 的 Rpc, 我可能需要用 telnet 來呼叫。

還有就是閘道器層的轉發,如果是 Http 協議,直接轉發過去了。如果是 Rpc 協議,閘道器內部需要轉特殊處理,當然目前也有支援 Rpc 的閘道器。如果我們是兩種協議,閘道器這邊還是直接 Http 轉發過去即可,內部服務之前想用什麼協議讓使用者自己決定。

其實在 Spring Cloud 慢慢進入企業後,有很多人都會遇到一個問題就是老的服務都是用 Dubbo 來通訊的,如果轉 Spring Cloud 技術棧,那麼勢必要去掉 Dubbo。

如果規模不大直接重構掉也沒關係,但是對於大規模的應用,服務數量眾多。不太可能一口吃成個胖子。就算要重構那也是一個一個的方式來,也就意味著在沒重構完之前,老的服務還是 Dubbo,但有一些服務已經變成 Spring Cloud 體系了。這個時候相容就是一個迫切需要解決的問題。

Spring Cloud Alibaba 的出現就為這個問題提供了完美的解決方案,同時支援兩種協議,可以慢慢過渡遷移。

舉例說明

下面通過一個例子來說明:

下圖中有兩個服務,最開始都是 Rpc 協議,服務 A 通過 Rpc 方式呼叫服務 B。

當我們將服務 B 重構成 Http 協議後,服務 A 就需要使用 Http 方式來呼叫服務 B。

改造方案一

如果從實現需求上來講,很簡單,將服務 A 中呼叫的程式碼給出用 Feign 或者 RestTemplate 呼叫即可。但是這樣也就意味著我重構了 B 服務,還需要改動 A 服務的程式碼,很有可能不止 A 一個服務在呼叫 B 服務,也許有幾十個,那麼我是不是得改幾十個服務的呼叫方式。

顯然這個方案不可行。你如果這樣出方案,你老大一個眼神送給你,自己體會吧。。。。。

改造方案二

方案一既然被否了,那需求很明顯嘛,就是你可以重構成 Spring Cloud 技術棧,但是你不能影響使用方。

要想不影響使用方,感覺只能從 Dubbo 的呼叫這塊入手。也就是在Dubbo 底層去擴充套件,如果目標服務是老的 Rpc 協議,那麼呼叫方式保持不變即可。

如果目標服務變成新的 Http 協議,那麼就需要使用新的方式去呼叫,只有在底層相容了才不會影響使用方。

改造方案三

第三種方案也就是我們現在目前的方案,讓服務 B 支援雙協議,支援雙協議後,那麼所有的呼叫方都不用改變,因為 Rpc 的方式還支援。如果有新的服務可以使用 Http 來呼叫 B 服務的介面。

怎麼支援兩種協議?

支援兩種協議的核心在於 Dubbo Spring Cloud ,Dubbo Spring Cloud 作為 Spring Cloud Alibaba 中的最核心元件,基本上適配了 Spring Cloud 技術棧。

介面還是單獨抽出來放在 API 模組中,FeignClient 相關定義在介面上。

在實現類中同時暴露兩種協議,加上 Dubbo 的@Service 和@RestController 註解。

使用方只需要注入介面即可呼叫,如果想使用 Feign 呼叫就用@Autowired 進行注入。

@Autowired
private UserRemoteService userRemoteService;

如果想使用 Dubbo 進行呼叫就用@Reference 進行注入。

@Reference(version = DubboConstant.VERSION_V100, group = DubboConstant.DEFAULT_GROUP, check = false)
private UserRemoteService userRemoteService;

還有一個很重要的配置在於需要將 Dubbo 的註冊中心掛載到 Spring Cloud 註冊中心上。

dubbo.registry.address=spring-cloud://localhost

高階玩法

目前雖然支援了雙協議,但使用權交到了使用者手裡。就是你想用什麼協議發起呼叫都可以,是通過硬編碼的方式來處理的。

如果想靈活度更高的話,我們可以在 Dubbo 或者 Feign 的底層去擴充套件。比如基於 Feign 去擴充套件的話,那就是呼叫都是採用 Feign 的方式,不需要用@Reference 來注入客戶端。我們可以通過整合配置中心,用配置的方式來指定採用哪種協議呼叫。在 Feign 底層通過配置內容決定是否要走 Rpc 呼叫。如果要走 Rpc 可以用 Dubbo 的泛化呼叫。

相關文章