淺析 Dubbo 3.0 中介面級地址推送性能的優化

来源:https://www.cnblogs.com/apache-dubbo/archive/2023/01/04/17024383.html
-Advertisement-
Play Games

向下相容特性是軟體開發系統的一個重要指標,它是指一個新的系統或者軟體能夠與舊的系統或軟體相容並正常運行。這意味著舊系統或軟體可以在新系統或軟體中使用,而不會出現問題。向下相容對於提高軟體或系統的可用性非常重要,因為它允許用戶在不更換舊系統或軟體的情況下使用新系統或軟體。 我們知道MacOS系統從Mo ...


URL 簡介

在闡述地址推送性能的具體優化之前,我們有必要先瞭解一下與之息息相關的內容 --- URL。

定義

在不談及 dubbo 時,我們大多數人對 URL 這個概念並不會感到陌生。統一資源定位器 (RFC1738――Uniform Resource Locators (URL))應該是最廣為人知的一個 RFC 規範,它的定義也非常簡單。

網際網路上的可用資源可以用簡單字元串來表示,該文檔就是描述了這種字元串的語法和語 義。而這些字元串則被稱為:“統一資源定位器”(URL)

一個標準的 URL 格式至多可以包含如下的幾個部分

protocol://username:password@host:port/path?key=value&key=value

一些典型 URL

http://www.facebook.com/friends?param1=value1&param2=value2
https://username:[email protected]:8080/list?version=1.0.0
ftp://username:[email protected]:21/1/read.txt

當然,也有一些不太符合常規的 URL,也被歸類到了 URL 之中

192.168.1.3:20880
url protocol = null, url host = 192.168.1.3, port = 20880, url path = null

file:///home/user1/router.js?type=script
url protocol = file, url host = null, url path = home/user1/router.js

file://home/user1/router.js?type=script<br>
url protocol = file, url host = home, url path = user1/router.js

file:///D:/1/router.js?type=script
url protocol = file, url host = null, url path = D:/1/router.js

file:/D:/1/router.js?type=script
同上 file:///D:/1/router.js?type=script

/home/user1/router.js?type=script
url protocol = null, url host = null, url path = home/user1/router.js

home/user1/router.js?type=script
url protocol = null, url host = home, url path = user1/router.js

Dubbo 中的 URL

在 dubbo 中,也使用了類似的 URL,主要用於在各個擴展點之間傳遞數據,組成此 URL 對象的具體參數如下:

  • protocol:一般是 dubbo 中的各種協議 如:dubbo thrift http zk

  • username/password:用戶名/密碼

  • host/port:主機/埠

  • path:介面名稱

  • parameters:參數鍵值對

    一些典型的 Dubbo URL

dubbo://192.168.1.6:20880/moe.cnkirito.sample.HelloService?timeout=3000
描述一個 dubbo 協議的服務

zookeeper://127.0.0.1:2181/org.apache.dubbo.registry.RegistryService?application=demo-consumer&dubbo=2.0.2&interface=org.apache.dubbo.registry.RegistryService&pid=1214&qos.port=33333&timestamp=1545721981946
描述一個 zookeeper 註冊中心

consumer://30.5.120.217/org.apache.dubbo.demo.DemoService?application=demo-consumer&category=consumers&check=false&dubbo=2.0.2&interface=org.apache.dubbo.demo.DemoService&methods=sayHello&pid=1209&qos.port=33333&side=consumer&timestamp=1545721827784
描述一個消費者

可以說,任意的一個領域中的一個實現都可以認為是一類 URL,dubbo 使用 URL 來統一描述了元數據,配置信息,貫穿在整個框架之中。

Dubbo 2.7

URL 結構

在 Dubbo 2.7 中,URL 的結構非常簡單,一個類就涵蓋了所有內容,如下圖所示。

Dubbo2 URL類圖.png

地址推送模型

接下來我們再來看看 Dubbo 2.7 中的地址推送模型方案,主要性能問題由下列過程引起。

Dubbo2 地址推送模型.png

上圖中主要的流程為
1、用戶新增/刪除DemoService的某個具體Provider實例(常見於擴容縮容、網路波動等原因)
2、ZooKeeper將DemoService下所有實例推送給Consumer端
3、Consumer端根據Zookeeper推送的數據重新全量生成URL
根據該方案可以看出在Provider實例數量較小時,Consumer端的影響比較小,但當某個介面有大量Provider實例時,便會有大量不必要的URL創建過程。
而Dubbo 3.0中則主要針對上述推送流程進行了一系列的優化,接下來我們便對其進行具體的講解。

Dubbo 3.0

URL 結構

當然,地址推送模型的優化依然離不開 URL 的優化,下圖是Dubbo 3.0中優化地址推送模型的過程中使用的新的URL結構。

Dubbo3 URL類圖.png

