從 0 到 1:全面理解 RPC 遠(yuǎn)程調(diào)用
從 0 到 1:全面理解 RPC 遠(yuǎn)程調(diào)用
作者 | Python編程時(shí)光 責(zé)編 | 胡巍巍 什么是RPC呢?百度百科給出的解釋是這樣的:“RPC(Remote Procedure Call Protocol)——遠(yuǎn)程過程調(diào)用協(xié)議,它是一種通過**從遠(yuǎn)程計(jì)算機(jī)程序上請(qǐng)求服務(wù),而不需要了解底層**技術(shù)的協(xié)議”。 這個(gè)概念聽起來還是比較抽象,沒關(guān)系,繼續(xù)往后看,后面概念性的東西,我會(huì)講得足夠清楚,讓你完全掌握 RPC 的基礎(chǔ)內(nèi)容。
在 OpenStack 里的進(jìn)程間通信方式主要有兩種,一種是基于HTTP協(xié)議的RESTFul API方式,另一種則是RPC調(diào)用。
那么這兩種方式在應(yīng)用場(chǎng)景上有何區(qū)別呢? 有使用經(jīng)驗(yàn)的人,就會(huì)知道: 首先,給你提兩個(gè)問題,帶著這兩個(gè)問題再往下看: 1、RPC 和 REST 區(qū)別是什么?2、為什么要采用RPC呢? 首先,**個(gè)問題:RPC 和 REST 區(qū)別是什么? 你一定會(huì)覺得這個(gè)問題很奇怪,是的,包括我,但是你在**上一搜,會(huì)發(fā)現(xiàn)類似對(duì)比的文章比比皆是,我在想可能很多初學(xué)者由于基礎(chǔ)不牢固,才會(huì)將不相干的二者拿出來對(duì)比吧。既然是這樣,那為了讓你更加了解陌生的RPC,就從你熟悉得不能再熟悉的 REST 入手吧。 01、所屬類別不同 REST,是Representational State Transfer 的簡(jiǎn)寫,中文描述表述性狀態(tài)傳遞(是指某個(gè)瞬間狀態(tài)的資源數(shù)據(jù)的快照,包括資源數(shù)據(jù)的內(nèi)容、表述格式(XML、JSON)等信息。) REST 是一種軟件架構(gòu)風(fēng)格。
這種風(fēng)格的典型應(yīng)用,就是HTTP。其因?yàn)楹?jiǎn)單、擴(kuò)展性強(qiáng)的特點(diǎn)而廣受開發(fā)者的青睞。 而RPC 呢,是 Remote Procedure Call Protocol 的簡(jiǎn)寫,中文描述是遠(yuǎn)程過程調(diào)用,它可以實(shí)現(xiàn)客戶端像調(diào)用本地服務(wù)(方法)一樣調(diào)用服務(wù)器的服務(wù)(方法)。
而 RPC 可以基于 TCP/UDP,也可以基于 HTTP 協(xié)議進(jìn)行傳輸?shù)?,按理說它和REST不是一個(gè)層面意義上的東西,不應(yīng)該放在一起討論,但是誰讓REST這么流行呢,它是目前***的一套互聯(lián)網(wǎng)應(yīng)用程序的API設(shè)計(jì)標(biāo)準(zhǔn),某種意義下,我們說 REST 可以其實(shí)就是指代 HTTP 協(xié)議。 02、使用方式不同 03、面向?qū)ο蟛煌?從設(shè)計(jì)上來看,RPC,所謂的遠(yuǎn)程過程調(diào)用 ,是面向方法的 ,REST:所謂的 Representational state transfer ,是面向資源的,除此之外,還有一種叫做 SOA,所謂的面向服務(wù)的架構(gòu),它是面向消息的,這個(gè)接觸不多,就不多說了。 04、序列化協(xié)議不同 接口調(diào)用通常包含兩個(gè)部分,序列化和通信協(xié)議。
通信協(xié)議,上面已經(jīng)提及了,REST 是 基于 HTTP 協(xié)議,而 RPC 可以基于 TCP/UDP,也可以基于 HTTP 協(xié)議進(jìn)行傳輸?shù)摹?常見的序列化協(xié)議,有:json、xml、hession、protobuf、thrift、text、bytes等,REST 通常使用的是 JSON或者XML,而 RPC 使用的是 JSON-RPC,或者 XML-RPC。 通過以上幾點(diǎn),我們知道了 REST 和 RPC 之間有很明顯的差異。
然后第二個(gè)問題:為什么要采用RPC呢? 那到底為何要使用 RPC,單純的依靠RESTful API不可以嗎?為什么要搞這么多復(fù)雜的協(xié)議,渣渣表示真的學(xué)不過來了。 關(guān)于這一點(diǎn),以下幾點(diǎn)僅是我的個(gè)人猜想,僅供交流哈: 說了這么多,我們?cè)撊绾芜x擇這兩者呢?我總結(jié)了如下兩點(diǎn),供你參考: “遠(yuǎn)程調(diào)用”意思就是:被調(diào)用方法的具體實(shí)現(xiàn)不在程序運(yùn)行本地,而是在別的某個(gè)地方(分布到各個(gè)服務(wù)器),調(diào)用者只想要函數(shù)運(yùn)算的結(jié)果,卻不需要實(shí)現(xiàn)函數(shù)的具體細(xì)節(jié)。 光說不練嘴把式,接下來,我將分別用三種不同的方式全面地讓你搞明白 rpc 遠(yuǎn)程調(diào)用是如何實(shí)現(xiàn)的。 01、基于 xml-rpc Python實(shí)現(xiàn) rpc,可以使用標(biāo)準(zhǔn)庫里的 SimpleXMLRPCServer,它是基于XML-RPC 協(xié)議的。
有了這個(gè)模塊,開啟一個(gè) rpc server,就變得相當(dāng)簡(jiǎn)單了。執(zhí)行以下代碼: 有了 rpc server,接下來就是 rpc client,由于我們上面使用的是 XML-RPC,所以 rpc clinet 需要使用xmlrpclib 這個(gè)庫。 然后,我們通過 server_proxy 對(duì)象就可以遠(yuǎn)程調(diào)用之前的rpc server的函數(shù)了。 SimpleXMLRPCServer是一個(gè)單線程的服務(wù)器。
這意味著,如果幾個(gè)客戶端同時(shí)發(fā)出多個(gè)請(qǐng)求,其它的請(qǐng)求就必須等待**個(gè)請(qǐng)求完成以后才能繼續(xù)。 若非要使用 SimpleXMLRPCServer 實(shí)現(xiàn)多線程并發(fā),其實(shí)也不難。只要將代碼改成如下即可。 02、基于json-rpc SimpleXMLRPCServer 是基于 xml-rpc 實(shí)現(xiàn)的遠(yuǎn)程調(diào)用,上面我們也提到 除了 xml-rpc 之外,還有 json-rpc 協(xié)議。
那 python 如何實(shí)現(xiàn)基于 json-rpc 協(xié)議呢? 答案是很多,很多web框架其自身都自己實(shí)現(xiàn)了json-rpc,但我們要獨(dú)立這些框架之外,要尋求一種較為干凈的解決方案,我查找到的選擇有兩種 **種是 jsonrpclib 第二種是 python-jsonrpc 先來看**種 jsonrpclib 它與 Python 標(biāo)準(zhǔn)庫的 SimpleXMLRPCServer 很類似(因?yàn)樗念惷徒凶?SimpleJSONRPCServer ,不明真相的人真以為它們是親兄弟)?;蛟S可以說,jsonrpclib 就是仿照 SimpleXMLRPCServer 標(biāo)準(zhǔn)庫來進(jìn)行編寫的。 它的導(dǎo)入與 SimpleXMLRPCServer 略有不同,因?yàn)镾impleJSONRPCServer分布在jsonrpclib庫中。
服務(wù)端 客戶端 再來看第二種python-jsonrpc,寫起來貌似有些復(fù)雜。 服務(wù)端 客戶端 調(diào)用過程如下 還記得上面我提到過的 zabbix API,因?yàn)槲矣薪佑|過,所以也拎出來講講。zabbix API 也是基于 json-rpc 2.0協(xié)議實(shí)現(xiàn)的。
因?yàn)閮?nèi)容較多,這里只帶大家打個(gè),zabbix 是如何調(diào)用的:直接指明要調(diào)用 zabbix server 的哪個(gè)方法,要傳給這個(gè)方法的參數(shù)有哪些。 03、基于 zerorpc 以上介紹的兩種rpc遠(yuǎn)程調(diào)用方式,如果你足夠細(xì)心,可以發(fā)現(xiàn)他們都是http+rpc 兩種協(xié)議結(jié)合實(shí)現(xiàn)的。 接下來,我們要介紹的這種(zerorpc),就不再使用走 http 了。 zerorpc 這個(gè)第三方庫,它是基于TCP協(xié)議、 ZeroMQ 和 MessagePack的,速度相對(duì)快,響應(yīng)時(shí)間短,并發(fā)高。
zerorpc 和 pyjsonrpc 一樣,需要額外安裝,雖然SimpleXMLRPCServer不需要額外安裝,但是SimpleXMLRPCServer性能相對(duì)差一些。 調(diào)用過程如下 客戶端除了可以使用zerorpc框架實(shí)現(xiàn)代碼調(diào)用之外,它還支持使用“命令行”的方式調(diào)用。 客戶端可以使用命令行,那服務(wù)端是不是也可以呢? 是的,通過 Github 上的文檔幾個(gè) demo 可以體驗(yàn)到這個(gè)第三方庫做真的是**。
比如我們可以用下面這個(gè)命令,創(chuàng)建一個(gè)rpc server,后面這個(gè) time Python 標(biāo)準(zhǔn)庫中的 time 模塊,zerorpc 會(huì)將 time 注冊(cè)綁定以供client調(diào)用。 經(jīng)過了上面的百科學(xué)習(xí),我們已經(jīng)學(xué)會(huì)了如何使用多種方式實(shí)現(xiàn)rpc遠(yuǎn)程調(diào)用。 通過對(duì)比,zerorpc 可以說是脫穎而出,一支獨(dú)秀。 為此,我也做了一番思考: OpenStack 組件繁多,在一個(gè)較大的集群內(nèi)部每個(gè)組件內(nèi)部通過rpc通信頻繁,如果都采用rpc直連調(diào)用的方式,連接數(shù)會(huì)非常地多,開銷大,若有些 server 是單線程的模式,超時(shí)會(huì)非常的嚴(yán)重。
OpenStack 是復(fù)雜的分布式集群架構(gòu),會(huì)有多個(gè) rpc server 同時(shí)工作,假設(shè)有 server01,server02,server03 三個(gè)server,當(dāng) rpc client 要發(fā)出rpc請(qǐng)求時(shí),發(fā)給哪個(gè)好呢?這是問題一。 你可能會(huì)說輪循或者隨機(jī),這樣對(duì)大家都公平。這樣的話還會(huì)引出另一個(gè)問題,倘若請(qǐng)求剛好發(fā)到server01,而server01剛好不湊巧,可能由于機(jī)器或者其他因?yàn)閷?dǎo)致服務(wù)沒在工作,那這個(gè)rpc消息可就直接失敗了呀。
要知道做為一個(gè)集群,高可用是基本要求,如果出現(xiàn)剛剛那樣的情況其實(shí)是很尷尬的。這是問題二。 集群有可能根據(jù)實(shí)際需要擴(kuò)充節(jié)點(diǎn)數(shù)量,如果使用直接調(diào)用,耦合度。
rpc 文件怎么用
Remote Procedure Calls遠(yuǎn)程過程調(diào)用 (RPC) 是一種協(xié)議,程序可使用這種協(xié)議向**中的另一臺(tái)計(jì)算機(jī)上的程序請(qǐng)求服務(wù)。由于使用 RPC 的程序不必了解支持通信的**協(xié)議的情況,因此 RPC 提高了程序的互操作性。
在 RPC 中,發(fā)出請(qǐng)求的程序是客戶程序,而提供服務(wù)的程序是服務(wù)器。
什么是RPC?
RPC是遠(yuǎn)程過程調(diào)用(Remote Procedure Call)的縮寫形式。SAP系統(tǒng)RPC調(diào)用的原理其實(shí)很簡(jiǎn)單,有一些類似于三層構(gòu)架的C/S系統(tǒng),第三方的客戶程序通過接口調(diào)用SAP內(nèi)部的標(biāo)準(zhǔn)或自定義函數(shù),獲得函數(shù)返回的數(shù)據(jù)進(jìn)行處理后顯示或打印。
進(jìn)程間通信(IPC)在多任務(wù)操作系統(tǒng)或聯(lián)網(wǎng)的計(jì)算機(jī)之間運(yùn)行的程序和進(jìn)程所用的通信技術(shù)。
有兩種類型的進(jìn)程間通信(IPC)。
本地過程調(diào)用(LPC)LPC用在多任務(wù)操作系統(tǒng)中,使得同時(shí)運(yùn)行的任務(wù)能互相會(huì)話。這些任務(wù)共享內(nèi)存空間使任務(wù)同步和互相發(fā)送信息。遠(yuǎn)程過程調(diào)用(RPC)RPC類似于LPC,只是在網(wǎng)上工作。
RPC開始是出現(xiàn)在Sun微系統(tǒng)公司和HP公司的運(yùn)行UNⅨ操作系統(tǒng)的計(jì)算機(jī)中。
擴(kuò)展資料
通過IPC和RPC,程序能利用其它程序或計(jì)算機(jī)處理的進(jìn)程??蛻魴C(jī)/服務(wù)器模式計(jì)算把遠(yuǎn)程過程調(diào)用與其它技術(shù)(如消息傳遞)一道,作為系統(tǒng)間通信的一種機(jī)制。
客戶機(jī)執(zhí)行自己的任務(wù),但靠服務(wù)器提供后端文件服務(wù)。
RPC為客戶機(jī)提供向后端服務(wù)器申請(qǐng)服務(wù)的通信機(jī)制,如圖R-4所示。如果你把客戶機(jī)/服務(wù)器應(yīng)用程序想作是一個(gè)分離的程序,服務(wù)器能運(yùn)行數(shù)據(jù)訪問部分,因?yàn)樗x數(shù)據(jù)最近,客戶機(jī)能運(yùn)行數(shù)據(jù)表示和與用戶交互的前端部分。
這樣,遠(yuǎn)程過程調(diào)用可看作是把分割的程序通過**重組的部件。LPC有時(shí)也稱耦合(Coupling)機(jī)制。
用這種方式分割程序,當(dāng)用戶要訪問數(shù)據(jù)時(shí)就無需每次拷貝整個(gè)數(shù)據(jù)庫或它的大部分程序到用戶系統(tǒng)。
其實(shí),服務(wù)器只處理請(qǐng)求,甚至只執(zhí)行一些數(shù)據(jù)計(jì)算,把得出的結(jié)果再發(fā)送給用戶。因?yàn)楫?dāng)數(shù)據(jù)存放在一個(gè)地方時(shí),數(shù)據(jù)庫同步很容易實(shí)現(xiàn),所以多個(gè)用戶可同時(shí)訪問相同的數(shù)據(jù)。
分布式計(jì)算環(huán)境是由一個(gè)通信系統(tǒng)——**連接的計(jì)算機(jī)集群。很容易把這個(gè)**看成一個(gè)計(jì)算平臺(tái),若是對(duì)等方式,其中任何一臺(tái)計(jì)算機(jī)都能成為客戶機(jī)或服務(wù)器。
一些處理任務(wù)可被分成獨(dú)立運(yùn)行程序在不同的**計(jì)算機(jī)上并行處理,而獨(dú)立的程序被交給最適合這個(gè)任務(wù)的計(jì)算機(jī)處理。這種策略可利用計(jì)算機(jī)空閑資源,提高**的效益。一個(gè)典型的企業(yè)網(wǎng)包括許多運(yùn)行著不同操作系統(tǒng)的異構(gòu)計(jì)算機(jī)系統(tǒng)。
RPC – 遠(yuǎn)程方法調(diào)用
1.RPC原理解析 1.1 什么是RPC RPC(Remote Procedure Call Protocol)——遠(yuǎn)程過程調(diào)用協(xié)議,它是一種通過**從遠(yuǎn)程計(jì)算機(jī)程序上請(qǐng)求服務(wù),而不需要了解底層**技術(shù)的協(xié)議。RPC協(xié)議假定某些傳輸協(xié)議的存在,如TCP/IP或UDP,為通信程序之間攜帶信息數(shù)據(jù)。
RPC將原來的本地調(diào)用轉(zhuǎn)變?yōu)檎{(diào)用遠(yuǎn)端的服務(wù)器上的方法,給系統(tǒng)的處理能力和吞吐量帶來了近似于無限制提升的可能。
在OSI**通信模型中,RPC跨域了傳輸層和應(yīng)用層。RPC使得開發(fā)包括**分布式多程序在內(nèi)的應(yīng)用程序更加容易。 太專業(yè)了,簡(jiǎn)而言之就是下面幾點(diǎn): 1.解決分布式系統(tǒng)中,服務(wù)之間的調(diào)用問題。 2.遠(yuǎn)程調(diào)用時(shí),要能夠像本地調(diào)用一樣方便,讓調(diào)用者感知不到遠(yuǎn)程調(diào)用的邏輯 3.序列化反序列化是前提 1.2 RPC架構(gòu) 一個(gè)完整的RPC架構(gòu)里面包含了四個(gè)核心的組件,分別是Client,Client Stub,Server以及Server Stub,這個(gè)Stub可以理解為存根。
客戶端(Client),服務(wù)的調(diào)用方。 客戶端存根(Client Stub),存放服務(wù)端的地址消息,再將客戶端的請(qǐng)求參數(shù)打包成**消息,然后通過**遠(yuǎn)程發(fā)送給服務(wù)方。 服務(wù)端(Server),真正的服務(wù)提供者。
服務(wù)端存根(Server Stub),接收客戶端發(fā)送過來的消息,將消息解包,并調(diào)用本地的方法。 1.3 RPC調(diào)用過程 (1) 客戶端(client)以本地調(diào)用方式(即以接口的方式)調(diào)用服務(wù); (2) 客戶端存根(client stub)接收到調(diào)用后,負(fù)責(zé)將方法、參數(shù)等組裝成能夠進(jìn)行**傳輸?shù)南Ⅲw(將消息體對(duì)象序列化為二進(jìn)制); (3) 客戶端通過sockets將消息發(fā)送到服務(wù)端; (4) 服務(wù)端存根( server stub)收到消息后進(jìn)行解碼(將消息對(duì)象反序列化); (5) 服務(wù)端存根( server stub)根據(jù)解碼結(jié)果調(diào)用本地的服務(wù); (6) 本地服務(wù)執(zhí)行并將結(jié)果返回給服務(wù)端存根( server stub); (7) 服務(wù)端存根( server stub)將返回結(jié)果打包成消息(將結(jié)果消息對(duì)象序列化); (8) 服務(wù)端(server)通過sockets將消息發(fā)送到客戶端; (9) 客戶端存根(client stub)接收到結(jié)果消息,并進(jìn)行解碼(將結(jié)果消息發(fā)序列化); (10) 客戶端(client)得到最終結(jié)果。 RPC的目標(biāo)是要把2、3、4、7、8、9這些步驟都封裝起來。
注意:無論是何種類型的數(shù)據(jù),最終都需要轉(zhuǎn)換成二進(jìn)制流在**上進(jìn)行傳輸,數(shù)據(jù)的發(fā)送方需要將對(duì)象轉(zhuǎn)換為二進(jìn)制流,而數(shù)據(jù)的接收方則需要把二進(jìn)制流再恢復(fù)為對(duì)象。