簡(jiǎn)單介紹RPC協(xié)議及常見(jiàn)框架,對(duì)比傳統(tǒng)restful api和RPC方式的優(yōu)缺點(diǎn)。常見(jiàn)RPC框架,gRPC及序列化方式Protobuf等
HTTP協(xié)議
http協(xié)議是基于tcp協(xié)議的,tcp協(xié)議是流式協(xié)議,包頭部分可以通過(guò)多出的\r\n來(lái)分界,包體部分如何分界呢?這是協(xié)議本身要解決的問(wèn)題。目前一般有兩種方式,第一種方式就是在包頭中有個(gè)content-Length字段,這個(gè)字段的值的大小標(biāo)識(shí)了POST數(shù)據(jù)的長(zhǎng)度,服務(wù)器收到一個(gè)數(shù)據(jù)包后,先從包頭解析出這個(gè)字段的值,再根據(jù)這個(gè)值去讀取相應(yīng)長(zhǎng)度的作為http協(xié)議的包體數(shù)據(jù)。
瀏覽器connect 80端口
RESTful API (http+json)
理解RESTful架構(gòu) - 阮一峰
REST 架構(gòu)該怎么生動(dòng)地理解? - 覃超的回答 - 知乎
網(wǎng)站即軟件,而且是一種新型的軟件,這種"互聯(lián)網(wǎng)軟件"采用客戶端/服務(wù)器模式,建立在分布式體系上,通過(guò)互聯(lián)網(wǎng)通信,具有高延時(shí)(high latency)、高并發(fā)等特點(diǎn)。
它首次出現(xiàn)在 2000 年 Roy Fielding 的博士論文中,他是 HTTP 規(guī)范的主要編寫者之一。Representational State Transfer,翻譯是”表現(xiàn)層狀態(tài)轉(zhuǎn)化”,通俗來(lái)講就是:資源在網(wǎng)絡(luò)中以某種表現(xiàn)形式進(jìn)行狀態(tài)轉(zhuǎn)移。
總結(jié)一下什么是RESTful架構(gòu):
?。?)每一個(gè)URI代表一種資源;
?。?)客戶端和服務(wù)器之間,傳遞這種資源的某種表現(xiàn)層,比如用JSON,XML,JPEG等;
?。?)客戶端通過(guò)四個(gè)HTTP動(dòng)詞,對(duì)服務(wù)器端資源進(jìn)行操作,實(shí)現(xiàn)"表現(xiàn)層狀態(tài)轉(zhuǎn)化"。
URL定位資源,用HTTP動(dòng)詞(GET,POST,DELETE,DETC)描述操作。
用HTTP協(xié)議里的動(dòng)詞來(lái)實(shí)現(xiàn)資源的添加,修改,刪除等操作。即通過(guò)HTTP動(dòng)詞來(lái)實(shí)現(xiàn)資源的狀態(tài)扭轉(zhuǎn):
GET 用來(lái)獲取資源,
POST 用來(lái)新建資源(也可以用于更新資源),
PUT 用來(lái)更新資源,
DELETE 用來(lái)刪除資源。
RPC
進(jìn)程間通信(IPC,Inter-Process Communication),指至少兩個(gè)進(jìn)程或線程間傳送數(shù)據(jù)或信號(hào)的一些技術(shù)或方法。進(jìn)程是計(jì)算機(jī)系統(tǒng)分配資源的最小單位。每個(gè)進(jìn)程都有自己的一部分獨(dú)立的系統(tǒng)資源,彼此是隔離的。為了能使不同的進(jìn)程互相訪問(wèn)資源并進(jìn)行協(xié)調(diào)工作,才有了進(jìn)程間通信。這些進(jìn)程可以運(yùn)行在同一計(jì)算機(jī)上或網(wǎng)絡(luò)連接的不同計(jì)算機(jī)上。 進(jìn)程間通信技術(shù)包括消息傳遞、同步、共享內(nèi)存和遠(yuǎn)程過(guò)程調(diào)用。 IPC是一種標(biāo)準(zhǔn)的Unix通信機(jī)制。
有兩種類型的進(jìn)程間通信(IPC)。
- 本地過(guò)程調(diào)用(LPC)LPC用在多任務(wù)操作系統(tǒng)中,使得同時(shí)運(yùn)行的任務(wù)能互相會(huì)話。這些任務(wù)共享內(nèi)存空間使任務(wù)同步和互相發(fā)送信息。
- 遠(yuǎn)程過(guò)程調(diào)用(RPC)RPC類似于LPC,只是在網(wǎng)上工作。RPC開(kāi)始是出現(xiàn)在Sun微系統(tǒng)公司和HP公司的運(yùn)行UNIX操作系統(tǒng)的計(jì)算機(jī)中。
為什么RPC呢?就是無(wú)法在一個(gè)進(jìn)程內(nèi),甚至一個(gè)計(jì)算機(jī)內(nèi)通過(guò)本地調(diào)用的方式完成的需求,比如比如不同的系統(tǒng)間的通訊,甚至不同的組織間的通訊。由于計(jì)算能力需要橫向擴(kuò)展,需要在多臺(tái)機(jī)器組成的集群上部署應(yīng)用
RPC的核心并不在于使用什么協(xié)議。RPC的目的是讓你在本地調(diào)用遠(yuǎn)程的方法,而對(duì)你來(lái)說(shuō)這個(gè)調(diào)用是透明的,你并不知道這個(gè)調(diào)用的方法是部署哪里。通過(guò)RPC能解耦服務(wù),這才是使用RPC的真正目的。RPC的原理主要用到了動(dòng)態(tài)代理模式,至于http協(xié)議,只是傳輸協(xié)議而已。簡(jiǎn)單的實(shí)現(xiàn)可以參考spring remoting,復(fù)雜的實(shí)現(xiàn)可以參考dubbo。
簡(jiǎn)單的說(shuō),
- RPC就是從一臺(tái)機(jī)器(客戶端)上通過(guò)參數(shù)傳遞的方式調(diào)用另一臺(tái)機(jī)器(服務(wù)器)上的一個(gè)函數(shù)或方法(可以統(tǒng)稱為服務(wù))并得到返回的結(jié)果。
- RPC 會(huì)隱藏底層的通訊細(xì)節(jié)(不需要直接處理Socket通訊或Http通訊) RPC 是一個(gè)請(qǐng)求響應(yīng)模型。
- 客戶端發(fā)起請(qǐng)求,服務(wù)器返回響應(yīng)(類似于Http的工作方式) RPC 在使用形式上像調(diào)用本地函數(shù)(或方法)一樣去調(diào)用遠(yuǎn)程的函數(shù)(或方法)。
RPC通信過(guò)程
RPC架構(gòu)簡(jiǎn)單理解
遠(yuǎn)程過(guò)程調(diào)用(RPC)詳解
默認(rèn)socket通信。本地機(jī)器的RPC框架反序列化出執(zhí)行結(jié)果,函數(shù)return這個(gè)結(jié)果

