自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Dubbo3.0 阿里大規(guī)模實踐解析—URL 重構(gòu)

精選
網(wǎng)絡(luò) 網(wǎng)絡(luò)管理
要支撐阿里百萬集群級實例和雙十一萬億級服務(wù)調(diào)用,性能提升一直是 Dubbo3.0 關(guān)注的重點,在本篇文章中,我們將簡要介紹 Dubbo3.0 性能優(yōu)化的關(guān)鍵一環(huán)——URL 重構(gòu)。

一、URL 簡介

在闡述地址推送性能的具體優(yōu)化之前,我們有必要先了解一下與之息息相關(guān)的內(nèi)容—— URL。

1.定義

在不談及 Dubbo 時,我們大多數(shù)人對 URL 這個概念并不會感到陌生。統(tǒng)一資源定位器 (RFC1738――Uniform Resource Locators (URL))應(yīng)該是最廣為人知的一個 RFC 規(guī)范,它的定義也非常簡單。

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

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

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

一些典型 URL:

http://www.facebook.com/friends?param1=value1&param2=value2
https://username:password@10.20.130.230:8080/list?version=1.0.0
ftp://username:password@192.168.1.7:21/1/read.txt

當然,也有一些不太符合常規(guī)的 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

2.Dubbo 中的 URL

在Dubbo 中,也使用了類似的 URL,主要用于在各個擴展點之間傳遞數(shù)據(jù),組成此 URL 對象的具體參數(shù)如下:

  1. protocol:一般是 Ddubbo 中的各種協(xié)議 如:Dubbo thrift http zk。
  2. username/password:用戶名/密碼。
  3. host/port:主機/端口。
  4. path:接口名稱。
  5. parameters:參數(shù)鍵值對。

一些典型的 Dubbo URL

dubbo://192.168.1.6:20880/moe.cnkirito.sample.HelloService?timeout=3000
描述一個 dubbo 協(xié)議的服務(wù)

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
描述一個消費者

可以說,任意的一個領(lǐng)域中的一個實現(xiàn)都可以認為是一類 URL,Dubbo 使用 URL 來統(tǒng)一描述了元數(shù)據(jù),配置信息,貫穿在整個框架之中。

二、Dubbo 2.7

1.URL 結(jié)構(gòu)

在 Dubbo 2.7 中,URL 的結(jié)構(gòu)非常簡單,一個類就涵蓋了所有內(nèi)容,如下圖所示。


2.地址推送模型

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


上圖中主要的流程為:

(1)用戶新增/刪除 DemoService 的某個具體 Provider 實例(常見于擴容縮容、網(wǎng)絡(luò)波動等原因);

(2)ZooKeeper 將 DemoService 下所有實例推送給 Consumer 端;

(3)Consumer 端根據(jù) Zookeeper 推送的數(shù)據(jù)重新全量生成 URL。

根據(jù)該方案可以看出在 Provider 實例數(shù)量較小時,Consumer 端的影響比較小,但當某個接口有大量 Provider 實例時,便會有大量不必要的 URL 創(chuàng)建過程。

而 Dubbo 3.0 中則主要針對上述推送流程進行了一系列的優(yōu)化,接下來我們便對其進行具體的講解。

三、Dubbo 3.0

1.URL 結(jié)構(gòu)

當然,地址推送模型的優(yōu)化依然離不開 URL 的優(yōu)化,下圖是 Dubbo 3.0 中優(yōu)化地址推送模型的過程中使用的新的 URL 結(jié)構(gòu)。


根據(jù)上圖我們可以看出,在 Dubbo 2.7 的 URL 中的幾個重要屬性在 Dubbo 3.0 中已經(jīng)不存在了,取而代之的是 URLAddress 和 URLParam 兩個類。原來的 parameters 屬性被移動到了 URLParam 中的 params,其他的屬性則移動到了 URLAddress 及其子類中。

再來介紹 URL 新增的 3 個子類,其中 InstanceAddressURL 屬于應(yīng)用級接口地址,本篇章中不做介紹。

而 ServiceConfigURL 及 ServiceAddressURL 主要的差別就是,ServiceConfigURL 是程序讀取配置文件時生成的 URL。而 ServiceAddressURL 則是注冊中心推送一些信息(如 providers)過來時生成的 URL。

在這里我們順便提一下為什么會有 DubboServiceAddressURL 這個子類,按照目前的結(jié)構(gòu)來看,ServiceAddressURL 只有這一個子類,所以完全可以將他們兩個的屬性全都放到 ServiceAddressURL 中,那么為什么還要有這個子類呢?其實是 Dubbo 3.0 為了兼容 HSF 框架所設(shè)計的,抽象出了一個 ServiceAddressURL,而 HSF 框架則可以繼承這個類,使用 HSFServiceAddressURL,當然,這個類目前沒有體現(xiàn)出來,所以此處我們簡單一提,不過多講解。

那么,我們接下來就討論一下 Dubbo 3.0 為什么要改為此種數(shù)據(jù)結(jié)構(gòu),并且該結(jié)構(gòu)和地址推送模型的優(yōu)化有何關(guān)聯(lián)性吧!

2.地址推送模型的優(yōu)化

  • URL 結(jié)構(gòu)上的優(yōu)化

我們在上小節(jié)中的類圖里看到雖然原來的屬性都被移到了 URLAddress 和 URLParam 里,但是 URL 的子類依然多了幾個屬性,這幾個屬性自然也是為了優(yōu)化而新增的,那么這里就講講這幾個屬性的作用。

