gRPC?vs?REST:創(chuàng)建API的方法比較
譯文譯者 | 李睿
審校 | 重樓
本文對gRPC和REST的特征和區(qū)別進行了介紹,這可能是當今創(chuàng)建API最常用的兩種方法。
以下將從這兩種工具的特征開始,也就是它們是什么以及提供什么功能。然后,將根據(jù)七個方面對它們進行比較,這對現(xiàn)代系統(tǒng)來說是最重要的7個類別。
其類別如下:
(1)底層HTTP協(xié)議
(2)支持的數(shù)據(jù)格式
(3)數(shù)據(jù)大小
(4)吞吐量
(5)定義
(6)易于采用
(7)工具支持
gRPC的介紹
當人們聽到API時,可能馬上想到REST API。然而,REST是構(gòu)建API的眾多方法之一。它并不是適用于所有用例的靈丹妙藥。還有其他方法,遠程過程調(diào)用 (RPC)只是其中之一,而gRPC可能是使用RPC最成功的框架。
盡管gRPC是一種相當成熟和高效的技術(shù),但它仍然被視為一種新技術(shù)。因此,盡管在某些用例中非常方便,但它沒有REST被廣泛采用。
本文主要介紹gRPC,并指出它可以發(fā)揮作用的用例。
什么是REST
表述性狀態(tài)轉(zhuǎn)移(REST)可能是創(chuàng)建公開任何類型API的應(yīng)用程序的最常用方法。它使用HTTP作為底層通信媒介。正因為如此,它可以從HTTP的所有優(yōu)點中獲益,例如緩存。
- 客戶端-服務(wù)器通信
 - 無狀態(tài)通信
 - 緩存
 - 統(tǒng)一接口
 - 分層系統(tǒng)
 - 按需編碼
 
REST的兩個關(guān)鍵概念是:
(1)端點:表示特定資源的唯一統(tǒng)一資源定位符(URL);可以看作是通過互聯(lián)網(wǎng)訪問特定操作或數(shù)據(jù)元素的一種方式。
(2)資源:在特定URL下可用的特定數(shù)據(jù)塊。
此外,還有一個叫做Richardson成熟模型的描述——這是一個描述REST API中“專業(yè)性”程度的模型。它根據(jù)特定API具有的特征集將REST API劃分為3個級別(或4個級別,取決于是否將級別0計算在內(nèi))。
其中一個特征是REST端點應(yīng)該在URL中使用名詞,并使用正確的HTTP請求方法來管理其資源。
- 示例:用DELETE user/1代替GET user/deleteById/1
 
至于HTTP方法及其相關(guān)操作,如下所示:
- GET—檢索特定的資源或資源集合。
 - POST—創(chuàng)建一個新的資源。
 - PUT—修改整個資源。
 - PATCH -特定資源的部分更新。
 - DELETE—刪除指定id的資源。
 
成熟度模型規(guī)定的遠不止這些。例如稱為HyperMedi的概念。HyperMedia將數(shù)據(jù)的呈現(xiàn)和對客戶端可以執(zhí)行的操作的控制結(jié)合在一起。
對成熟度模型的完整描述超出了本文的范圍。
什么是gRPC?
gRPC是遠程過程調(diào)用(RPC)這個相對古老的概念的另一種實現(xiàn)。谷歌的開發(fā)人員創(chuàng)建了它,這就是為什么它的名稱里有“g”的原因。它可能是處理RPC最現(xiàn)代和最有效的工具,也是CNCF孵化項目。
gRRC使用谷歌公司的協(xié)議緩沖區(qū)作為序列化格式,同時利用HTTP/2作為傳輸介質(zhì)數(shù)據(jù),盡管gRPC也可以使用JSON作為數(shù)據(jù)層。
- 方法:gRPC的基本構(gòu)建塊,每個方法都是一個遠程過程調(diào)用,它接受一些輸入并返回輸出。它執(zhí)行用所選編程語言進一步實現(xiàn)的單個操作。目前,gRPC支持4種方法:
 