RPC和restful api對(duì)比
* REST vs JSON-RPC? - stackoverflow
既然有http 請(qǐng)求,為什么還要用rpc調(diào)用? - 手不要亂摸的回答 - 知乎
為什么需要RPC,而不是簡(jiǎn)單的HTTP接口
REST是一種設(shè)計(jì)風(fēng)格,它的很多思維方式與RPC是完全沖突的。 RPC的思想是把本地函數(shù)映射到API,也就是說(shuō)一個(gè)API對(duì)應(yīng)的是一個(gè)function,我本地有一個(gè)getAllUsers,遠(yuǎn)程也能通過(guò)某種約定的協(xié)議來(lái)調(diào)用這個(gè)getAllUsers。至于這個(gè)協(xié)議是Socket、是HTTP還是別的什么并不重要; RPC中的主體都是動(dòng)作,是個(gè)動(dòng)詞,表示我要做什么。 而REST則不然,它的URL主體是資源,是個(gè)名詞。而且也僅支持HTTP協(xié)議,規(guī)定了使用HTTP Method表達(dá)本次要做的動(dòng)作,類型一般也不超過(guò)那四五種。這些動(dòng)作表達(dá)了對(duì)資源僅有的幾種轉(zhuǎn)化方式。
RPC的根本問(wèn)題是耦合。RPC客戶端以多種方式與服務(wù)實(shí)現(xiàn)緊密耦合,并且很難在不中斷客戶端的情況下更改服務(wù)實(shí)現(xiàn)。RPC更偏向內(nèi)部調(diào)用,REST更偏向外部調(diào)用。
Web 服務(wù)應(yīng)該算是 RPC 的一個(gè)子集,理論上 RPC 能實(shí)現(xiàn)的功能, 用 Web 服務(wù)也能實(shí)現(xiàn),甚至很多 RPC 框架選用 HTTP 協(xié)議作為傳輸層。
現(xiàn)在很多網(wǎng)站的 API 都是以 HTTP 服務(wù)的形式提供的,這也算是 RPC 的一種形式。
區(qū)別主要在這 2 個(gè)東西設(shè)計(jì)的出發(fā)點(diǎn)不太一樣:
- HTTP 是面向?yàn)g覽器設(shè)計(jì)的應(yīng)用層協(xié)議,操作的核心在資源。我們更多的用 Web 服務(wù)在做網(wǎng)站。
- RPC 是為了在像在本地調(diào)用一個(gè)函數(shù)那樣調(diào)用遠(yuǎn)程的代碼而設(shè)計(jì)的,所以更關(guān)注減少本地調(diào)用和遠(yuǎn)程調(diào)用的差異,像 SOAP(簡(jiǎn)單對(duì)象訪問(wèn)協(xié)議) 這種東西是可以把對(duì)象當(dāng)參數(shù)傳的。
我們討論 RPC 和 Web 的區(qū)別,其實(shí)是在談?wù)?2 個(gè)東西:序列化協(xié)議和傳輸協(xié)議。序列化協(xié)議比如常見(jiàn)的 XML,JSON 和比較現(xiàn)代的 Protocol Buffers、Thrift。 傳輸協(xié)議比如 TCP、UDP 以及更高層的 HTTP 1.1、HTTP 2.0。
一般我們考慮用 RPC 而不是 HTTP 構(gòu)建自己的服務(wù),通常是考慮到下面的因素:
- 接口是否需要 Schema 約束
- 是否需要更高效的傳輸協(xié)議(TCP,HTTP 2.0)
- 是否對(duì)數(shù)據(jù)包的大小非常敏感
比如 HTTP 是基于文本的協(xié)議,頭部有非常多冗余(對(duì)于 RPC 服務(wù)而言)。HTTP 中我們用的最多就是 RESTful ,而 RESTful 是個(gè)弱 Schema 約束,大家通過(guò)文檔溝通,但是如果我就是不在實(shí)現(xiàn)的時(shí)候?qū)涌谖臋n約定的參數(shù)做檢查,你也不能把我怎么樣。這個(gè)時(shí)候 Thrift 這種序列化協(xié)議的優(yōu)勢(shì)就體現(xiàn)出來(lái)了,由于 Schema 的存在,可以保證服務(wù)端接受的參數(shù)和 Schema 保持一致。
RPC框架
誰(shuí)能用通俗的語(yǔ)言解釋一下什么是 RPC 框架? - 洪春濤的回答 - 知乎
常用的跨語(yǔ)言通信方案
深入淺出 RPC - 深入篇
- Call ID映射。我們?cè)趺锤嬖V遠(yuǎn)程機(jī)器我們要調(diào)用Multiply,而不是Add或者FooBar呢?在本地調(diào)用中,函數(shù)體是直接通過(guò)函數(shù)指針來(lái)指定的,我們調(diào)用Multiply,編譯器就自動(dòng)幫我們調(diào)用它相應(yīng)的函數(shù)指針。但是在遠(yuǎn)程調(diào)用中,函數(shù)指針是不行的,因?yàn)閮蓚€(gè)進(jìn)程的地址空間是完全不一樣的。所以,在RPC中,所有的函數(shù)都必須有自己的一個(gè)ID。這個(gè)ID在所有進(jìn)程中都是唯一確定的??蛻舳嗽谧鲞h(yuǎn)程過(guò)程調(diào)用時(shí),必須附上這個(gè)ID。然后我們還需要在客戶端和服務(wù)端分別維護(hù)一個(gè) {函數(shù) <--> Call ID} 的對(duì)應(yīng)表。兩者的表不一定需要完全相同,但相同的函數(shù)對(duì)應(yīng)的Call ID必須相同。當(dāng)客戶端需要進(jìn)行遠(yuǎn)程調(diào)用時(shí),它就查一下這個(gè)表,找出相應(yīng)的Call ID,然后把它傳給服務(wù)端,服務(wù)端也通過(guò)查表,來(lái)確定客戶端需要調(diào)用的函數(shù),然后執(zhí)行相應(yīng)函數(shù)的代碼。
- 序列化和反序列化??蛻舳嗽趺窗褏?shù)值傳給遠(yuǎn)程的函數(shù)呢?在本地調(diào)用中,我們只需要把參數(shù)壓到棧里,然后讓函數(shù)自己去棧里讀就行。但是在遠(yuǎn)程過(guò)程調(diào)用時(shí),客戶端跟服務(wù)端是不同的進(jìn)程,不能通過(guò)內(nèi)存來(lái)傳遞參數(shù)。甚至有時(shí)候客戶端和服務(wù)端使用的都不是同一種語(yǔ)言(比如服務(wù)端用C++,客戶端用Java或者Python)。這時(shí)候就需要客戶端把參數(shù)先轉(zhuǎn)成一個(gè)字節(jié)流,傳給服務(wù)端后,再把字節(jié)流轉(zhuǎn)成自己能讀取的格式。這個(gè)過(guò)程叫序列化和反序列化。同理,從服務(wù)端返回的值也需要序列化反序列化的過(guò)程。
- 網(wǎng)絡(luò)傳輸。遠(yuǎn)程調(diào)用往往用在網(wǎng)絡(luò)上,客戶端和服務(wù)端是通過(guò)網(wǎng)絡(luò)連接的。所有的數(shù)據(jù)都需要通過(guò)網(wǎng)絡(luò)傳輸,因此就需要有一個(gè)網(wǎng)絡(luò)傳輸層。網(wǎng)絡(luò)傳輸層需要把Call ID和序列化后的參數(shù)字節(jié)流傳給服務(wù)端,然后再把序列化后的調(diào)用結(jié)果傳回客戶端。只要能完成這兩者的,都可以作為傳輸層使用。因此,它所使用的協(xié)議其實(shí)是不限的,能完成傳輸就行。盡管大部分RPC框架都使用TCP協(xié)議,但其實(shí)UDP也可以,而gRPC干脆就用了HTTP2。Java的Netty也屬于這層的東西。
目前有很多Java的RPC框架,有基于Json的,有基于XML,也有基于二進(jìn)制對(duì)象的。
論復(fù)雜度,RPC框架肯定是高于簡(jiǎn)單的HTTP接口的。但毋庸置疑,HTTP接口由于受限于HTTP協(xié)議,需要帶HTTP請(qǐng)求頭,導(dǎo)致傳輸起來(lái)效率或者說(shuō)安全性不如RPC

