gRPC vs REST:兩種API架構風格的對比

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"想知道未來是不是gRPC的天下?本文會具體介紹兩種API架構風格:REST和gRPC,並討論它們之間的區別。不過,首先,我們會解釋什麼是API,以及爲什麼它對微服務基礎設施而言至關重要。之後,我們會介紹gRPC的基礎——RPC,並探討gRPC和REST API之間的重要差異。根據它們的對比結果,我們最後會分析什麼時候應該使用哪種架構類型。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"API是什麼"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"API,即應用程序編程接口。這些接口充當軟件中介,爲應用程序之間的交互和對話建立特定的定義和規則。API負責將響應從用戶傳遞到系統,然後從系統返回給用戶。聽起來還是有點糊塗?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/60\/60372699d270a9261f9224438d37cdfb.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":"center","origin":null},"content":[{"type":"text","text":"API的工作機制"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"假設我們正在預訂一個酒店。我們在筆記本電腦上訪問酒店預訂頁面,連接到互聯網的這個頁面會將數據(我們的請求)發送到服務器。然後,服務器檢索數據,解析它,一旦所需的操作得到執行,它就會向我們發送一個響應,並在我們的界面上提供信息。這個過程需要API才能實現。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"API 指定了一個應用程序(網頁或移動應用)可以向另一個應用程序發出的請求類型,並進一步確定:如何發出這些請求;使用哪些數據格式;以及用戶必須遵循的實踐。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"本文會對比gRPC 和REST 兩大架構風格,因爲它們代表了人們創建API時最常用的兩種架構風格。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"API和微服務"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"一方面,在單體應用程序中,項目的所有功能都包含在一個單元中,更準確地說是包含在一個代碼庫中。另一方面,微服務架構由一些較小的服務組成,這些服務使用HTTP等協議相互通信。作爲微服務架構一部分的組件服務通過API相互通信和交互。換句話說,API允許集成到微服務應用程序中的所有服務互相連接和通信。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"最常用的架構風格是REST API。但構建API時主要有3種模型:RPC(遠程過程調用)、REST(表徵狀態傳輸)和GraphQL。在本文中,我們將重點介紹前兩個。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"什麼是RPC?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"RPC使用客戶端-服務器模型。請求服務器(換句話說就是客戶端)請求一條消息,該消息由RPC轉換併發送到另一臺服務器。服務器收到請求後將響應發送回客戶端。當服務器處理這個調用時,客戶端被阻塞,服務器內部的消息傳遞被隱藏。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"此外,RPC允許客戶端以特定格式請求函數,並以完全相同的格式接收響應。在URL中可以找到使用RPC API提交調用的方法。RPC支持本地和分佈式環境中的遠程過程調用。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"與REST API一樣,RPC還建立了交互規則以及用戶如何提交“調用”(請求)以調用方法與服務通信和交互的機制。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"什麼是REST?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"使用REST API時,來自後端數據的響應通過JSON或XML消息格式傳遞給客戶端(或用戶)。這種架構模型傾向於遵循HTTP協議。然而,在維護RCP模型的同時,RCP設計也時常從HTTP中汲取一些想法。事實上,不管使用的是哪種模型(RPC或REST),大多數現代API實現都將API映射到相同的HTTP協議時。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當REST API公開可用時,每個集成微服務應用程序的服務都可以作爲資源呈現給用戶\/客戶端,資源可以通過以下HTTP命令訪問:"},{"type":"codeinline","content":[{"type":"text","text":"GET"}]},{"type":"text","text":"、"},{"type":"codeinline","content":[{"type":"text","text":"DELETE"}]},{"type":"text","text":"、"},{"type":"codeinline","content":[{"type":"text","text":"POST"}]},{"type":"text","text":"和"},{"type":"codeinline","content":[{"type":"text","text":"PUT"}]},{"type":"text","text":"。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"什麼是gRPC?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"gRPC是Google Remote Procedure Call的簡寫,是基於RCP架構的變體。該技術遵循一個使用HTTP 2.0協議的RPC API實現,但HTTP不會呈現給API開發人員或服務器。因此,開發人員無需擔心RPC概念如何映射到HTTP,從而降低了複雜性。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"總的來說,gRPC旨在加快微服務之間的數據傳輸。它的基礎方法是確定一個服務,建立方法和相應的參數來實現遠程調用和返回類型。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"此外,它以"},{"type":"text","marks":[{"type":"strong"}],"text":"一個IDL(接口描述語言)表示RPC API模型"},{"type":"text","text":",這爲確定遠程過程提供了更直接的方法。默認情況下,IDL使用"},{"type":"text","marks":[{"type":"strong"}],"text":"Protocol Buffers"},{"type":"text","text":"(但也可以使用其他替代方案)來描述服務接口以及負載消息的結構。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"gRPC與REST:對比"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"現在,我們對gRPC和REST有了一個初步認識,下面我們來看看它們的主要區別。"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"HTTP 1.1 vs HTTP 2"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"REST API遵循一個通常基於HTTP 1.1構建的"},{"type":"text","marks":[{"type":"strong"}],"text":"請求-響應通信模型"},{"type":"text","text":"。不幸的是,這意味着如果一個微服務收到來自多個客戶端的多個請求,該模型必須每次只處理一個請求,拖慢了整個系統的速度。REST API也可以構建在HTTP 2上,但通信的請求-響應模型保持不變,這使得REST API無法充分利用HTTP 2的優勢,例如"},{"type":"text","marks":[{"type":"strong"}],"text":"流式通信"},{"type":"text","text":"和"},{"type":"text","marks":[{"type":"strong"}],"text":"雙向支持"},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"gRPC沒有面臨類似的障礙。它建立在HTTP 2之上,且遵循客戶端-響應通信模型。這讓它支持雙向通信和流式通信,因爲gRPC能接收來自多個客戶端的多個請求,並通過不斷地流式傳輸信息來同時處理這些請求。此外,gRPC還可以處理“一元”交互,例如構建在HTTP 1.1上的交互。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"總之,gRPC能處理一元交互和多種類型的流:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"一元:客戶端發出單個請求並接收單個響應。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"服務器流:服務器對客戶端的請求響應一個消息流。當全部數據發送完畢後,服務器會再發送一條狀態消息來完成流程。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"客戶端流:客戶端向服務器發送一個消息流,並接收單個響應消息。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"雙向流:客戶端和服務器的兩個流互相獨立,也就是說它們都能以任何順序傳輸消息。客戶端負責發起並結束雙向流。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/15\/155a193c6cbba97475ed4bb8c4304093.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":"center","origin":null},"content":[{"type":"text","text":"流類型"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"瀏覽器支持"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這可能是REST相對於gRPC的主要優勢之一。一方面,所有瀏覽器都完全支持REST。另一方面,gRPC獲得的瀏覽器支持仍然非常有限。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"不幸的是,它需要gRPC-web和一個代理層來執行HTTP 1.1和HTTP 2之間的轉換。因此,gRPC主要用於內部\/私有系統(特定組織的後端數據和應用程序功能中的API程序)。"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"負載數據結構"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如前所述,gRPC默認使用Protocol Buffers來序列化負載數據。這個方案更輕便,因爲它支持高度壓縮的格式並減少了消息的大小。此外,Protobuf(或Protocol Buffer)是二進制的;它對結構化數據進行序列化和反序列化,以便通信和傳輸。換句話說,強類型消息可以自動從Protobuf轉換爲客戶端和服務器的編程語言。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"相比之下,REST主要依靠JSON或XML格式來發送和接收數據。事實上,即使它不強制要求任何結構,JSON也是最流行的格式,因爲它具有靈活性和發送動態數據的能力,而不必遵循嚴格的結構。使用JSON的另一顯著優勢是其人類可讀水平,這方面Protobuf尚無法與之競爭。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"儘管如此,JSON在數據傳輸方面並不夠輕量或快速。其原因在於,在使用REST時,必須將JSON(或其他格式)序列化並轉換爲客戶端和服務器端使用的編程語言。這在傳輸數據的過程中增加了一個額外步驟,從而可能會損害性能並增加出現錯誤的可能性。"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"代碼生成功能"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"與gRPC不同,REST API不提供內置代碼生成功能,這意味着開發人員必須使用Swagger或Postman等第三方工具爲API請求生成代碼。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"相比之下,gRPC由於其protoc編譯器而具有原生代碼生成功能,該編譯器與多種編程語言兼容。這對於集成了以不同語言和平臺開發的各種服務的微服務系統來說尤其方便。此外,內置的代碼生成器還有助於創建SDK(軟件開發工具包)。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"gRPC與REST:對比表"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/2a\/2a885d8675c884668da19cafd345b487.jpeg","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"何時使用gRPC,何時使用REST?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如前所述,儘管gRPC提供了許多優勢,但它有一個主要障礙:瀏覽器兼容性低。因此,gRPC的用例一般侷限在內部\/私有系統。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"相比之下,正如我們所討論的那樣,REST API可能有其缺點,但它們仍然是連接基於微服務的系統的最流行的API。此外,REST遵循HTTP協議標準化並提供通用支持,使這種API架構風格成爲Web服務開發以及應用程序和微服務集成的首選。然而,這並不意味着我們應該忽視gRPC的應用場景。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"gRPC架構風格具有很多值得(並且應該)探索的有前途的特性。它是處理多語言系統和實時流的絕佳選擇,例如,當運營需要輕量級消息傳輸(可以由序列化Protobuf消息支持)的IoT系統時,gRPC就很合適。此外,gRPC也可以考慮用於移動應用程序,因爲它們不需要瀏覽器,且消息體積更小,不會拖慢移動設備的速度。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"結論"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"gRPC提供了很多優勢。與REST不同,它可以充分利用HTTP 2,使用多路複用流並遵循二進制協議。此外,由於Protobuf消息結構,它還具備性能優勢,支持多語言環境的內置代碼生成功能也是一大好處。這些因素使gRPC成爲了一種很有前途的API架構風格。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"儘管如此,瀏覽器支持不足使gRPC很難匹敵REST的通用支持能力。REST仍然是微服務系統中的粘合劑,是最流行的解決方案。因此它很可能會存在很長時間,而且說實話,它是一個非常成熟和成功的架構。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"原文鏈接:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"https:\/\/www.imaginarycloud.com\/blog\/grpc-vs-rest\/?fileGuid=3WQyP6YQDvcqhcXx"}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章