HTTP VS RPC
先再次重復強調一遍,通信協議不是 rpc 最重要的部分,不要被這類回答帶偏。如果要了解 rpc 請更多的去了解服務治理(SOA)的一些基本策略,推薦去看看 dubbo 的相關文檔。
一、詳解
rpc是遠端過程調用,其調用協議通常包含:傳輸協議 和 序列化協議。
- 傳輸協議:比如著名的 grpc,它底層使用的是 http2 協議;還有 dubbo 一類的自定義報文的 tcp 協議
- 序列化協議:例如基于文本編碼的 json 協議;也有二進制編碼的 protobuf、hession 等協議;還有針對 java 高性能、高吞吐量的 kryo 和 ftc 等序列化協議
因此我理解大部人理解誤區的問題應該是:為什么要使用自定義 tcp 協議的 rpc 做后端進程通信?
解答:要解決這個問題就應該搞清楚 http 使用的 tcp 協議,和我們自定義的 tcp 協議在報文上的區別。
- 首先要 否認 一點 http 協議相較于 自定義tcp 報文協議,增加的開銷在于連接的建立與斷開。
- 第一、http協議是支持連接池復用的,也就是建立一定數量的連接不斷開,并不會頻繁的創建和銷毀連接
- 第二、http也可以使用 protobuf 這種二進制編碼協議對內容進行編碼
因此二者即 http 和 rpc 最大的區別還是在傳輸協議上。
即使編碼協議也就是 body 是使用二進制編碼協議,報文元數據也就是header頭的鍵值對卻使用了文本編碼,非常占字節數。如上圖所使用的報文中有效字節數僅僅占約 30%,也就是70%的時間用于傳輸元數據廢編碼。當然實際情況下報文內容可能會比這個長,但是報頭所占的比例也是非常可觀的。
那么假如我們使用自定義tcp協議的報文如下:
報頭占用的字節數也就只有16個byte,極大地精簡了傳輸內容。這也就是為什么后端進程間通常會采用 自定義tcp協議 的 rpc 來進行通信的原因。
二、不單效率那么簡單
- 所謂的效率優勢是針對 http1.1協議 來講的,http2.0協議 已經優化編碼效率問題,像 grpc 這種 rpc 庫使用的就是 http2.0協議。這么來說吧,http容器的性能測試單位通常是kqps,自定義tpc協議則通常是以 10kqps 到 100kqps為基準。
- 簡單來說成熟的 rpc庫相對 http容器,更多的是封裝了 “服務發現”,"負載均衡",“熔斷降級” 一類面向服務的高級特性。可以這么理解,rpc框架是面向服務的更高級的封裝。如果把一個http servlet 容器上封裝一層服務發現和 函數代理調用,那它就已經可以做一個rpc框架了。
- 因為良好的 rpc 調用是 面向服務的封裝,針對服務的 可用性 和 效率 等都做了優化。單純使用http調用則缺少了這些特性。
- 可以這樣說:用http不是因為它性能好,而是因為它普適,隨便一個web容器就能跑起來你的應用。
三、RPC 底層是怎么實現的
對于以上兩個問題,這里用一個圖來一一說明:
上圖是一個比較完整的關系圖,這時我們發現HTTP(圖中藍色框)出現了兩次。
- 其中一個是 和 RPC并列的,都是跨應用調用方法的解決方案;
- 另一個則是被RPC包含的,是RPC通信過程的可選協議之一。
- 第一個問題的答案是都對。看指的是哪一個藍色框。從題主的提問看,既然題主在糾結這兩者,應該是指與RPC并列的藍色框。
- 第二個問題是在問遠程過程調用(紅色框)是不是包含了Restful(黃色框),這種理解的關鍵在于對RPC的理解。
RPC字面理解是"遠程過程調用",即在一個應用中調用另一個應用的方法。那Restful是滿足的,通過它可以實現在一個應用中調用另一個應用的方法。但是,上述理解使得RPC的定義過于寬泛。RPC通常特指在一個應用中調用另一個應用的接口而實現的遠程調用,即紅色框所指的范圍。這樣,RPC是不包含Restful的。
因此,第二個問題的答案是Restful不屬于RPC。
RPC的英文全稱是:Remote Procedure Call,翻譯為中文叫 “遠程過程調用”。其中稍顯晦澀的其實就是“過程”,過程其實就是“方法”。所以,可以把RPC理解為“遠程方法調用”。要了解遠程過程調用,那先理解過程調用。非常簡單,如下圖,就是調用一個方法。這太常見了,不多解釋。
而在分布式系統中,因為每個服務的邊界都很小,很有可能調用別的服務提供的方法。這就出現了服務A 調用 服務B 中方法的需求,即遠程過程調用。要想讓服務A 調用 服務B 中的方法,最先想到的就是通過 HTTP 請求實現。是的,這是很常見的,例如 服務B 暴露 Restful接口,然后讓 服務A 調用它的接口。基于Restful的調用方式因為可讀性好(服務B暴露出的是Restful接口,可讀性當然好)而且HTTP請求可以通過各種防火墻,因此非常不錯。然而,如前面所述,基于Restful的遠程過程調用有著明顯的缺點,主要是效率低、封裝調用復雜。當存在大量的服務間調用時,這些缺點變得更為突出。服務A 調用 服務B 的過程是應用間的內部過程,犧牲可讀性提升效率、易用性是可取的。基于這種思路,RPC產生了。
通常,RPC要求在調用方中放置被調用的方法的接口。調用方只要調用了這些接口,就相當于調用了被調用方的實際方法,十分易用。于是,調用方可以像調用內部接口一樣調用遠程的方法,而不用封裝參數名和參數值等操作。
那要想實現這個過程該怎么辦呢?別急,咱們一步一步來。
- 首先,調用方調用的是接口,必須得為接口構造一個假的實現。顯然,要使用動態代理。這樣,調用方的調用就被動態代理接收到了。
- 動態代理接收到調用后,應該想辦法調用遠程的實際實現。這包括下面幾步:
- 這樣,遠程的服務就接收到了調用方的請求。它應該:
整個過程如下所示。
這樣,RPC操作就完成了。調用方調用內部的一個方法,但是被RPC框架偷梁換柱為遠程的一個方法。之間的通信數據可讀性不需要好,只需要RPC框架能讀懂即可,因此效率可以更高。通常使用UDP或者TCP作為通訊協議,當然也可以使用HTTP。
四、RPC和restful api對比
REST是一種設計風格,它的很多思維方式與RPC是完全沖突的。 RPC的思想是把本地函數映射到API,也就是說一個API對應的是一個function,我本地有一個getAllUsers,遠程也能通過某種約定的協議來調用這個getAllUsers。至于這個協議是Socket、是HTTP還是別的什么并不重要; RPC中的主體都是動作,是個動詞,表示我要做什么。 而REST則不然,它的URL主體是資源,是個名詞。而且也僅支持HTTP協議,規定了使用HTTP Method表達本次要做的動作,類型一般也不超過那四五種。這些動作表達了對資源僅有的幾種轉化方式。
RPC的根本問題是耦合。RPC客戶端以多種方式與服務實現緊密耦合,并且很難在不中斷客戶端的情況下更改服務實現。RPC更偏向內部調用,REST更偏向外部調用。
Web 服務應該算是 RPC 的一個子集,理論上 RPC 能實現的功能, 用 Web 服務也能實現,甚至很多 RPC 框架選用 HTTP 協議作為傳輸層。
現在很多網站的 API 都是以 HTTP 服務的形式提供的,這也算是 RPC 的一種形式。
區別主要在這 2 個東西設計的出發點不太一樣:
- HTTP 是面向瀏覽器設計的應用層協議,操作的核心在資源。我們更多的用 Web 服務在做網站。
- RPC是為了在像在本地調用一個函數那樣調用遠程的代碼而設計的,所以更關注減少本地調用和遠程調用的差異,像 SOAP(簡單對象訪問協議)這種東西是可以把對象當參數傳的。
我們討論 RPC 和 Web 的區別,其實是在談論 2 個東西:序列化協議和傳輸協議。序列化協議比如常見的 XML,JSON 和比較現代的 Protocol Buffers、Thrift。 傳輸協議比如 TCP、UDP 以及更高層的 HTTP 1.1、HTTP 2.0。
一般我們考慮用 RPC 而不是 HTTP 構建自己的服務,通常是考慮到下面的因素:
- 接口是否需要 Schema 約束
- 是否需要更高效的傳輸協議(TCP,HTTP 2.0)
- 是否對數據包的大小非常敏感
比如 HTTP 是基于文本的協議,頭部有非常多冗余(對于 RPC 服務而言)。HTTP 中我們用的最多就是 RESTful ,而 RESTful 是個弱 Schema 約束,大家通過文檔溝通,但是如果我就是不在實現的時候對接口文檔約定的參數做檢查,你也不能把我怎么樣。這個時候 Thrift 這種序列化協議的優勢就體現出來了,由于 Schema 的存在,可以保證服務端接受的參數和 Schema 保持一致。
關于序列化協議
參考文章
參考文章
文章大部分轉自
總結
以上是生活随笔為你收集整理的HTTP VS RPC的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2020中国消费金融行业研究报告
- 下一篇: 互联网日报 | 3月2日 星期二 |