天天看點

Dubbo RPC面試題

RPC非常重要,很多人面試的時候都挂在了這個地方!你要是還不懂RPC是什麼?他的基本原理是什麼?你一定要把下邊的内容記起來!好好研究一下!特别是文中給出的一張關于RPC的基本流程圖,重點中的重點,Dubbo RPC的基本執行流程就是他,RPC架構的基本原理也是他,别說我沒告訴你!看了下邊的内容你要掌握的内容如下,當然還有很多:

RPC的由來,是怎樣一步步演進出來的;

RPC的基本架構是什麼;

RPC的基本實作原理,就是下邊的這張圖,重點中的重點;

REST 和 SOAP、RPC 有何差別呢?

整個調用的過程經曆了哪幾步和Spring MVC的執行流程一樣,相當重要;

一、為什麼要有RPC

随着網際網路的發展,網站應用的規模不斷擴大,正常的垂直應用架構已無法應對,分布式服務架構以及流動計算架構勢在必行,亟需一個治理系統確定架構有條不紊的演進。

1、單一應用架構

當網站流量很小時,隻需一個應用,将所有功能都部署在一起,以減少部署節點和成本。此時,用于簡化增删改查工作量的資料通路架構(ORM) 是關鍵。

2、垂直應用架構

當通路量逐漸增大,單一應用增加機器帶來的加速度越來越小,将應用拆成互不相幹的幾個應用,以提升效率。此時,用于加速前端頁面開發的 Web架構(MVC) 是關鍵。

3、分布式服務架構

當垂直應用越來越多,應用之間互動不可避免,将核心業務抽取出來,作為獨立的服務,逐漸形成穩定的服務中心,使前端應用能更快速的響應多變的市場需求。

此時,用于提高業務複用及整合的分布式服務架構(RPC),提供統一的服務是關鍵。

例如:各個團隊的服務提供方就不要各自實作一套序列化、反序列化、網絡架構、連接配接池、收發線程、逾時處理、狀态機等“業務之外”的重複技術勞動,造成整體的低效。

PS:其實上述三個原因也是為什麼要有Dubbo的原因!不信你去Dubbo官網去看!

流動計算架構

PS:這個屬于擴充内容,摘自Dubbo官網,屬于架構演進的一個過程

當服務越來越多,容量的評估,小服務資源的浪費等問題逐漸顯現,此時需增加一個排程中心基于通路壓力實時管理叢集容量,提高叢集使用率。此時,用于提高機器使用率的資源排程和治理中心(SOA)是關鍵。

4、另外一個原因

就是因為在幾個程序内(應用分布在不同的機器上),無法共用記憶體空間,或者在一台機器内通過本地調用無法完成相關的需求,比如不同的系統之間的通訊,甚至不同組織之間的通訊。此外由于機器的橫向擴充,需要在多台機器組成的叢集上部署應用等等。

是以,統一RPC架構來解決提供統一的服務。

二、什麼是RPC

RPC(Remote Procedure Call Protocol)遠端過程調用協定,它是一種通過網絡從遠端計算機程式上請求服務,而不需要了解底層網絡技術的協定。簡言之,RPC使得程式能夠像通路本地系統資源一樣,去通路遠端系統資源。比較關鍵的一些方面包括:通訊協定、序列化、資源(接口)描述、服務架構、性能、語言支援等。

Dubbo RPC面試題

簡單的說,RPC就是從一台機器(用戶端)上通過參數傳遞的方式調用另一台機器(伺服器)上的一個函數或方法(可以統稱為服務)并得到傳回的結果。

三、PRC架構元件

一個基本的RPC架構裡面應該至少包含以下4個元件:

1、用戶端(Client):服務調用方(服務消費者)

2、用戶端存根(Client Stub):存放服務端位址資訊,将用戶端的請求參數資料資訊打包成網絡消息,再通過網絡傳輸發送給服務端

3、服務端存根(Server Stub):接收用戶端發送過來的請求消息并進行解包,然後再調用本地服務進行處理

4、服務端(Server):服務的真正提供者

Dubbo RPC面試題

具體調用過程:

1、服務消費者(client用戶端)通過調用本地服務的方式調用需要消費的服務;

2、用戶端存根(client stub)接收到調用請求後負責将方法、入參等資訊序列化(組裝)成能夠進行網絡傳輸的消息體;

3、用戶端存根(client stub)找到遠端的服務位址,并且将消息通過網絡發送給服務端;

4、服務端存根(server stub)收到消息後進行解碼(反序列化操作);

5、服務端存根(server stub)根據解碼結果調用本地的服務進行相關處理;

6、本地服務執行具體業務邏輯并将處理結果傳回給服務端存根(server stub);

7、服務端存根(server stub)将傳回結果重新打包成消息(序列化)并通過網絡發送至消費方;

8、用戶端存根(client stub)接收到消息,并進行解碼(反序列化);

9、服務消費方得到最終結果;

