自從 2011 年 Dubbo 開源之后,被大量中小公司采用,,一直是國內(nèi)最受歡迎的 RPC 框架,。2014年 由于阿里內(nèi)部組織架構(gòu)調(diào)整,Dubbo 暫停維護了一段時間,,之后隨著 Spring Cloud 的面世,,兩個體系在融合中一起助推了微服務(wù)的火熱。 不過這世界變化快,,自從以 docker 為代表的的容器技術(shù)和以 k8s 為代表的容器編排技術(shù)登上舞臺之后,,云原生時代到來了。在云原生時代,,不可變的基礎(chǔ)設(shè)施給原有的中間件帶來的了不可變的中間件基礎(chǔ)設(shè)施:gRPC 統(tǒng)一了底層通信層,,protobuf 統(tǒng)一了序列化協(xié)議,以 envoy + istio 為代表的 service mesh 逐漸統(tǒng)一了服務(wù)的控制面與數(shù)據(jù)面,。 dubbogo 的天然使命是:Bridging the gap between Java and Go,。保持 Go 應(yīng)用與 Java 應(yīng)用互聯(lián)互通的同時,借助 Go 語言(事實上的遠程桌面第一云原生語言)的優(yōu)勢擁抱云原生時代,。dubbogo 社區(qū) 2020 年勠力打造三支箭:已經(jīng)發(fā)布的對齊 dubbo 2.7 的 dubbogo v1.5 版本,、近期將要發(fā)布的 sidecar 形態(tài)的 dubbo-go-proxy 項目 以及 處于進行時的 dubbogo 3.0。 用一句話概括 dubbogo 3.0 即是:新通信協(xié)議,、新序列化協(xié)議,、新應(yīng)用注冊模型以及新的服務(wù)治理能力,!本文主要著重討論 dubbogo 3.0 的新通信協(xié)議和應(yīng)用級服務(wù)注冊發(fā)現(xiàn)模型,。 1. dubbogo 3.0 vs gRPC 知己知彼,方能進步。dubbogo 3.0 的通信層改進主要借鑒了 gRPC,。 簡單來說就是http2協(xié)議的基礎(chǔ)之上,,增加了特定的協(xié)議header:“grpc-”開頭的header字段,采用特定的打解包工具(protobuf)對數(shù)據(jù)進行序列化,,從而實現(xiàn)RPC調(diào)用,。 眾所周知,gRPC 幾乎沒有服務(wù)治理能力,,而阿里云現(xiàn)有 dubbo 框架兼具 RPC 和服務(wù)治理能力,,整體實力不遜于 gRPC。但“大家都用gRPC” 這樣的背景之下,,dubbogo 3.0 的新通信協(xié)議就必須完美兼容 gRPC,,對開發(fā)者已部署的服務(wù)完全兼容,并在此基礎(chǔ)之上延續(xù)已有 dubbo 協(xié)議和服務(wù)治理能力,,進而推出一系列新策略:比如mesh支持,、應(yīng)用級服務(wù)注冊等。 2. dubbogo 3.0 vs dubbogo 1.5 目前已有的 dubbo 2.7 協(xié)議已經(jīng)盡可能實現(xiàn)了 gRPC 的支持,。開發(fā)者可以通過 protoc-gen-dubbo 工具將 pb IDL 協(xié)議轉(zhuǎn)換為框架支持的 stub,,再借助底層 gRPC conn 的 RPC 過程,將已有的服務(wù)治理能力自上而下傳遞給了 gRPC,,因此實現(xiàn)了 gRPC 服務(wù)的支持,。 dubbo-go v1.5.x 也支持 gRPC 的 Stream 調(diào)用。和 unary RPC 類似,,通過產(chǎn)生框架支持的 stub,,在底層gRPC stream 調(diào)用的基礎(chǔ)之上,將流式 RPC 的能力和并入框架,。但由于 dubbo v2.7.x / dubbo-go v1.5.x 本身并不支持流式調(diào)用,,所以沒有對 gRPC stream 調(diào)用的進行上層服務(wù)治理支持。 開發(fā)者所面臨的問題就是:我們在使用dubbo-go2.7進行g(shù)rpc協(xié)議傳輸?shù)臅r候,,或多或少不是那么放心,。 而即將推出的 dubbo-go 3.0 協(xié)議將從根源解決這個問題。 3. 協(xié)議兼容的三種層次 筆者認為,,一款服務(wù)框架對于第三方協(xié)議的支持可分為三個程度:應(yīng)用層次,、協(xié)議層次、傳輸層次,。 一款框架如果在一個協(xié)議的 sdk 之上封裝接口,,可以認為它處于應(yīng)用層次支持,這樣的框架需要遵循下層 sdk 的接口,,可擴展性較差,。 處于協(xié)議層次的框架,,從配置層到服務(wù)治理層均由本框架提供,而在此之下的協(xié)議層到網(wǎng)絡(luò)傳輸層均使用某個固定的通信協(xié)議,,這樣的框架可以解決服務(wù)治理的問題,,但框架本身無法與第三方協(xié)議完全適配,如果不適配就會出現(xiàn)對第三方協(xié)議支持的削弱,,比如上面說到的 dubbo-go 1.5 對 stream rpc 支持的缺陷,。 如果想進一步支持更多的第三方協(xié)議,需要從傳輸層下手,,真正了解第三方協(xié)議的具體字段,、所依賴的底層協(xié)議(比如 HTTP2)的幀模型和數(shù)據(jù)流,再開發(fā)出與第三方協(xié)議完全一致的數(shù)據(jù)交互模塊,,作為本框架的底層,。這樣做的好處是最大程度賦予了協(xié)議的可擴展性,可以在兼容已有協(xié)議的基礎(chǔ)之上,,可選地增加開發(fā)者需要的字段,,從而實現(xiàn)已有協(xié)議無法實現(xiàn)的功能,就比如 dubbogo 3.0 將支持的反壓策略,。 4. 基于 HTTP2 的通信流程 gRPC 一次基于 HTTP2 的 unary rpc 調(diào)用傳輸主要流程如下: client 發(fā)送 Magic 信息 PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n server 收到并檢查是否正確 client 和 server 互相發(fā)送 setting 幀,,收到后發(fā)送ACK 確認 client 發(fā)送 Header 幀,包含 gRPC 協(xié)議字段,,以 End Headers 作為 Header 結(jié)束標志 client 緊接著發(fā)送 Data 幀,,包含 RPC 調(diào)用的 request 信息,以 End Stream 作為 Data 結(jié)束標志 server 調(diào)用函數(shù)獲得結(jié)果 server 發(fā)送 Header 幀,,包含 gRPC 協(xié)議字段,,以 End Headers 作為 Header 結(jié)束標志 server 緊接著發(fā)送Data幀,包含 RPC 調(diào)用回傳的 response 信息 server 緊接著再次發(fā)送 Header 幀,,包含 RPC 狀態(tài)和 message 信息,,以 End Stream 作為本次 RPC 調(diào)用結(jié)束標志 另外,在 gRPC 的 stream 調(diào)用中,,可在 server 端回傳的過程中發(fā)送多次 Data,,調(diào)用結(jié)束后再發(fā)送 Header 終止 RPC 過程,并匯報狀態(tài)信息,。 dubbogo 3.0 的通信層將在 HTTP2 通信協(xié)議之上采用同樣的通信流程,,以保證與 gRPC 的底層通信溝通能力。 5. dubbogo 3.0 預(yù)期通信架構(gòu) 除了通信協(xié)議采用 HTTP2 外,,dubbogo 3.0 將采用 基于 google protobuf 的 triple 協(xié)議【下面稱為 dubbo3 協(xié)議】作為 dubbogo 3.0 的序列化協(xié)議,,為 dubbo 將來支持更多的編程語言打下通信協(xié)議層面的基礎(chǔ)。 目前設(shè)計的 dubbogo 3.0 傳輸模型 為保證同時支持 unary RPC 和 stream RPC,,在 server 端和 client 端增加數(shù)據(jù)流結(jié)構(gòu),,以異步調(diào)用的形式完成數(shù)據(jù)傳遞,。 繼續(xù)支持原有的 TCP 通信能力 在 HTTP2 的通信協(xié)議之上支持 dubbo3協(xié)議,decode 過程兼容 gRPC 使用的的 protobuf,,保證與 gRPC 服務(wù)打通,。 6. 應(yīng)用級服務(wù)注冊發(fā)現(xiàn) 6.1 應(yīng)用級服務(wù)注冊發(fā)現(xiàn)介紹 dubbogo 3.0 使用的新一代服務(wù)注冊發(fā)現(xiàn)體系,,將摒棄舊版的“接口級注冊發(fā)現(xiàn)”,,使用“應(yīng)用級別注冊發(fā)現(xiàn)”。 簡單地說,,接口級別注冊發(fā)現(xiàn),,在注冊中心中以 RPC 服務(wù)為key,以實例列表作為 value 來組織數(shù)據(jù)的,,而我們新引入的“應(yīng)用粒度的服務(wù)發(fā)現(xiàn)”,,它以應(yīng)用名(Application)作為 key,以這個應(yīng)用部署的一組實例(Instance)列表作為 value,。這帶來兩點不同: 數(shù)據(jù)映射關(guān)系變了,,從 RPC Service -> Instance 變?yōu)?Application -> Instance 數(shù)據(jù)變少了,注冊中心沒有了 RPC Service 及其相關(guān)配置信息 可以認為,,基于應(yīng)用粒度的模型所存儲和推送的數(shù)據(jù)量是和應(yīng)用,、實例數(shù)成正比的,只有當我們的應(yīng)用數(shù)增多或應(yīng)用的實例數(shù)增長時,,地址推送壓力才會上漲,。 而對于基于接口粒度的模型,數(shù)據(jù)量是和接口數(shù)量正相關(guān)的,,鑒于一個應(yīng)用通常發(fā)布多個接口的現(xiàn)狀,,其數(shù)量級一般是比應(yīng)用粒度的數(shù)十倍。另外一個關(guān)鍵點在于,,接口的定義更多的是業(yè)務(wù)側(cè)的內(nèi)部行為,,接口粒度導(dǎo)致的集群規(guī)模評估的不透明,而實例,、應(yīng)用增長都通常是在運維側(cè)的規(guī)劃之中,,可控性較好。 工商銀行曾經(jīng)對這兩個模型進行生產(chǎn)測算:應(yīng)用級服務(wù)注冊模型可以讓注冊中心上的數(shù)據(jù)量變成原來的 1.68%,,新模型可以讓 zookeeper 輕松至成 10 萬級別的服務(wù)量和 10 萬級別的節(jié)點量,。 6.2 元數(shù)據(jù)中心同步機制的引入 數(shù)據(jù)中心的數(shù)據(jù)量變少所造成的結(jié)果,是RPC 服務(wù)相關(guān)的數(shù)據(jù)在注冊中心消失了,,只有 application - instance 這兩個層級的數(shù)據(jù),。為了保證這部分缺少的 RPC 服務(wù)數(shù)據(jù)仍然能被 Consumer 端正確的感知,我們在 Consumer 和 Provider 間建立了一條單獨的通信通道,,目前針對元數(shù)據(jù)同步有兩種具體的可選方案,,分別是: 內(nèi)建 MetadataService,。 獨立的元數(shù)據(jù)中心,通過中細化的元數(shù)據(jù)集群協(xié)調(diào)數(shù)據(jù),。 |
|