RPC發展歷史的幾個關鍵節點
奠基: 過程調用最早可以追溯到 Jon Postel 和 Jim White 在1974 年發表的 Procedure Call Protocol Documents Version 2(RFC674)。這個協議試圖定義一種通用的方法,用于解決 NSW 項目中多個計算節點通信的問題。
第一個RPC標準: 1988年,RFC 1057 發布,ONC RPC(Sun RPC) 被定義為標準的RPC規范。ONC RPC 提供了一個編譯器,需要一個遠程過程接口的定義來生成客戶端和服務器的存根函數。這個編譯器叫做 rpcgen。在運行此編譯器之前,程序員必須提供接口定義,包含函數聲明的接口定義,通過版本號進行分組,并被一個獨特的程序編碼來標識。這一過程已經成為現在RPC的基本調用模型。
第一個對象模型調用標準: 1991年,OMG 發布CORBA 1.0,試圖為應用程序開發人員提供幾個好處: 語言獨立性、操作系統獨立性、體系結構獨立性、通過 IDL 中的抽象類型映射到這些類型的機器和語言特定實現的靜態類型,以及對象傳輸,其中對象可以通過不同機器之間的連接進行遷移。
HTTP誕生: 1996年:HTTP/1.x 版本發布,為互聯網的發展奠定了基礎,我們今天的大部分遠程調用,都基于HTTP協議。
REST概念提出: 2000年,Roy Thomas Fielding 博士在他的博士論文 《Architectural Styles and the Design of Network-based Software Architectures》首次提出了 REST 這個詞。REST非常簡單,無需客戶端stub 代碼 和服務端 stub代碼,且所有語言都可以集成實現。HTTP REST慢慢侵占了RPC大部分應用領地的“異類”,并且導致了一度盛行的XML-RPC的滅絕,但同時促進了正統RPC技術走向一個新的發展階段。
注:了解更詳細的發展歷史,請閱讀RPC發展史。
RPC需要解決的問題
RPC 的出現的確為 分布式系統 構建帶來了便利,但與此同時分布式系統本身的問題也暴露了出來:
延遲問題 首先就是延遲的問題,最直觀的表現就是響應時間變長:用戶的一次點擊事件可能需要經過多個服務處理,每個服務都被部署在不同的機器上,這種跨機器、跨網絡的進程間通信更容易出現網絡延遲。此外,數據編/解碼帶來的性能損耗也會拖慢響應速度。要解決這個問題,就得投入更大的網絡帶寬以及更強的硬件設備。
地址空間被隔離 內存地址只在同一臺機器上有效,在一臺機器內,可以通過內存共享實現地址空間不被隔離,但是在跨機器場景下,地址空間是被完全隔離的。比如在使用指針時,本地地址空間的指針在另一臺機器上是無法使用的,所以需要 RPC 通過編程范式對開發者隱藏這種區別。而作為開發者,也應該清楚 RPC 框架下的開發不可以直接使用原始指針。
局部故障 在分布式架構中,不同的服務部署在不同的機器上,而且每個服務也會部署多個節點。當某服務的其中一個或幾個節點發生故障時,若沒有一個合適的發現機制,流量依舊請求到了故障節點,就會造成響應失敗。為了解決這個問題,我們可以引入注冊中心。注冊中心可以發現并屏蔽掉發生故障的節點,但是注冊中心也可能使故障類型變得模糊,定位問題的過程會更加復雜。除了發現問題、定位問題難度的上升,注冊中心在解決局部故障上的難度也不小:因為出現局部故障后,需要保證整個集群的處理結果是一致的。比如需要通過分布式事務來保證整個集群所有節點寫入數據是一致的,不會因為局部故障而出現故障節點寫入數據失敗但是非故障節點寫入成功,導致數據不一致的情況。
并發問題 在分布式架構中,每個服務都有多個節點,如果多個節點同時對某個服務發起調用,就會產生并發問題。與本地多線程調用不同,分布式架構無法做到完全控制調用順序,因為每個節點在不同的機器上,它們發起調用的時間也難以被統一管控。
RPC的調用類型
在項目開發中常用的RPC調用方式有以下幾種:
Synchronous /同步模式,默認的RPC調用方式,客戶端發起請求并等待服務端響應。
Nonblocking/非阻塞模式, 客戶端發起請求后不等待服務端響應,繼續執行自己的進程,該模式也可成為異步(Async)模式。
Batch-mode/批量模式, 客戶端發起一組非阻塞的調用。
Broadcast/廣播模式,客戶端向多個服務器發送消息,然后接收所有結果回復。
Callback/回調模式,配合非阻塞模式使用。
RPC的基本原理
RPC的核心思想是將遠程調用封裝成本地調用,使得調用方無需關心底層網絡通信細節。當調用方需要調用遠程函數時,它會像調用本地函數一樣發起調用請求,然后等待遠程函數的返回結果。
RPC調用流程
服務消費方(client)調用以本地調用方式調用服務;
client stub接收到調用后負責將方法、參數等組裝成能夠進行網絡傳輸的消息體;
client stub找到服務地址,并將消息發送到服務端;
server stub收到消息后進行解碼;
server stub根據解碼結果調用本地的服務;
本地服務執行并將結果返回給server stub;
server stub將返回結果打包成消息并發送至消費方;
client stub接收到消息,并進行解碼;
服務消費方得到最終結果。
核心組件
RPC 技術發展至今,底層核心組成部分始終沒有很大變化。無論是幾十年前的 CORBA,還是如今流行的 Dubbo、gRPC 等,它們基本都由以下五個部分組成:
Consumer(服務調用方);
Consumer-Stub(調用方本地存根);
RPC Runtime(RPC 運行時);
Provider-Stub(提供方本地存根);
Provider(服務提供方)。
序列化
什么是序列化?序列化就是將數據結構或對象轉換成二進制串的過程,也就是編碼的過程。
什么是反序列化?將在序列化過程中所生成的二進制串轉換成數據結構或者對象的過程。
為什么需要序列化?轉換為二進制串后才好進行網絡傳輸嘛!
為什么需要反序列化?將二進制轉換為對象才好進行后續處理!
現如今序列化的方案越來越多,每種序列化方案都有優點和缺點,它們在設計之初有自己獨特的應用場景,那到底選擇哪種呢?從RPC的角度上看,主要看三點:
通用性:比如是否能支持Map等復雜的數據結構;
性能:包括時間復雜度和空間復雜度,由于RPC框架將會被公司幾乎所有服務使用,如果序列化上能節約一點時間,對整個公司的收益都將非常可觀,同理如果序列化上能節約一點內存,網絡帶寬也能省下不少;
可擴展性:對互聯網公司而言,業務變化飛快,如果序列化協議具有良好的可擴展性,支持自動增加新的業務字段,而不影響老的服務,這將大大提供系統的靈活度。
目前互聯網公司廣泛使用Protobuf、Thrift、Avro等成熟的序列化解決方案來搭建RPC框架,這些都是久經考驗的解決方案。
通訊協議
RPC調用過程通常采用的底層協議有:TCP、HTTP、UDP。報文格式由序列化方式來決定。
服務注冊與服務發現
在分布式環境中,服務的命名及注冊從約定模式逐步發展到了分布式注冊中心 ,各種發現方式依然普遍應用于實現中,包括約定模式。
服務注冊 :服務進程在注冊中心注冊自己的元數據信息,通常包括主機和端口號等信息。
服務發現 :客戶端服務進程向注冊中心發起查詢,獲取可用的服務信息。
RPC 技術和RPC 框架簡介
常見 RPC 技術和框架有:
應用級的服務框架: 阿里的 Dubbo/Dubbox、Google gRPC、Facebook Thrift、Spring Boot/Spring Cloud。
遠程通信協議: Corba、SOAP API(HTTP+XML)、RESTful API(HTTP+JSON)。
通信框架: MINA 和 Netty。
各語言專用RPC實現框架 :Java RMI、Golang Rpcx、C++ RCF、Python自帶的RPC實現
RPC與SOAP
RPC 提供了一種簡單且輕量級的通信協議,而 SOAP 提供了一個標準化的消息傳遞框架,可以跨不同的平臺和編程語言使用。
RPC(遠程過程調用)是一種在遠程系統上執行代碼的協議,而 SOAP(簡單對象訪問協議)是一種基于 XML 的消息傳遞協議,用于交換數據。
RPC 可以使用多種協議,包括 SOAP,而 SOAP 只依賴于 XML 和 HTTP。
與 RPC 相比,SOAP 提供了更好的互操作性和標準化,這可以簡化跨各種平臺的實施。
RPC與REST
REST和RPC協議具有相似的品質。例如,這兩種協議都用于通過分布式系統進行通信。然而,它們仍然有不同的基本結構和用例。
REST必須是無狀態的,但RPC系統可以是無狀態的或無狀態的。REST還具有更大的靈活性,因為它可以在一個API中以多種格式(如JavaScript對象符號或可擴展標記語言)發送數據,而RPC使用固定數據格式。
推薦閱讀
終于把RPC框架整明白了 RPC理論及框架詳解
我們有何不同?
API服務商零注冊
多API并行試用
數據驅動選型,提升決策效率
查看全部API→