全部的界面和服務均在同一個進程下 java
基於mvc的視圖與服務分離,可是實際上仍是在一個應用系統中,只不過在功能層次上劃分的更加細緻 程序員
粒度更細,對於不一樣的功能服務進行切分,並進行單獨的部署 數據庫
面向服務的架構,將應用程序的不一樣功能單元(稱爲服務)經過這些服務之間定義良好的接口和契約聯繫起來 bash
微服務服務器
此處不支持圖片展現,自行腦補!!!網絡
隨着業務量和用戶量的增長,架構也是從單一系統走向分佈式系統,我能想到的是,這種架構的演變主要解決的問題在於:架構
隨着集中式架構向分佈式架構的轉變,應用系統之間的服務調用與通信問題成爲了首要解決的需求。併發
而RPC 的主要目標就是爲了讓構建分佈式計算(應用)變得更加簡單,在提供強大的遠程調用能力時不損失本地調用的語義簡潔性。 爲實現該目標,RPC 框架需提供一種透明調用機制讓使用者沒必要顯式的區分本地調用和遠程調用。mvc
以下代碼:app
@Autowired
private GlRpcAgent glRpcAgent; //rpc代理
/**
* @param param 此處約定參數以Map鍵值對的形式傳遞
*/
@Override
public List<OrderInfo> queryOrdersByUserId(Map<String, Object> param) {
//建立遠程調用代理(遠程服務的類的全限定名)
OrderConsumeAgent orderConsumer=glRpcAgent.getAgent("com.glmapper.rpc.interface.OrderConsumeInterface");
//經過代理獲取返回結果 此處getOrders爲遠程服務器上的com.glmapper.rpc.interface.OrderConsumeInterface接口中的方法,param爲參數
Map<String,Object> resultMap=(Map)orderConsumer.call("getOrders",param);
//解析返回結果(遠程方法一樣以Map集合的方式放回)
List<OrderInfo> orders = parseResultMap(resultMap);
return orders;
}
複製代碼
爲何要以全限定名來獲取呢,這個咱們將會在後面來講。
In distributed computing a remote procedure call (RPC) is when a computer program causes a procedure (subroutine) to execute in another address space(commonly on another computer on a shared network), which is coded as if it were a normal (local) procedure call, without the programmer explicitly coding the details for the remote interaction. RPC 的全稱是 Remote Procedure Call 是一種進程間通訊方式。 它容許程序調用另外一個進程上(一般是共享網絡的另外一臺機器上)的過程或函數,而不用程序員顯式編碼這個遠程調用的細節。即程序員不管是調用本地的仍是遠程的函數,本質上編寫的調用代碼基本相同。
從定義中能夠得知,RPC主要來解決三件事情:
首先是進程間的通訊問題,對於分佈式環境,rpc可以幫助咱們解決不一樣服務器之間的通訊及數據傳輸問題,即**作好方法調用到數據的轉換,而後藉助網絡進行數據傳遞;**rpc客戶端向rpc服務端發起遠程服務調用,經過請求的封裝,參數的封裝,序列化、編碼、約定協議傳輸、解析請求、處理請求、封裝返回消息數據、在進行返回數據的序列化、編碼、在經過網絡返回給客戶端。再者是提供和本地方法調用同樣的調用機制,爲何這麼說,對於業務系統來講,咱們更多的關注點在於如何解決實際的業務需求問題,而不想花更多的時間和心思在諸如上述過程當中關於網絡傳輸及編解碼過程,所以對於rpc來講,須要將這些編解碼、協議約定、網絡傳輸等進行一個總體的封裝,而後只向業務系統提供最簡單的調用方式。最後一個屏蔽程序員對遠程調用的細節實現,其實也就是第二點中提到的那些功能的封裝,咱們不用去關係rpc究竟是如何實現的,也不用關心它是如何運做的,對於業務開發人員來講,經過約定的方式進行相似於本地方法調用的形式來調用遠程服務接口就能夠了。 那麼如何實現透明化的遠程調用呢? 什麼樣的內部封裝才能讓咱們以爲像以本地調用方式調用遠程服務呢? 對於java來講就是使用代理。java代理有兩種方式:1) jdk 動態代理(接口代理);2)cglib代理(子類代理)。儘管字節碼生成方式實現的代理更爲強大和高效,但代碼不易維護,大部分公司實現RPC框架時仍是選擇動態代理方式。這部分也將會在後續的章節中展開來講。
上面說到,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就至關於將step2-step8的步驟進行了封裝。下面借用一張網上的圖片來幫助咱們理解這個過程。
對於上圖,咱們進行進一步的拆解獲得(來自網絡):
經過上述分析可知,這裏麪包括如下核心組件:
目前常見的分佈式RPC框架有如下幾個:
MQ(message queue)消息隊列,從某種程度上來講,一樣能夠實現RPC的功能。從功能特色上來講,MQ能夠把消息存儲,而RPC不行。關於MQ和RPC作了如下簡單的對比,以下圖所示:
本文對RPC的基本原理、特色以及基本組件進行了簡單的說明,讓咱們能夠對RPC有一個基本的瞭解。關於常見的RPC框架也作了基本認識,對於這些優秀的框架,咱們在實現咱們本身RPC時能夠借鑑一下這些架構裏的一些模式以及技術。最後說明了下爲何咱們會在分佈式架構中要使用RPC而不是MQ,對於MQ來講,在處理同步調用沒法知足實際的生產需求,而RPC才更加適合分佈式應用的實際須要。