ServiceConfigURL:這個子類中新增了 attribute 這個屬性,這個屬性主要是針對 URLParam 的 params 做了冗余,僅僅只是將 value 的類型從 String 改為了 Object,減少了代碼中每次獲取 parameters 的格式轉(zhuǎn)換消耗。

ServiceAddressURL:這個子類及其對應(yīng)的其他子類中則新增了 overrideURL 和 consumerURL 屬性。其中 consumerURL 是針對 consumer 端的配置信息,overrideURL 則是在 Dubbo Admin 上進行動態(tài)配置時寫入的值,當我們調(diào)用 URL 的 getParameter() 方法時,優(yōu)先級為 overrideURL > consumerURL > urlParam。在 Dubbo 2.7 時,動態(tài)配置屬性會替換 URL 中的屬性,及當你有大量 URL 時消耗也是不可忽視的,而此處的 overrideURL 則避免了這種消耗,因為所有 URL 都會共同使用同一個對象。

  • 多級緩存

緩存是 Dubbo 3.0 在 URL 上做的優(yōu)化的重點,同時這部分也是直接針對地址推送模型所做的優(yōu)化,那么接下來我們就開始來介紹一下多級緩存的具體實現(xiàn)。

首先,多級緩存主要體現(xiàn)在 CacheableFailbackRegistry 這個類之中,它直接繼承于 FailbackRegistry,以 Zookeeper 為例,我們看看 Dubbo 2.7 和 Dubbo 3.0 繼承結(jié)構(gòu)的區(qū)別。


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

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

  • 延遲通知

除了上面提到的優(yōu)化之外,其實另外還有兩個小小的優(yōu)化。

第一個是解析 URL 時可以直接使用編碼后的 URL 字符串字節(jié)進行解析,而在 Dubbo 2.7 中,所有編碼后的 URL 字符串都需要經(jīng)過解碼才可以正常解析為 URL 對象。該方式也直接減少了 URL 解碼過程的開銷。

第二個則是 URL 變更后的通知機制增加了延遲,下圖以Zookeeper為例講解了實現(xiàn)細節(jié)。


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

  • 字符串重用

在舊版本實現(xiàn)中,不同的 URL 中屬性相同的字符串會存儲在堆內(nèi)不同的地址中,如 protocol、path 等,當有大量 provider 的情況下,Consumer 端的堆內(nèi)會存在大量的重復(fù)字符串,導(dǎo)致內(nèi)存利用率低下,所以此處提供了另一個優(yōu)化方式,即字符串重用。

而它的實現(xiàn)方式也非常的簡單,讓我們來看看對應(yīng)的代碼片段。

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

// 省略無關(guān)代碼片段

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 來存儲對應(yīng)的緩存值,當你使用了相同的字符串時,便會從 Map 中獲取早已存在的對象返回給調(diào)用方,由此便可以減少堆內(nèi)存中重復(fù)的字符串數(shù)以達到優(yōu)化的效果。

3.優(yōu)化結(jié)果

這里優(yōu)化結(jié)果我引用了《Dubbo 3.0 前瞻:服務(wù)發(fā)現(xiàn)支持百萬集群,帶來可伸縮微服務(wù)架構(gòu)》這篇文章中的兩副圖來說明,下圖模擬了在 220 萬個 Provider 接口的情況下,接口數(shù)據(jù)不斷變更導(dǎo)致的 Consumer 端的消耗,我們看到整個 Consumer 端幾乎被 Full GC 占滿了,嚴重影響了性能。

那么我們再來看看 Dubbo 3.0 中對 URL 進行優(yōu)化后同一個環(huán)境下的壓測結(jié)果,如下圖所示。



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

作者介紹:

吳治國,Apache Dubbo 社區(qū)活躍貢獻者

責(zé)任編輯:武曉燕 來源: 阿里巴巴中間件
相關(guān)推薦

2021-08-09 10:21:42

云原生Dubbo3.0 服務(wù)治理

2021-04-22 13:38:21

前端開發(fā)技術(shù)

2014-07-15 13:41:41

阿里云可信云

2016-12-14 11:44:25

阿里Docker大數(shù)據(jù)

2015-07-09 16:35:02

2023-06-28 08:23:41

搜索語義模型

2024-01-30 07:56:57

2018-02-27 08:39:47

圖譜數(shù)據(jù)存儲

2021-09-06 09:46:26

Dubbo 服務(wù)端開發(fā)

2013-03-22 14:44:52

大規(guī)模分布式系統(tǒng)飛天開放平臺

2016-01-12 14:59:40

分布式存儲分布式存儲架構(gòu)

2022-07-07 11:00:09

美團模型實踐

2025-03-06 10:33:04

2023-05-26 08:39:44

深度學(xué)習(xí)Alluxio

2021-09-06 11:15:05

數(shù)據(jù)治理字節(jié)跳動埋點

2014-06-20 10:34:20

阿里云帶寬數(shù)據(jù)中心

2020-06-10 10:00:53

Serverless數(shù)據(jù)處理函數(shù)

2016-04-15 00:43:13

2023-04-04 07:32:35

TorchRec模型訓(xùn)練

2023-01-11 21:11:37

RabbitMQRocketMQ消息中間件
點贊
收藏

51CTO技術(shù)棧公眾號