根據上圖我們可以看出,在 Dubbo 2.7 的 URL 中的幾個重要屬性在 Dubbo 3.0 中已經不存在了,取而代之的是 URLAddress 和 URLParam 兩個類。原來的 parameters 屬性被移動到了 URLParam 中的 params,其他的屬性則移動到了 URLAddress 及其子類中。
再來介紹 URL 新增的 3 個子類,其中 InstanceAddressURL 屬於應用級介面地址,本篇章中不做介紹。
而 ServiceConfigURL 及 ServiceAddressURL 主要的差別就是,ServiceConfigURL 是程式讀取配置文件時生成的 URL。而 ServiceAddressURL 則是註冊中心推送一些信息(如 providers)過來時生成的 URL。
在這裡我們順便提一下為什麼會有 DubboServiceAddressURL 這個子類,按照目前的結構來看,ServiceAddressURL 只有這一個子類,所以完全可以將他們兩個的屬性全都放到 ServiceAddressURL 中,那麼為什麼還要有這個子類呢?其實是 Dubbo 3.0 為了相容 HSF 框架所設計的,抽象出了一個 ServiceAddressURL,而 HSF 框架則可以繼承這個類,使用 HSFServiceAddressURL,當然,這個類目前沒有體現出來,所以此處我們簡單一提,不過多講解。
那麼,我們接下來就討論一下 Dubbo 3.0 為什麼要改為此種數據結構,並且該結構和地址推送模型的優化有何關聯性吧!

地址推送模型的優化

URL 結構上的優化

我們在上小節中的類圖裡看到雖然原來的屬性都被移到了 URLAddress 和 URLParam 里,但是 URL 的子類依然多了幾個屬性,這幾個屬性自然也是為了優化而新增的,那麼這裡就講講這幾個屬性的作用。
ServiceConfigURL:這個子類中新增了 attribute 這個屬性,這個屬性主要是針對 URLParam 的 params 做了冗餘,僅僅只是將 value 的類型從 String 改為了 Object,減少了代碼中每次獲取 parameters 的格式轉換消耗。
ServiceAddressURL:這個子類及其對應的其他子類中則新增了 overrideURL 和 consumerURL 屬性。其中 consumerURL 是針對 consumer 端的配置信息,overrideURL 則是在 Dubbo Admin 上進行動態配置時寫入的值,當我們調用 URL 的 getParameter() 方法時,優先順序為 overrideURL > consumerURL > urlParam。在 Dubbo 2.7 時,動態配置屬性會替換 URL 中的屬性,及當你有大量 URL 時消耗也是不可忽視的,而此處的 overrideURL 則避免了這種消耗,因為所有 URL 都會共同使用同一個對象。

多級緩存

緩存是 Dubbo 3.0 在 URL 上做的優化的重點,同時這部分也是直接針對地址推送模型所做的優化,那麼接下來我們就開始來介紹一下多級緩存的具體實現。
首先,多級緩存主要體現在 CacheableFailbackRegistry 這個類之中,它直接繼承於 FailbackRegistry,以 Zookeeper 為例,我們看看 Dubbo 2.7 和 Dubbo 3.0 繼承結構的區別。

Dubbo3 CacheableFailbackRegistry緩存.png

可以看到在 CacheableFailbackRegistry 緩存中,我們新增了 3 個緩存屬性 stringAddressstringParamstringUrls。我們通過下圖來描述這 3 個緩存的具體使用場景。

多級緩存.png

在該方案下,我們使用了 3 個緯度的緩存數據(URL 字元串緩存、URL 地址緩存、URL 參數緩存),這樣一來,在大部分情況下都能有效利用到緩存中的數據,減少了 Zookeeper 重覆通知的消耗。

延遲通知

除了上面提到的優化之外,其實另外還有兩個小小的優化。
第一個是解析 URL 時可以直接使用編碼後的 URL 字元串位元組進行解析,而在 Dubbo 2.7 中,所有編碼後的 URL 字元串都需要經過解碼才可以正常解析為 URL 對象。該方式也直接減少了 URL 解碼過程的開銷。
第二個則是 URL 變更後的通知機制增加了延遲,下圖以Zookeeper為例講解了實現細節。

延遲通知.png

在該方案中,當 Consumer 接收 Zookeeper 的變更通知後會主動休眠一段時間,而這段時間內的變更在休眠結束後只會保留最後一次變更,Consumer 便會使用最後一次變更來進行監聽實例的更新,以此方法來減少大量 URL 的創建開銷。

字元串重用

在舊版本實現中,不同的 URL 中屬性相同的字元串會存儲在堆內不同的地址中,如 protocol、path 等,當有大量 provider 的情況下,Consumer 端的堆內會存在大量的重覆字元串,導致記憶體利用率低下,所以此處提供了另一個優化方式,即字元串重用。
而它的實現方式也非常的簡單,讓我們來看看對應的代碼片段。

public class URLItemCache {
    private static final Map<String, String> PATH_CACHE = new LRUCache<>(10000);
    private static final Map<String, String> PROTOCOL_CACHE = new ConcurrentHashMap<>();

    // 省略無關代碼片段

