您好,登錄后才能下訂單哦!
這篇文章主要講解了“Dubbo-go應用維度注冊模型怎么實現”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Dubbo-go應用維度注冊模型怎么實現”吧!
在 v1.5 以前,Dubbo-go 注冊模型都是以服務為維度的,直觀的理解可認為其是接口維度。譬如注冊信息,按照服務維度模型其示例如下:
"com.xxx.User":[ {"name":"instance1", "ip":"127.0.0.1", "metadata":{"timeout":1000}}, {"name":"instance2", "ip":"127.0.0.2", "metadata":{"timeout":2000}}, {"name":"instance3", "ip":"127.0.0.3", "metadata":{"timeout":3000}}, ]
這種模式的好處是不言而喻的,簡單直觀,提供了細粒度的服務控制手段。
而近兩年,隨著云時代的到來,這種模式就暴露了不足:
主流的注冊模型都是應用維度的;
以服務維度來注冊,那么規模與服務數量成正比,大規模集群之下,注冊中心壓力非常大;
這次 Dubbo-go 支持了新的注冊模型,也就是應用維度的注冊模型。簡單而言,在應用維度注冊下,其注冊信息類似:
"application1": [ {"name":"instance1", "ip":"127.0.0.1", "metadata":{}}, {"name":"instance2", "ip":"127.0.0.2", "metadata":{}}, {"name":"instanceN", "ip":"127.0.0.3", "metadata":{}} ]
在此模式之下,可以看到注冊信息將會大幅度減少,集群規模只與實例數量相關。
與此同時,在實現這一個功能的時候,Dubbo-go 還希望保持兩個目標:
對用戶完全兼容,用戶遷移無感知;
保持住原本服務粒度上精細控制的能力——即保留現有的服務維度的元數據;
因此 Dubbo-go 要著力解決以下幾點:
目前 Consumer 的配置是以接口為準的,如何根據接口找到該接口對應的應用?例如,用戶配置了 com.xxx.User
服務,那么,Dubbo-go 怎么知道這個服務是由哪個應用來提供的呢?
在知道了是哪個應用之后,可以從注冊中心拿到應用的注冊信息,如實例信息等;那怎么知道 com.xxx.User
服務自身的元數據呢?
為了解決這兩個問題,在已有的注冊模型的基礎上,Dubbo-go 引入兩個額外的組件:ServiceNameMapping 和 MetadataService。
前者用于解決服務-應用之間的映射,后者用于獲取服務的元數據。
由此,Dubbo-go 的應用維度注冊模型就變為:
cdn.nlark.com/yuque/0/2020/png/755700/1595053608806-be43aed1-83b4-4a05-8d25-60a0c7fa5445.png">
ServiceNameMapping 并不復雜。考慮到一般人在 Consumer 側想要調用一個服務,其十有八九是知道這個服務是哪個應用提供的,于是 Dubbo-go 引入了新的配置項 provideBy
當然,所謂 “十有八九”就是說有些時候確實不知道是服務是誰提供的,所以 Dubbo-go 還支持了基于配置中心的 ServiceNameMapping 實現。Dubbo-go 會用服務名作為 Key 從配置中心里面讀出對應的應用名。這意味著, Provider 啟動的時候,也會在配置中心將自身的 服務-應用名映射 寫入配置中心。
MetadataService 稍微要復雜一點,有 remote
和 local
兩種模式。
類似于前面的 ServiceNameMapping,Dubbo-go 提供了基于配置中心的 MetadataService 的實現,即 remote
模式。Provider 啟動的時候,就會將服務的元數據寫進去。
另外一種模式是 local
模式。Dubbo-go 可以直接將 MetadataService 看做是一個普通的微服務,而后由 Provider
所提供。類似于:
由此帶來一個問題:
既然 Dubbo-go 將 MetadataService 看做是一個普通的服務,那么 MetadataService 的元數據,Consumer 該怎么獲得呢?這是一個典型的雞生蛋蛋生雞的問題。
Dubbo-go 的方案非常簡單粗暴,Provider 啟動的時候,不僅僅往注冊中心里面寫入應用本身的信息,還要把它的 MetadataService 信息寫入。
這是一個應用的注冊信息:
本質上來說,應用維度注冊信息 + 服務元數據 = 服務維度注冊信息。或者說,應用維度注冊,只是一種重新組織這些信息的方式。
Dubbo-go v1.5.x 對標 Dubbo 2.7.5,可以認為是參照 Dubbo 2.7.5 直接實現其 Go 源碼,但是考慮到 Java 和 Go 之間的語言差異,導致二者之間的實現不可能完全對等。
Dubbo v2.7.x 在 MetadataService 注冊時,會對其 provider 應用的所有服務接口的 hash 值做為修訂版本號寫入元數據中心,此 revision 是對所有接口的方法以及其參數總體的計算結果。其目的是減少 consumer 端到注冊中心的拉取次數。
在Go中用的計算 revision 的 hash 算法與 Java 是不一致的,而且 Go 與 Java 的方法簽名信息是不相同的,所以計算出來的 hash 值一定是不一樣的。
此不一致會導致如果Go應用和Java應用同時發布同一個服務的時候,Go服務和Java服務的修訂版本號必定是不相同的,Consumer需要分別緩存這兩個修訂版本的元數據。
Dubbo-go v1.5.0 實現時,其中一個考量是全面向后兼容 v1.4.x。Dubbo-go v1.5.x 應用 consumer 既可以調用 Dubbo-go v1.4.x 應用的服務,也可以調用 Dubbo v2.6.x 應用的服務,當然也可以調用其對標的 v2.7.x 應用的服務。
為了達到兼容性,Dubbo-go v1.5.x 實現時面臨一個問題:Dubbo-go provider 應用啟動時有一個服務啟動成功,把應用信息注冊到元數據中心之后,就會把實例注冊到注冊中心,而 Dubbo 2.7.x 的 provider 應用則是在其所有服務接口的信息注冊到元數據中心后才會注冊實例!
這個問題的后果就是:Dubbo-go v1.5.0 的 provider 每次發布接口到元數據中心的同時,都會觸發Dubbo-go v1.5.0 / Dubbo v2.7.x 的 consumer 應用拉取 Dubbo-go v1.5.0 應用信息,當provider 發布的服務過多時 consumer 側性能損耗非常明顯!
Dubbo-go 在 v1.5.1 中已經修復了這個問題,provider 在啟動時先將其全部服務接口發布到元數據中心,然后注冊實例到注冊中心,減少了 consumer 拉取元數據的次數。
感謝各位的閱讀,以上就是“Dubbo-go應用維度注冊模型怎么實現”的內容了,經過本文的學習后,相信大家對Dubbo-go應用維度注冊模型怎么實現這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。