①Unary:經(jīng)典的請求-響應(yīng)模型,該方法接受輸入并返回輸出。
②服務(wù)器流:該方法接受消息作為輸入,同時返回消息流作為輸出。gRPC保證了單個RPC調(diào)用中的消息排序。
③客戶端流:該方法將消息流作為輸入,處理它們直到?jīng)]有消息為止,然后返回一條消息作為輸出。與上面類似,gRPC保證在單個RPC調(diào)用中進行消息排序。
④雙向流:該方法將消息流作為輸入,并將消息流作為輸出返回,有效地使用了讀和寫兩個消息流。兩個流都獨立運行,并且將消息順序保留在流級別上。
- 服務(wù):表示一組方法,每個方法在服務(wù)中必須有其唯一的名稱。服務(wù)還描述了安全性、超時或重試等特性。
 - 消息:表示方法的輸入或輸出的對象。
 
gRPC API定義以.proto文件的形式編寫,其中包含上述所有三個基本構(gòu)建塊。此外,gRPC提供了一個協(xié)議緩沖區(qū)編譯器,它從.proto文件生成客戶端和服務(wù)代碼。
用戶可以隨心所欲地實現(xiàn)服務(wù)器端方法,必須堅持使用API的輸入輸出契約。
在客戶端,有一個叫做客戶端(或stub)的對象——類似于HTTP客戶端。它知道來自服務(wù)器的所有方法,只處理調(diào)用遠程過程并返回它們的響應(yīng)。
gRPC和REST的比較
(1)底層HTTP協(xié)議
這是第一類,可能也是最重要的一類,因為它的影響也可以在其他方面看到。
一般來說,REST是基于請求-響應(yīng)的,并使用HTTP/1.1作為傳輸媒介。這里必須使用不同的協(xié)議,例如WebSocket或任何類型的流或更持久的連接。
還可以實現(xiàn)一些簡單的代碼,使REST看起來像消息流。更重要的是,使用HTTP/1.1 REST需要每個請求-響應(yīng)交換一個連接。對于長時間運行的請求,或者當網(wǎng)絡(luò)容量有限時,這種方法可能會有問題。
當然,可以使用HTTP/2來構(gòu)建類似REST的API;然而,并不是所有的服務(wù)器和庫都支持HTTP/2。因此,其他地方可能會出現(xiàn)問題。
另一方面,gRPC只使用HTTP/2。它允許通過單個TCP連接發(fā)送多個請求-響應(yīng)對。這種方法可以顯著地提高應(yīng)用程序的性能。
- 結(jié)果:gRPC略有獲勝
 
(2)支持的數(shù)據(jù)格式
假設(shè)REST API使用HTTP/1.1的默認情況,那么它可以支持多種格式。
REST通常不對消息格式和樣式施加任何限制。基本上,任何一種可以序列化為普通舊文本的格式都是有效的。用戶可以在特定場景中使用最適合自己的任何格式。
在REST應(yīng)用程序中發(fā)送數(shù)據(jù)的最流行格式無疑是JSON。XML排在第二位,因為有大量的較舊/遺留應(yīng)用程序。
然而,當使用REST和HTTP/2時,只支持二進制交換格式。在這種情況下,可以使用Protobuf或Avro。當然,這種方法也有它的缺點,但在以下幾點中會詳細說明這一點。
同時,gRPC只支持兩種數(shù)據(jù)交換格式:
①Protobuf —默認情況下。
②JSON—當需要與原有API集成時。
如果用戶嘗試使用JSON,那么gRPC將使用JSON作為消息的編碼格式,而使用GSON作為消息格式。此外,使用JSON需要做更多的配置。
- 結(jié)果:REST獲勝,因為它支持更多格式。
 