而RPC架構的實作目标則是将上面的第2-10步完好地封裝起來,也就是把調用、編碼/解碼的過程給封裝起來,讓使用者感覺上像調用本地服務一樣的調用遠端服務。

四、RPC和SOA、SOAP、REST的差別

1、REST

可以看着是HTTP協定的一種直接應用,預設基于JSON作為傳輸格式,使用簡單,學習成本低效率高,但是安全性較低。

2、SOAP

SOAP是一種資料交換協定規範,是一種輕量的、簡單的、基于XML的協定的規範。而SOAP可以看着是一個重量級的協定,基于XML、SOAP在安全方面是通過使用XML-Security和XML-Signature兩個規範組成了WS-Security來實作安全控制的,目前已經得到了各個廠商的支援 。

它有什麼優點?簡單總結為:易用、靈活、跨語言、跨平台。

3、SOA

面向服務架構,它可以根據需求通過網絡對松散耦合的粗粒度應用元件進行分布式部署、組合和使用。服務層是SOA的基礎,可以直接被應用調用,進而有效控制系統中與軟體代理互動的人為依賴性。

SOA是一種粗粒度、松耦合服務架構,服務之間通過簡單、精确定義接口進行通訊,不涉及底層程式設計接口和通訊模型。SOA可以看作是B/S模型、XML(标準通用标記語言的子集)/Web Service技術之後的自然延伸。

4、REST 和 SOAP、RPC 有何差別呢?

沒什麼太大差別,他們的本質都是提供可支援分布式的基礎服務,最大的差別在于他們各自的的特點所帶來的不同應用場景 。

五、RPC架構需要解決的問題?

1、如何确定用戶端和服務端之間的通信協定?

2、如何更高效地進行網絡通信?

3、服務端提供的服務如何暴露給用戶端?

4、用戶端如何發現這些暴露的服務?

5、如何更高效地對請求對象和響應結果進行序列化和反序列化操作?

六、RPC的實作基礎?

1、需要有非常高效的網絡通信,比如一般選擇Netty作為網絡通信架構;

2、需要有比較高效的序列化架構,比如谷歌的Protobuf序列化架構;

3、可靠的尋址方式(主要是提供服務的發現),比如可以使用Zookeeper來注冊服務等等;

4、如果是帶會話(狀态)的RPC調用,還需要有會話和狀态保持的功能;

七、RPC使用了哪些關鍵技術?

1、動态代理

生成Client Stub(用戶端存根)和Server Stub(服務端存根)的時候需要用到Java動态代理技術,可以使用JDK提供的原生的動态代理機制,也可以使用開源的:CGLib代理,Javassist位元組碼生成技術。

2、序列化和反序列化

在網絡中,所有的資料都将會被轉化為位元組進行傳送,是以為了能夠使參數對象在網絡中進行傳輸,需要對這些參數進行序列化和反序列化操作。

  • 序列化:把對象轉換為位元組序列的過程稱為對象的序列化,也就是編碼的過程。
  • 反序列化:把位元組序列恢複為對象的過程稱為對象的反序列化,也就是解碼的過程。

目前比較高效的開源序列化架構:如Kryo、FastJson和Protobuf等。

3、NIO通信

出于并發性能的考慮,傳統的阻塞式 IO 顯然不太合适,是以我們需要異步的 IO,即 NIO。Java 提供了 NIO 的解決方案,Java 7 也提供了更優秀的 NIO.2 支援。可以選擇Netty或者MINA來解決NIO資料傳輸的問題。

4、服務注冊中心

可選:Redis、Zookeeper、Consul 、Etcd。一般使用ZooKeeper提供服務注冊與發現功能,解決單點故障以及分布式部署的問題(注冊中心)。

八、主流RPC架構有哪些

1、RMI

利用java.rmi包實作,基于Java遠端方法協定(Java Remote Method Protocol) 和java的原生序列化。

2、Hessian

是一個輕量級的remoting onhttp工具,使用簡單的方法提供了RMI的功能。 基于HTTP協定,采用二進制編解碼。

3、protobuf-rpc-pro

是一個Java類庫,提供了基于 Google 的 Protocol Buffers 協定的遠端方法調用的架構。基于 Netty 底層的 NIO 技術。支援 TCP 重用/ keep-alive、SSL加密、RPC 調用取消操作、嵌入式日志等功能。

4、Thrift

是一種可伸縮的跨語言服務的軟體架構。它擁有功能強大的代碼生成引擎,無縫地支援C + +,C#,Java,Python和PHP和Ruby。thrift允許你定義一個描述檔案,描述資料類型和服務接口。依據該檔案,編譯器友善地生成RPC用戶端和伺服器通信代碼。

最初由facebook開發用做系統内個語言之間的RPC通信,2007年由facebook貢獻到apache基金 ,現在是apache下的opensource之一 。支援多種語言之間的RPC方式的通信:php語言client可以構造一個對象,調用相應的服務方法來調用java語言的服務,跨越語言的C/S RPC調用。底層通訊基于SOCKET。

