本文來自于Dubbo官網(wǎng)累贤,作者為@lexburner:Dubbo2.7 三大新特性詳解,轉(zhuǎn)載請(qǐng)保留鏈接 ;)
1 背景介紹
自 2017 年 7 月阿里重啟 Dubbo 開源贴彼,到目前為止 github star 數(shù),contributor 數(shù)都有了非常大的提升糯累。2018 年 2 月 9 日阿里決定將 Dubbo 項(xiàng)目貢獻(xiàn)給 Apache栗弟,經(jīng)過一周的投票,順利成為了 Apache 的孵化項(xiàng)目规揪,也就是大家現(xiàn)在看到的 Incubator Dubbo桥氏。預(yù)計(jì)在 2019 年 4 月,Dubbo 可以達(dá)成畢業(yè)猛铅,成為 Apache 的頂級(jí)項(xiàng)目字支。
2 分支介紹
Dubbo 目前有如圖所示的 5 個(gè)分支,其中 2.7.1-release 只是一個(gè)臨時(shí)分支奸忽,忽略不計(jì)堕伪,對(duì)其他 4 個(gè)分支進(jìn)行介紹。
- 2.5.x 近期已經(jīng)通過投票栗菜,Dubbo 社區(qū)即將停止對(duì)其的維護(hù)欠雌。
- 2.6.x 為長(zhǎng)期支持的版本,也是 Dubbo 貢獻(xiàn)給 Apache 之前的版本疙筹,其包名前綴為:com.alibaba富俄,JDK 版本對(duì)應(yīng) 1.6禁炒。
- 3.x-dev 是前瞻性的版本,對(duì) Dubbo 進(jìn)行一些高級(jí)特性的補(bǔ)充霍比,如支持 rx 特性幕袱。
- master 為長(zhǎng)期支持的版本,版本號(hào)為 2.7.x悠瞬,也是 Dubbo 貢獻(xiàn)給 Apache 的開發(fā)版本凹蜂,其包名前綴為:org.apache,JDK 版本對(duì)應(yīng) 1.8阁危。
如果想要研究 Dubbo 的源碼玛痊,建議直接瀏覽 master 分支。
3 Dubbo 2.7 新特性
Dubbo 2.7.x 作為 Apache 的孵化版本狂打,除了代碼優(yōu)化之外擂煞,還新增了許多重磅的新特性,本文將會(huì)介紹其中最典型的三個(gè)新特性:
- 異步化改造
- 三大中心改造
- 服務(wù)治理增強(qiáng)
4 異步化改造
4.1 幾種調(diào)用方式
在遠(yuǎn)程方法調(diào)用中趴乡,大致可以分為這 4 種調(diào)用方式对省。oneway 指的是客戶端發(fā)送消息后,不需要接受響應(yīng)晾捏。對(duì)于那些不關(guān)心服務(wù)端響應(yīng)的請(qǐng)求蒿涎,比較適合使用 oneway 通信。
注意惦辛,void hello() 方法在遠(yuǎn)程方法調(diào)用中劳秋,不屬于 oneway 調(diào)用,雖然 void 方法表達(dá)了不關(guān)心返回值的語義胖齐,但在 RPC 層面玻淑,仍然需要做通信層的響應(yīng)。
sync 是最常用的通信方式呀伙,也是默認(rèn)的通信方法补履。
future 和 callback 都屬于異步調(diào)用的范疇,他們的區(qū)別是:在接收響應(yīng)時(shí)剿另,future.get() 會(huì)導(dǎo)致線程的阻塞;callback 通常會(huì)設(shè)置一個(gè)回調(diào)線程箫锤,當(dāng)接收到響應(yīng)時(shí),自動(dòng)執(zhí)行雨女,不會(huì)對(duì)當(dāng)前線程造成阻塞谚攒。
4.2 Dubbo 2.6 異步化
異步化的優(yōu)勢(shì)在于客戶端不需要啟動(dòng)多線程即可完成并行調(diào)用多個(gè)遠(yuǎn)程服務(wù),相對(duì)多線程開銷較小戚篙。介紹 2.7 中的異步化改造之前五鲫,先回顧一下如何在 2.6 中使用 Dubbo 異步化的能力。
- 將同步接口聲明成
async=true
<dubbo:reference id="asyncService" interface="org.apache.dubbo.demo.api.AsyncService" async="true"/>
public interface AsyncService { String sayHello(String name); }
- 通過上下文類獲取 future
AsyncService.sayHello("Han Meimei"); Future<String> fooFuture = RpcContext.getContext().getFuture(); fooFuture.get();
可以看出岔擂,這樣的使用方式位喂,不太符合異步編程的習(xí)慣浪耘,竟然需要從一個(gè)上下文類中獲取到 Future。如果同時(shí)進(jìn)行多個(gè)異步調(diào)用塑崖,使用不當(dāng)很容易造成上下文污染七冲。而且,F(xiàn)uture 并不支持 callback 的調(diào)用方式规婆。這些弊端在 Dubbo 2.7 中得到了改進(jìn)澜躺。
4.3 Dubbo 2.7 異步化
- 無需配置中特殊聲明,顯式聲明異步接口即可
public interface AsyncService { String sayHello(String name); default CompletableFuture<String> sayHiAsync(String name) { return CompletableFuture.completedFuture(sayHello(name)); } }
- 使用 callback 方式處理返回值
CompletableFuture<String> future = asyncService.sayHiAsync("Han MeiMei"); future.whenComplete((retValue, exception) -> { if (exception == null) { System.out.println(retValue); } else { exception.printStackTrace(); } });
Dubbo 2.7 中使用了 JDK1.8 提供的 CompletableFuture
原生接口對(duì)自身的異步化做了改進(jìn)抒蚜。CompletableFuture
可以支持 future 和 callback 兩種調(diào)用方式掘鄙,用戶可以根據(jù)自己的喜好和場(chǎng)景選擇使用,非常靈活嗡髓。
4.4 異步化設(shè)計(jì) FAQ
Q:如果 RPC 接口只定義了同步接口操漠,有辦法使用異步調(diào)用嗎?
A:2.6 中的異步調(diào)用唯一的優(yōu)勢(shì)在于饿这,不需要在接口層面做改造浊伙,又可以進(jìn)行異步調(diào)用,這種方式仍然在 2.7 中保留长捧;使用 Dubbo 官方提供的 compiler hacker嚣鄙,編譯期自動(dòng)重寫同步方法,請(qǐng)在此討論和跟進(jìn)具體進(jìn)展串结。
Q:關(guān)于異步接口的設(shè)計(jì)問題哑子,為何不提供編譯插件,根據(jù)原接口奉芦,自動(dòng)編譯出一個(gè) XxxAsync 接口赵抢?
A:Dubbo 2.7 采用過這種設(shè)計(jì),但接口的膨脹會(huì)導(dǎo)致服務(wù)類的增量發(fā)布声功,而且接口名的變化會(huì)影響服務(wù)治理的一些相關(guān)邏輯,改為方法添加 Async 后綴相對(duì)影響范圍較小宠叼。
Q:Dubbo 分為了客戶端異步和服務(wù)端異步先巴,剛剛你介紹的是客戶端異步,為什么不提服務(wù)端異步呢冒冬?
A:Dubbo 2.7 新增了服務(wù)端異步的支持伸蚯,但實(shí)際上,Dubbo 的業(yè)務(wù)線程池模型简烤,本身就可以理解為異步調(diào)用剂邮,個(gè)人認(rèn)為服務(wù)端異步的特性較為雞肋。
5 三大中心改造
三大中心指的:注冊(cè)中心横侦,元數(shù)據(jù)中心挥萌,配置中心绰姻。
在 2.7 之前的版本,Dubbo 只配備了注冊(cè)中心引瀑,主流使用的注冊(cè)中心為 zookeeper狂芋。新增加了元數(shù)據(jù)中心和配置中心,自然是為了解決對(duì)應(yīng)的痛點(diǎn)憨栽,下面我們來詳細(xì)闡釋三大中心改造的原因帜矾。
5.1 元數(shù)據(jù)改造
元數(shù)據(jù)是什么?元數(shù)據(jù)定義為描述數(shù)據(jù)的數(shù)據(jù)屑柔,在服務(wù)治理中屡萤,例如服務(wù)接口名,重試次數(shù)掸宛,版本號(hào)等等都可以理解為元數(shù)據(jù)死陆。在 2.7 之前,元數(shù)據(jù)一股腦丟在了注冊(cè)中心之中旁涤,這造成了一系列的問題:
推送量大 -> 存儲(chǔ)數(shù)據(jù)量大 -> 網(wǎng)絡(luò)傳輸量大 -> 延遲嚴(yán)重
生產(chǎn)者端注冊(cè) 30+ 參數(shù)翔曲,有接近一半是不需要作為注冊(cè)中心進(jìn)行傳遞;消費(fèi)者端注冊(cè) 25+ 參數(shù)劈愚,只有個(gè)別需要傳遞給注冊(cè)中心瞳遍。有了以上的理論分析,Dubbo 2.7 進(jìn)行了大刀闊斧的改動(dòng)菌羽,只將真正屬于服務(wù)治理的數(shù)據(jù)發(fā)布到注冊(cè)中心之中掠械,大大降低了注冊(cè)中心的負(fù)荷。
同時(shí)注祖,將全量的元數(shù)據(jù)發(fā)布到另外的組件中:元數(shù)據(jù)中心猾蒂。元數(shù)據(jù)中心目前支持 redis(推薦),zookeeper是晨。這也為 Dubbo 2.7 全新的 Dubbo Admin 做了準(zhǔn)備肚菠,關(guān)于新版的 Dubbo Admin,我將會(huì)后續(xù)準(zhǔn)備一篇獨(dú)立的文章進(jìn)行介紹罩缴。
示例:使用 zookeeper 作為元數(shù)據(jù)中心
<dubbo:metadata-report address="zookeeper://127.0.0.1:2181"/>
5.2 Dubbo 2.6 元數(shù)據(jù)
dubbo://30.5.120.185:20880/com.alibaba.dubbo.demo.DemoService?
anyhost=true&
application=demo-provider&
interface=com.alibaba.dubbo.demo.DemoService&
methods=sayHello&
bean.name=com.alibaba.dubbo.demo.DemoService&
dubbo=2.0.2&
executes=4500&
generic=false&
owner=kirito&
pid=84228&
retries=7&
side=provider&
timestamp=1552965771067
從本地的 zookeeper 中取出一條服務(wù)數(shù)據(jù)蚊逢,通過解碼之后,可以看出箫章,的確有很多參數(shù)是不必要烙荷。
5.3 Dubbo 2.7 元數(shù)據(jù)
在 2.7 中,如果不進(jìn)行額外的配置檬寂,zookeeper 中的數(shù)據(jù)格式仍然會(huì)和 Dubbo 2.6 保持一致终抽,這主要是為了保證兼容性,讓 Dubbo 2.6 的客戶端可以調(diào)用 Dubbo 2.7 的服務(wù)端。如果整體遷移到 2.7昼伴,則可以為注冊(cè)中心開啟簡(jiǎn)化配置的參數(shù):
<dubbo:registry address=“zookeeper://127.0.0.1:2181” simplified="true"/>
Dubbo 將會(huì)只上傳那些必要的服務(wù)治理數(shù)據(jù)匾旭,一個(gè)簡(jiǎn)化過后的數(shù)據(jù)如下所示:
dubbo://30.5.120.185:20880/org.apache.dubbo.demo.api.DemoService?
application=demo-provider&
dubbo=2.0.2&
release=2.7.0&
timestamp=1552975501873
對(duì)于那些非必要的服務(wù)信息,仍然全量存儲(chǔ)在元數(shù)據(jù)中心之中:
元數(shù)據(jù)中心的數(shù)據(jù)可以被用于服務(wù)測(cè)試亩码,服務(wù) MOCK 等功能季率。目前注冊(cè)中心配置中 simplified 的默認(rèn)值為 false,因?yàn)榭紤]到了遷移的兼容問題描沟,在后續(xù)迭代中飒泻,默認(rèn)值將會(huì)改為 true。
5.4 配置中心支持
衡量配置中心的必要性往往從三個(gè)角度出發(fā):
分布式配置統(tǒng)一管理
動(dòng)態(tài)變更推送
安全性
Spring Cloud Config, Apollo, Nacos 等分布式配置中心組件都對(duì)上述功能有不同程度的支持吏廉。在 2.7 之前的版本中泞遗,在 zookeeper 中設(shè)置了部分節(jié)點(diǎn):configurators,routers席覆,用于管理部分配置和路由信息史辙,它們可以理解為 Dubbo 配置中心的雛形。在 2.7 中佩伤,Dubbo 正式支持了配置中心聊倔,目前支持的幾種注冊(cè)中心 Zookeeper,Apollo生巡,Nacos(2.7.1-release 支持)耙蔑。
在 Dubbo 中,配置中心主要承擔(dān)了兩個(gè)作用
外部化配置孤荣。啟動(dòng)配置的集中式存儲(chǔ)
服務(wù)治理甸陌。服務(wù)治理規(guī)則的存儲(chǔ)與通知
示例:使用 Zookeeper 作為配置中心
<dubbo:config-center address="zookeeper://127.0.0.1:2181"/>
引入配置中心后,需要注意配置項(xiàng)的覆蓋問題盐股,優(yōu)先級(jí)如圖所示
6 服務(wù)治理增強(qiáng)
我更傾向于將 Dubbo 當(dāng)做一個(gè)服務(wù)治理框架钱豁,而不僅僅是一個(gè) RPC 框架。在 2.7 中疯汁,Dubbo 對(duì)其服務(wù)治理能力進(jìn)行了增強(qiáng)牲尺,增加了標(biāo)簽路由的能力,并抽象出了應(yīng)用路由和服務(wù)路由的概念幌蚊。在最后一個(gè)特性介紹中秸谢,著重對(duì)標(biāo)簽路由 TagRouter 進(jìn)行探討。
在服務(wù)治理中霹肝,路由層和負(fù)載均衡層的對(duì)比。區(qū)別 1塑煎,Router:m 選 n沫换,LoadBalance:n 選 1;區(qū)別 2,路由往往是疊加使用的讯赏,負(fù)載均衡只能配置一種垮兑。
在很長(zhǎng)的一段時(shí)間內(nèi),Dubbo 社區(qū)經(jīng)常有人提的一個(gè)問題是:Dubbo 如何實(shí)現(xiàn)流量隔離和灰度發(fā)布漱挎,直到 2.7 提供了標(biāo)簽路由系枪,用戶可以使用這個(gè)功能,來實(shí)現(xiàn)上述的需求磕谅。
標(biāo)簽路由提供了這樣一個(gè)能力私爷,當(dāng)調(diào)用鏈路為 A -> B -> C -> D 時(shí),用戶給請(qǐng)求打標(biāo)膊夹,最典型的打標(biāo)方式可以借助 attachment(他可以在分布式調(diào)用中傳遞下去)衬浑,調(diào)用會(huì)優(yōu)先請(qǐng)求那些匹配的服務(wù)端,如 A -> B放刨,C -> D工秩,由于集群中未部署 C 節(jié)點(diǎn),則會(huì)降級(jí)到普通節(jié)點(diǎn)进统。
打標(biāo)方式會(huì)收到集成系統(tǒng)差異的影響助币,從而導(dǎo)致很大的差異,所以 Dubbo 只提供了 RpcContext.getContext().setAttachment()
這樣的基礎(chǔ)接口螟碎,用戶可以使用 SPI 擴(kuò)展眉菱,或者 server filter 的擴(kuò)展,對(duì)測(cè)試流量進(jìn)行打標(biāo)抚芦,引導(dǎo)進(jìn)入隔離環(huán)境/灰度環(huán)境倍谜。
新版的 Dubbo Admin 提供了標(biāo)簽路由的配置項(xiàng):
Dubbo 用戶可以在自己系統(tǒng)的基礎(chǔ)上對(duì)標(biāo)簽路由進(jìn)行二次擴(kuò)展,或者借鑒標(biāo)簽路由的設(shè)計(jì)叉抡,實(shí)現(xiàn)自己系統(tǒng)的流量隔離尔崔,灰度發(fā)布。
7 總結(jié)
本文介紹了 Dubbo 2.7 比較重要的三大新特性:異步化改造褥民,三大中心改造季春,服務(wù)治理增強(qiáng)。Dubbo 2.7 還包含了很多功能優(yōu)化消返、特性升級(jí)载弄,可以在項(xiàng)目源碼的 CHANGES.md 中瀏覽全部的改動(dòng)點(diǎn)。最后提供一份 Dubbo 2.7 的升級(jí)文檔:2.7遷移文檔撵颊,歡迎體驗(yàn)宇攻。