(3)數(shù)據(jù)大小
默認情況下,gRPC使用二進制數(shù)據(jù)交換格式,這顯著地減少了通過網(wǎng)絡(luò)發(fā)送的消息的大小:研究表明,以字節(jié)計算,大約減少了40%~50%,而從以前的一個項目中獲得的經(jīng)驗表明,甚至減少了50%~70%。
以上提供了JSON和Protobuff之間相對深入的大小比較。本文作者還提供了一個生成JSON和二進制文件的工具。這樣就可以重新運行他的實驗并比較結(jié)果。
本文中的對象相當簡單。不過,一般的規(guī)則是——嵌入的對象越多,JSON的結(jié)構(gòu)越復(fù)雜,它就會比Protobuf更重。50%的大小差異有利于Protobuf 是一個很好的基線。
在使用REST的二進制交換格式時,可以最大限度地減少或消除這種差異。然而,這不是最常見的,也不是最受支持的RESTful API方式,因此可能會出現(xiàn)其他問題。
- 結(jié)果:默認情況下,gRPC獲勝;在兩者都使用二進制數(shù)據(jù)格式的情況下,雙方為平局。
 
(4)吞吐量
同樣,在REST的情況下,一切都取決于底層HTTP協(xié)議和服務(wù)器。
在默認情況下,基于HTTP/1.1的REST,即使是最高性能的服務(wù)器也無法擊敗gRPC的性能,特別是當使用JSON時添加序列化和反序列化開銷時。雖然當切換到HTTP/2時,差異似乎有所減少。
至于最大吞吐量,在這兩種情況下,HTTP都是一種傳輸媒介,因此它具有無限擴展的潛力。因此,一切都取決于正在使用的工具以及對應(yīng)用程序的精確操作,因為設(shè)計沒有限制。
- 結(jié)果:默認情況下為gRPC;在同時使用二進制數(shù)據(jù)和HTTP/2的情況下,gRPC略勝一籌。
 
(5)定義
在這一部分中,將描述如何在這兩種方法中定義消息和服務(wù)。
在大多數(shù)REST應(yīng)用程序中,只是將請求和響應(yīng)聲明為類、對象或特定語言支持的任何結(jié)構(gòu)。然后,依靠提供的庫來序列化和反序列化JSON/XML/YAML或任何需要的格式。
此外,目前正在努力創(chuàng)建能夠根據(jù)Swagger的REST API定義用所選編程語言生成代碼的工具。然而,它們似乎是在alpha版本中,所以仍然可能會出現(xiàn)一些錯誤和小問題,這將使它們難以使用。
REST應(yīng)用程序的二進制格式和非二進制格式之間幾乎沒有區(qū)別,因為這兩種情況下的規(guī)則大致相同。對于二進制格式,只是以特定格式所需的方式定義所有內(nèi)容。
此外,可以通過來自底層庫或框架的方法或注釋來定義REST服務(wù)。該工具還負責將其與其他配置一起向外部世界公開。
在gRPC的情況下,將Protobuf作為默認的并且事實上是編寫定義的唯一方式。必須在.proto文件中聲明所有內(nèi)容:消息、服務(wù)和方法,所以事情非常簡單。
然后使用gRPC提供的工具生成代碼,只需要實現(xiàn)自己的方法。在那之后,一切都應(yīng)該按預(yù)期工作。
此外,Protobuf支持導(dǎo)入,因此能夠以一種相當簡單的方式將設(shè)置擴展到多個文件。
- 結(jié)果:在這里沒有贏家,給出的描述和建議是,選擇最適合自己的方法。
 
