在過去持續(xù)分享的幾十期阿里Java面試題中,幾乎每次都會問到Dubbo相關(guān)問題,比如:“如何從0到1設計一個Dubbo的RPC框架”,這個問題主要考察以下幾個方面:
你對RPC框架的底層原理掌握程度。
以及考驗你的整體RPC框架系統(tǒng)設計能力。
具體,mike來為大家詳解。
RPC和RPC框架
1.RPC(Remote Procedure Call)
即遠程過程調(diào)用, 主要解決遠程通信間的問題,不需要了解底層網(wǎng)絡的通信機制。
2.RPC框架
RPC框架負責屏蔽底層的傳輸方式(TCP或者UDP)、序列化方式、以及通信細節(jié)。
實際使用中,并不需要關(guān)心底層通信細節(jié)和調(diào)用過程,讓業(yè)務端專注于業(yè)務代碼的實現(xiàn)。
國內(nèi)大家熟知的PRC框架,阿里的HSF和Dubbo(開源)。
Dubbo的發(fā)展由來
1. 業(yè)務規(guī)模小
比如早期一個應用Java War包,將所有功能都打包,部署在一個單機服務器,調(diào)用接口也比較方便,不涉及到任何分布式場景。

2.業(yè)務規(guī)模變大
隨著業(yè)務的快速發(fā)展,業(yè)務越來越多、子系統(tǒng)也越來越多時。比如:淘寶的交易系統(tǒng)、商品系統(tǒng)、用戶系統(tǒng)、評價系統(tǒng)...上百個系統(tǒng)的出現(xiàn)。
系統(tǒng)變得越來越復雜,業(yè)務代碼依然耦合在一起。比如最早期的淘寶denali工程,包含所有業(yè)務系統(tǒng)的代碼,就僅打包部署都需要很長的時間。
并且,隨著每個業(yè)務線的快速發(fā)展,業(yè)務代碼耦合在一起,上線后出現(xiàn)問題急需要回滾代碼,拉分支、大量的代碼merge工作,這個過程極其痛苦。
這個時候,你會發(fā)現(xiàn)技術(shù)已經(jīng)成了業(yè)務的瓶頸,急需把業(yè)務單獨抽離出來,各自單獨部署。
3.Dubbo和HSF的出現(xiàn)
應用系統(tǒng)一旦涉及到拆分部署,問題就來了,急需一種高效的應用程序間的通訊手段來完成這種需求,這就會涉及到分布式遠程調(diào)用。
于是,淘寶就把denali按照業(yè)務為單位拆分成了類似這樣的系統(tǒng):UM(UserManger)、SM(ShopManager)..等等幾十個工程代碼。
再按照業(yè)務為單位,把所有調(diào)用相關(guān)的接口以業(yè)務為單元進行拆分:UIC(用戶中心服務)、SIC(店鋪中心服務)...等等以業(yè)務為單位集群部署,按照業(yè)務提供服務。

所以,RPC的框架來了,阿里內(nèi)部使用HSF,以及開源的RPC 框架:Dubbo。
RPC框架的核心設計
前面提到了RPC的核心目標:主要是解決分布式系統(tǒng)中服務之間的調(diào)用問題。
其實,走到這一步涉及的知識體系非常的多:要求對通信、遠程調(diào)用、消息機制等有深入的理解和掌握,要求的都是從理論、硬件級、操作系統(tǒng)級以及所采用的語言的實現(xiàn)都有清楚的理解。
1.RPC框架三個核心角色

1)服務提供者(Server)
對外提供后臺服務,將自己的服務信息,注冊到注冊中心。
2)注冊中心(Registry)
用于服務端注冊遠程服務以及客戶端發(fā)現(xiàn)服務。
目前主要的注冊中心可以借由 zookeeper,eureka,consul,etcd 等開源框架實現(xiàn)。
比如:阿里的Dubbo就是采用zookeeper實現(xiàn)注冊中心。
3)服務消費者(Client)
從注冊中心獲取遠程服務的注冊信息,然后進行遠程過程調(diào)用。
2.RPC遠程調(diào)用過程