常用RPC框架
支持Java最多,golang
- Netty - Netty框架不局限于RPC,更多的是作為一種網(wǎng)絡(luò)協(xié)議的實(shí)現(xiàn)框架,比如HTTP,由于RPC需要高效的網(wǎng)絡(luò)通信,就可能選擇以Netty作為基礎(chǔ)。
- brpc是一個(gè)基于protobuf接口的RPC框架,在百度內(nèi)部稱為“baidu-rpc”,它囊括了百度內(nèi)部所有RPC協(xié)議,并支持多種第三方協(xié)議,從目前的性能測(cè)試數(shù)據(jù)來(lái)看,brpc的性能領(lǐng)跑于其他同類RPC產(chǎn)品。
- Dubbo是Alibaba開(kāi)發(fā)的一個(gè)RPC框架,遠(yuǎn)程接口基于Java Interface, 依托于Spring框架。
- gRPC的Java實(shí)現(xiàn)的底層網(wǎng)絡(luò)庫(kù)是基于Netty開(kāi)發(fā)而來(lái),其Go實(shí)現(xiàn)是基于net庫(kù)。
- Thrift是Apache的一個(gè)項(xiàng)目(http://thrift.apache.org),前身是Facebook開(kāi)發(fā)的一個(gè)RPC框架,采用thrift作為IDL (Interface description language)。
- jsonrpc
JSON-RPC
python web接口實(shí)現(xiàn)(restful方式、jsonrpc方式)
區(qū)塊鏈項(xiàng)目中用的較多?資料不是很多
JSON-RPC是一種序列化協(xié)議。JSON 是 JS 對(duì)象的字符串表示法,它使用文本表示一個(gè) JS 對(duì)象的信息,本質(zhì)是一個(gè)字符串。
非常簡(jiǎn)單,方便,速度慢
相關(guān)Python 包(直接集成到flask和django)
Flask-JSONRPC,django-json-rpc;jsonrpcserver,jsonrpcclient
thrift
Python RPC 之 Thrift
Facebook開(kāi)源的跨語(yǔ)言RPC框架。
gRPC
gRPC 官方文檔中文版
深入了解gRPC協(xié)議-知乎
- tensorflow分布式與tensorflow serving底層通信都是是用的grpc
序列化用protobuf,通信使用http2 - latest Google APIs will have gRPC versions of their interfaces, letting you easily build Google functionality into your applications.
- 支持 C, C++, Node.js, Python, Ruby, Objective-C,PHP and C#
HTTP2
一文讀懂 HTTP2 特性 - 又拍云的文章 - 知乎
HTTP/2 和 HTTP/1 速度對(duì)比
http://www.http2demo.io/
HTTP/2
HTTP/2 是 HTTP 協(xié)議自 1999 年 HTTP 1.1 發(fā)布后的首個(gè)更新,主要基于 SPDY 協(xié)議。
HTTP/2的主要目標(biāo)是通過(guò)啟用完整請(qǐng)求和響應(yīng)復(fù)用來(lái)減少延遲,通過(guò)有效壓縮HTTP頭字段來(lái)最大限度地降低協(xié)議開(kāi)銷,并添加對(duì)請(qǐng)求優(yōu)先級(jí)和服務(wù)器推送的支持;多路復(fù)用(同一tcp,多個(gè)流),頭部壓縮,服務(wù)推送。
Protobuf
常用的跨語(yǔ)言通信方案
Google Protocol Buffer 的使用和原理
Protobuf 語(yǔ)法指南
Protocol Buffers 是一種輕便高效的結(jié)構(gòu)化數(shù)據(jù)存儲(chǔ)格式,可以用于結(jié)構(gòu)化數(shù)據(jù)串行化,或者說(shuō)序列化。它很適合做數(shù)據(jù)存儲(chǔ)或 RPC 數(shù)據(jù)交換格式。可用于通訊協(xié)議、數(shù)據(jù)存儲(chǔ)等領(lǐng)域的語(yǔ)言無(wú)關(guān)、平臺(tái)無(wú)關(guān)、可擴(kuò)展的序列化結(jié)構(gòu)數(shù)據(jù)格式。目前提供了 C++、Java、Python 三種語(yǔ)言的 API。
同 XML 相比, Protobuf 的主要優(yōu)點(diǎn)在于性能高。它以高效的二進(jìn)制方式存儲(chǔ),比 XML 小 3 到 10 倍,快 20 到 100 倍。
框架選擇
gRPC vs Thrift
RPC框架性能基本比較測(cè)試
怎么看待谷歌的開(kāi)源 RPC 框架 gRPC? - 知乎
微服務(wù)的服務(wù)間通信與服務(wù)治理
最佳實(shí)踐 | 7大維度看國(guó)外企業(yè)為啥選擇gRPC打造高性能微服務(wù)?
如何選擇
什么時(shí)候應(yīng)該選擇gRPC而不是Thrift
需要良好的文檔、示例
喜歡、習(xí)慣HTTP/2、ProtoBuf
對(duì)網(wǎng)絡(luò)傳輸帶寬敏感
什么時(shí)候應(yīng)該選擇Thrift而不是gRPC
需要在非常多的語(yǔ)言間進(jìn)行數(shù)據(jù)交換
對(duì)CPU敏感
協(xié)議層、傳輸層有多種控制要求
需要穩(wěn)定的版本
不需要良好的文檔和示例
總的來(lái)說(shuō),Python rpc框架選擇較少,thrift性能最好,grpc性能比thrift稍差,原因是多了http2,而thrift直接基于tcp,但grpc序列化方案更通用(protobuf)優(yōu)秀,文檔較好;
jsonrpc 本身基于http/1進(jìn)行通信,速度最慢,相對(duì)于之前速度無(wú)提升,只是接口和數(shù)據(jù)格式更為統(tǒng)一;
gRPC不足
1)GRPC尚未提供連接池
2)尚未提供“服務(wù)發(fā)現(xiàn)”、“負(fù)載均衡”機(jī)制
3)因?yàn)榛贖TTP2,絕大部多數(shù)HTTP Server、Nginx都尚不支持,即Nginx不能將GRPC請(qǐng)求作為HTTP請(qǐng)求來(lái)負(fù)載均衡,而是作為普通的TCP請(qǐng)求。(nginx將會(huì)在1.9版本支持)