(6)易于采用
在這一部分中,將比較現(xiàn)代編程語言中對每種方法的庫/框架支持。
本文作者表示,在他作為軟件工程師的職業(yè)生涯中,遇到的每種編程語言(Java、Scala、Python)都至少有3個主要的庫/框架用于創(chuàng)建類REST應(yīng)用程序,更不用說將JSON解析為對象/類的庫了。
此外,由于REST默認使用人類可讀的格式,因此對于新手來說,它更容易調(diào)試和使用。這也會影響交付新特性的速度,并幫助用戶應(yīng)對代碼中出現(xiàn)的錯誤。
長話短說,對REST風格應(yīng)用程序的支持至少非常好。
在Scala中,甚至有一個叫做Tapir的工具。Tapir允許用戶抽象HTTP服務(wù)器,并編寫可用于多個服務(wù)器的端點。
gRPC本身為超過8種流行的編程語言提供了客戶端庫。這通常就足夠了,因為這些庫包含了制作gRPC API所需的所有內(nèi)容。此外,一些庫為Java(通過Spring Boot Starter)和Scala提供了更高的抽象。
另一件事是,REST如今被認為是一個世界性的標準和構(gòu)建服務(wù)的切入點,而RPC和gRPC,特別是,盡管在這一點上有點過時,但仍然被視為一種新奇事物。
- 結(jié)果:REST被更廣泛地采用,并且有更多的庫和框架。
 
(7)工具支持
以上已經(jīng)介紹了庫、框架和一般市場份額,所以在這一部分中介紹圍繞這兩種風格的工具。它意味著用于測試、性能/壓力測試和文檔的工具。
①自動化測試
首先,在REST的情況下,用于構(gòu)建自動化測試的工具被構(gòu)建到不同的庫和框架中,或者是為了這個唯一目的而構(gòu)建的獨立工具,比如REST-assured。
在gRPC的情況下,可以生成一個stub并將其用于測試。如果想要更嚴格,可以將生成的客戶端作為一個單獨的應(yīng)用程序使用,并將其用作對實際服務(wù)進行測試的基礎(chǔ)。
關(guān)于gRPC的外部工具支持,需要知道:
- Postman程序?qū)RPC的支持。
 - 在IDE中使用的JetBrains HTTP客戶端也可以通過一些最低配置來支持gRPC。
 - 結(jié)果一:REST獲得勝利。然而,gRPC的情況似乎有所改善。
 
②性能測試
在這里,REST具有顯著的優(yōu)勢,因為像JMeter或Gatling這樣的工具使REST API的壓力測試變得相當容易。
不幸的是,gRPC沒有這樣的支持。在當前的Gatling版本中包含了gRPC插件,所以情況似乎正在好轉(zhuǎn)。
然而到目前為止,只有一個名為ghz的非官方插件和庫。這些都很好;它只是與REST的支持級別不同。
- 結(jié)果二:REST的勝利;然而,gRPC的情況似乎有所改善。
 
③文檔
在API文檔方面,隨著OpenAPI和Swagger在整個行業(yè)被廣泛采用并成為事實上的標準,REST再次取得了勝利。幾乎所有用于REST的庫都能夠以最小的努力或開箱即用的方式公開Swagger文檔。
不幸的是,gRPC沒有這樣的文檔。
然而,問題是gRPC是否需要這樣的工具。gRPC在設(shè)計上比REST更具描述性,因此可能需要其他文檔工具。
一般來說,帶有API描述的.proto文件比負責編寫REST API代碼的代碼更具聲明性和緊湊性,因此可能不需要gRPC提供更多文檔。
- 結(jié)果三:REST的勝利。然而,關(guān)于gRPC文檔的問題是開放的。
 
④總體結(jié)果
這是REST的一次重大勝利。
總結(jié)
以下是gRPC和REST比較的最終得分表。

得出的結(jié)論是:gRPC和REST的比較結(jié)果平分秋色,各有三場勝利,沒有明顯的贏家。
因此沒有什么靈丹妙藥,用戶只需要考慮哪些類別可能對應(yīng)用程序最重要,然后選擇在大多數(shù)類別中獲勝的方法。
本文作者表示,如果可以的話,他會嘗試使用gRPC,因為gRPC在他的上一個項目中運行得非常好。它可能是比原有的REST更好的選擇。
原文標題:gRPC vs REST:Comparing Approaches for Making APIs,作者:Bart?omiej ?yliński















 
 
 














 
 
 
 