1)服務調(diào)用方(client)調(diào)用以本地調(diào)用方式調(diào)用服務;
2)client stub接收到調(diào)用后負責將方法、參數(shù)等組裝成能夠進行網(wǎng)絡傳輸?shù)南Ⅲw;在Java里就是序列化的過程
3)client stub找到服務地址,并將消息通過網(wǎng)絡發(fā)送到服務端;
4)server stub收到消息后進行解碼,在Java里就是反序列化的過程;
5)server stub根據(jù)解碼結(jié)果調(diào)用本地的服務;
6)本地服務執(zhí)行處理邏輯;
7)本地服務將結(jié)果返回給server stub;
8)server stub將返回結(jié)果打包成消息,Java里的序列化;
9)server stub將打包后的消息通過網(wǎng)絡并發(fā)送至消費方
10)client stub接收到消息,并進行解碼, Java里的反序列化;
11)服務調(diào)用方(client)得到最終結(jié)果。
RPC框架的目標就是要2~10這些步驟都封裝起來。
RPC框架涉及技術(shù)
1.建立通信
首先,要解決通訊的問題,主要是通過在客戶端和服務器之間建立TCP連接,遠程過程調(diào)用的所有交換的數(shù)據(jù)都在這個連接里傳輸。
2.服務尋址
1)服務注冊
首先需要把服務注冊到服務中心。其實就是在注冊中心進行一個登記,注冊中心存儲了該服務的IP、端口、調(diào)用方式(協(xié)議、序列化方式)等。在zookeeper中,進行服務注冊,實際上就是在zookeeper中創(chuàng)建了一個znode節(jié)點,該節(jié)點存儲了上面所說的服務信息。
2)服務發(fā)現(xiàn)
服務消費者在第一次調(diào)用服務時,會通過注冊中心找到相應的服務的IP地址列表,并緩存到本地,以供后續(xù)使用。當消費者調(diào)用服務時,不會再去請求注冊中心,而是直接通過負載均衡算法從IP列表中取一個服務提供者的服務器調(diào)用服務。
3)注冊服務
可靠的尋址方式(主要是提供服務的發(fā)現(xiàn))是RPC的實現(xiàn)基石,比如可以zookeeper來實現(xiàn)注冊服務等等。

服務提供者啟動后主動向服務(注冊)中心注冊機器ip、端口以及提供的服務列表。
服務消費者啟動時向服務(注冊)中心獲取服務提供方地址列表,可實現(xiàn)軟負載均衡和Failover。
提供者需要定時向注冊中心發(fā)送心跳,一段時間未收到來自提供者的心跳后,認為提供者已經(jīng)停止服務,從注冊中心上摘取掉對應的服務等等。
3.網(wǎng)絡傳輸
數(shù)據(jù)傳輸采用什么協(xié)議,數(shù)據(jù)該如何序列化和反序列化。
4.NIO通信
當前很多RPC框架都直接基于netty這一IO通信框架,比如阿里巴巴的HSF、dubbo,Hadoop Avro,推薦使用Netty 作為底層通信框架。
5.服務調(diào)用
比如:B機器進行本地調(diào)用(通過代理Proxy)之后得到了返回值,此時還需要再把返回值發(fā)送回A機器,同樣也需要經(jīng)過序列化操作,然后再經(jīng)過網(wǎng)絡傳輸將二進制數(shù)據(jù)發(fā)送回A機器,而當A機器接收到這些返回值之后,則再次進行反序列化操作
總之,要實現(xiàn)一個RPC不算難,難的是實現(xiàn)一個高性能高可靠的RPC框架,后續(xù)將結(jié)合Dubbo的實現(xiàn)一起再探討。
以上就是RPC的介紹,更多Redis、Spring Cloud、MySQL數(shù)據(jù)庫分庫分表等高并發(fā)架構(gòu)設計,具體請參考高并發(fā)架構(gòu)系列專題:

覺得有用請點贊支持,送你:
1、上面架構(gòu)師專題資料合集,由原BAT架構(gòu)師堅持1年、精心創(chuàng)作,目前已更新至90期;
2、Java 面試題目最全集合1000+ ;

覺得不錯請點贊支持,歡迎留言或進我的個人群179961551領取【架構(gòu)資料專題目合集90期】、【BATJTMD大廠JAVA面試真題1000+】,本群專用于學習交流技術(shù)、分享面試機會,拒絕廣告,我也會在群內(nèi)不定期答題、探討。