    public static String checkProtocol(String _protocol) {
        if (_protocol == null) {
            return _protocol;
        }
        String cachedProtocol = PROTOCOL_CACHE.putIfAbsent(_protocol, _protocol);
        if (cachedProtocol != null) {
            return cachedProtocol;
        }
        return _protocol;
    }

    public static String checkPath(String _path) {
        if (_path == null) {
            return _path;
        }
        String cachedPath = PATH_CACHE.putIfAbsent(_path, _path);
        if (cachedPath != null) {
            return cachedPath;
        }
        return _path;
    }
}

由如上代碼片段可以得知,字元串重用即為簡單地使用了 Map 來存儲對應的緩存值,當你使用了相同的字元串時,便會從 Map 中獲取早已存在的對象返回給調用方,由此便可以減少堆記憶體中重覆的字元串數以達到優化的效果。

優化結果

這裡優化結果我引用了《Dubbo 3.0 前瞻:服務發現支持百萬集群,帶來可伸縮微服務架構》這篇文章中的兩副圖來說明,下圖模擬了在220萬個 Provider 介面的情況下,介面數據不斷變更導致的 Consumer 端的消耗,我們看到整個 Consumer 端幾乎被 Full GC 占滿了,嚴重影響了性能。

Dubbo2 介面級地址模型.png

那麼我們再來看看 Dubbo 3.0 中對 URL 進行優化後同一個環境下的壓測結果,如下圖所示。

Dubbo3 介面級地址模型.png

我們明顯可以看到 Full GC 的頻率減少到了只有 3 次,大大提升了性能。當然,該文章中還有其他方面的對比,此處便不一一引用了,感興趣的讀者可以自行去閱讀該文章。

歡迎在 https://github.com/apache/dubbo 給 Dubbo Star。
搜索關註官方微信公眾號:Apache Dubbo,瞭解更多業界最新動態,掌握大廠面試必備 Dubbo 技能


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 我是車轍,我的掘金小冊《SkyWalking:應用監控和鏈路跟蹤》已經上線啦,這是我的第一本電子書,歡迎大家訂閱。 大家好,我是車轍。在完成小冊後的一段時間,我突然想開發一款個人H5產品。在起初有這樣想法的時候,內心其實還是有不少糾結的。 大家都知道,雖然我是電腦專業,但我從畢業到現在工作4年時間 ...
  • 通過學習C++11移動構造函數我們知道,C++11 標準中藉助右值引用可以為指定類添加移動構造函數,這樣當使用該類的右值對象(可以理解為臨時對象)初始化同類對象時,編譯器會優先選擇移動構造函數。 需要註意,移動構造函數的調用時機是:用同類的右值對象初始化新對象。那麼,用當前類的左值對象(有名稱,能獲 ...
  • Spring Boot常見問題 昔日齷齪不足誇,今朝放蕩思無涯。 1、什麼是 Spring Boot? Spring Boot 是 Spring 開源組織下的子項目,是 Spring 組件一站式解決方案。 主要是簡化了使用Spring 的難度,簡省了繁重的配置,提供了各種啟動器,使開發者能快速上手。 ...
  • 現在的年輕人都開始每天保溫杯里泡枸杞,這怎麼能行呢? 想要每天過的好,美女必然少不了,每天看美女,只為了愉悅心情,心情好了,才長壽。 於是懷揣著愉悅心情的想法,我開始製作GIF動圖生成器,想要用Python來做成美女壁紙,行動起來。 這個小工具製作的目的是為了將多張圖片組合後生成一張動態的GIF圖片 ...
  • 摘要:本文主要講解常見的圖像銳化和邊緣檢測方法,即Roberts運算元和Prewitt運算元。 本文分享自華為雲社區《[Python從零到壹] 五十七.圖像增強及運算篇之圖像銳化Roberts、Prewitt運算元實現邊緣檢測》,作者: eastmount。 一.圖像銳化 由於收集圖像數據的器件或傳輸圖像 ...
  • 提到新版本,我們往往會首先想到服務端架構的設計變動,很容易忽略客戶端的設計理念。 客戶端也是消息產品的必要組成部分,許多特性需要 client 與 server 兩端互相協作,才能更好地實現。 而輕量化、雲原生、統一模型是 RocketMQ 5.0 客戶端的三個最為重要的設計理念。 ...
  • 1、Stream 與 Channel stream 不會自動緩衝數據,channel 會利用系統提供的發送緩衝區、接收緩衝區(更為底層) stream 僅支持阻塞 API,channel 同時支持阻塞、非阻塞 API,網路 channel 可配合 selector 實現多路復用 二者均為全雙工,即讀 ...
  • 我國目前並未出台專門針對網路爬蟲技術的法律規範,但在司法實踐中,相關判決已屢見不鮮,K 哥特設了“K哥爬蟲普法”專欄,本欄目通過對真實案例的分析,旨在提高廣大爬蟲工程師的法律意識,知曉如何合法合規利用爬蟲技術,警鐘長鳴,做一個守法、護法、有原則的技術人員。 案情介紹 據魔蝎科技官網(現已無法打開)介 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...