5、Avro

出自Hadoop之父Doug Cutting, 在Thrift已經相當流行的情況下推出Avro的目标不僅是提供一套類似Thrift的通訊中間件,更是要建立一個新的,标準性的雲計算的資料交換和存儲的Protocol。支援HTTP,TCP兩種協定。

6、Dubbo

Dubbo是 阿裡巴巴公司開源的一個高性能優秀的服務架構,使得應用可通過高性能的 RPC 實作服務的輸出和輸入功能,可以和 Spring架構無縫內建。

九、RPC的實作原理架構圖

Dubbo RPC面試題
Dubbo RPC面試題

PS:這張圖非常重點,是PRC的基本原理,請大家一定記住!

也就是說兩台伺服器A,B,一個應用部署在A伺服器上,想要調用B伺服器上應用提供的函數/方法,由于不在一個記憶體空間,不能直接調用,需要通過網絡來表達調用的語義和傳達調用的資料。

比如說,A伺服器想調用B伺服器上的一個方法:

User getUserByName(String userName)

1、建立通信

首先要解決通訊的問題:即A機器想要調用B機器,首先得建立起通信連接配接。

主要是通過在用戶端和伺服器之間建立TCP連接配接,遠端過程調用的所有交換的資料都在這個連接配接裡傳輸。連接配接可以是按需連接配接,調用結束後就斷掉,也可以是長連接配接,多個遠端過程調用共享同一個連接配接。

通常這個連接配接可以是按需連接配接(需要調用的時候就先建立連接配接,調用結束後就立馬斷掉),也可以是長連接配接(用戶端和伺服器建立起連接配接之後保持長期持有,不管此時有無資料包的發送,可以配合心跳檢測機制定期檢測建立的連接配接是否存活有效),多個遠端過程調用共享同一個連接配接。

2、服務尋址

要解決尋址的問題,也就是說,A伺服器上的應用怎麼告訴底層的RPC架構,如何連接配接到B伺服器(如主機或IP位址)以及特定的端口,方法的名稱名稱是什麼。

通常情況下我們需要提供B機器(主機名或IP位址)以及特定的端口,然後指定調用的方法或者函數的名稱以及入參出參等資訊,這樣才能完成服務的一個調用。

可靠的尋址方式(主要是提供服務的發現)是RPC的實作基石,比如可以采用Redis或者Zookeeper來注冊服務等等。

Dubbo RPC面試題

2.1、從服務提供者的角度看:

當服務提供者啟動的時候,需要将自己提供的服務注冊到指定的注冊中心,以便服務消費者能夠通過服務注冊中心進行查找;

當服務提供者由于各種原因緻使提供的服務停止時,需要向注冊中心登出停止的服務;

服務的提供者需要定期向服務注冊中心發送心跳檢測,服務注冊中心如果一段時間未收到來自服務提供者的心跳後,認為該服務提供者已經停止服務,則将該服務從注冊中心上去掉。

2.2、從調用者的角度看:

服務的調用者啟動的時候根據自己訂閱的服務向服務注冊中心查找服務提供者的位址等資訊;

當服務調用者消費的服務上線或者下線的時候,注冊中心會告知該服務的調用者;

服務調用者下線的時候,則取消訂閱。

3、網絡傳輸

3.1、序列化

當A機器上的應用發起一個RPC調用時,調用方法和其入參等資訊需要通過底層的網絡協定如TCP傳輸到B機器,由于網絡協定是基于二進制的,所有我們傳輸的參數資料都需要先進行序列化(Serialize)或者編組(marshal)成二進制的形式才能在網絡中進行傳輸。然後通過尋址操作和網絡傳輸将序列化或者編組之後的二進制資料發送給B機器。

3.2、反序列化

當B機器接收到A機器的應用發來的請求之後,又需要對接收到的參數等資訊進行反序列化操作(序列化的逆操作),即将二進制資訊恢複為記憶體中的表達方式,然後再找到對應的方法(尋址的一部分)進行本地調用(一般是通過生成代理Proxy去調用,

通常會有JDK動态代理、CGLIB動态代理、Javassist生成位元組碼技術等),之後得到調用的傳回值。

4、服務調用

B機器進行本地調用(通過代理Proxy和反射調用)之後得到了傳回值,此時還需要再把傳回值發送回A機器,同樣也需要經過序列化操作,然後再經過網絡傳輸将二進制資料發送回A機器,而當A機器接收到這些傳回值之後,則再次進行反序列化操作,恢複為記憶體中的表達方式,最後再交給A機器上的應用進行相關處理(一般是業務邏輯處理操作)。

通常,經過以上四個步驟之後,一次完整的RPC調用算是完成了,另外可能因為網絡抖動等原因需要重試等。

參考連結:www.jianshu.com/p/78f72ccf0377

繼續閱讀