API 設計:瞭解 gRPC、OpenAPI 和 REST 以及使用它們的時機(下)

本系列文的上半部,我們介紹了 gRPC、REST 與 OpenAPI 三種 API 模型的特性,並說明比較了 REST 與 OpenAPI 各自的優勢,若有興趣而還沒閱讀文章的朋友,可以點此連結閱讀。接下來,本文會繼續說明 gRPC 與 OpenAPI 的比較。

什麼情況下,gRPC 會是比 OpenAPI 更好的選擇?

使用 OpenAPI 描述 API 的挑戰,是定義 URL 路徑和 HTTP 方法來解釋你的「選擇」和「參數」。這是一項艱難的工作,因為有很多選擇。對於大多數項目而言,你無法得知是否為省時又省力的方式。上篇文章提過、由 Pascal Chambon 所撰寫的部落文章探討 SOAP 和 REST 間的關係,還詳細地描述了這種方式所帶來的挫折,而這篇文章也向我們展示了 RPC 的範例。

Chambon 的文章有部分錯誤資訊與誤解,而大家的回應也多集中在糾正上,但是 Chambon 的錯誤反而支援了他的論點──即使自己設計類似的概念,要從 RPC 轉移到 HTTP 上還是很困難的。

大多數針對 Chambon 的文章所提的建議都是將 REST 作為 RPC 的替代方案,畢竟這也是 Chambon 和大多數人較熟悉的模型。這當然是一個選擇──本文上篇的 REST 範例,就是描述如何做到這一點的極簡方法。

Chambon 的另一種選擇是保留基本的 RPC 模型,但使用的是 gRPC 而非 OpenAPI。這避免了定義 API 和 HTTP 間相互對應的複雜性。RPC 模型和其它替代方案比起來發展時間更長,如果 API 設計者無論如何都要做類似 RPC 的模型,那麼他們應該權衡所有可用的技術,再來做這件事。

gRPC 的優勢

gRPC 以介面定義語言 (interface description language, IDL) 表示 RPC API,這對 RPC IDL的悠久有許多優勢,其中包括 DCE IDL、Corba IDL 等。相較於 OpenAPI 使用 URL、參數和 HTTP methods, gRPC 的 IDL 提供了一種更簡單、直觀的方式。

gRPC 底層使用的是 HTTP/2,但 HTTP/2 並不會向 API 設計人員或 API 客戶暴露關於 HTTP/2 的事。gRPC 已經將 HTTP 上 RPC 所需做的事情做完,所以您無需另外做事情——因這些事已經內建於 gRPC 的軟體程式中,使 API 設計人員和客戶更方便使用。相較之下,OpenAPI 要求 API 設計人員,在 API 上設定 HTTP 表示 RPC 的相關資訊,且使用 API 的客戶也須了解這些資訊。OpenAPI 方法的優勢為它讓 API 客戶端可使用標準的 HTTP 工具和技術,這對於許多 API 設計人員而言是合理的。

無論您的 API 如何使用 HTTP,您會希望能讓各種不同語言的工程師都能使用,在程式中為程式庫(可能稱為函數或方法,取決於使用的語言)。gRPC 最吸引人的特點為,它非常適合做客戶端程式庫,讓工程師可以更直覺地使用,並快速的撰寫。OpenAPI 也能用於客戶端程式庫,但筆者認為 gRPC 更簡單直觀,可能是因為其 IDL 只需要表達 RPC 概念,不必描述這些對應到 HTTP 的概念。

gRPC 指定的 API 在伺服器較容易執行。由於 gRPC 提供了frameworks、libraries 和 code-generation 等功能,因此使用 gRPC 方法的 sever 執行可能比寫標準的 HTTP 傳輸協定還要簡單許多,雖然有很多 framework 可以幫助完成 HTTP 傳輸協定的發送和解析需求。

gRPC 的另一個特點是效能良好。gRPC 使用二進位提升了建立和解析的效能,並利用 HTTP/2 來有效管理連線。當然,你也可以不使用 gRPC 直接使用二進位高成效負載和HTTP/2,但這需要您和您的客戶掌握更多技術細節。

gRPC 還避免的一個問題,就是即使是最好的 HTTP-based 的 API 也無法執行完整的 HTTP 協定,這需要 API 提供者和客戶端了解哪些 HTTP 子集被哪些特定的API支援。REST 和 OpenAPI API 都存在這個問題。gRPC 要求客戶端和伺服器都使用特別的軟體實作完整的 gRPC 協定來避免這個問題。我們希望 gRPC 能像 HTTP 一樣,讓該協定保持穩定 25 年以上,讓客戶在升級伺服器時不會中斷,反之亦然。

如何結合 RPC 和 entity-oriented model?

無論你使用 gRPC 還是 OpenAPI,以實體為導向 (entity-oriented) 的操作 RPC 的技巧都在於將 RPC 方法的定義限制為能夠簡易的對應到到標準實體的操作(建立、檢索、更新和刪除,通常稱為 CRUD,加上列表)為每個資源類型。

 

若要以實體為導向的方式使用 RPC,你需要反向思考 RPC 的運作模式──先從定義資源類型開始,而不是從過程定義,然後根據這些類型實體操作,來制定 RPC 方法,再加上其它你認為必要的額外操作。

以實體導向風格使用 RPC 能教導人們框架的使用模式。在實踐的過程中,我們看到以這種方式設計 API 有時是以實體為導向和以程序為導向的概念的混合體,這反而破壞了某些好處。

gRPC 的缺點?

每種技術都有缺點和限制性,我們之前已討論過 OpenAPI 的一些缺點與侷限。

HTTP API 廣泛流程行的原因在於客戶端可以自由使用,且伺服器只需一般通用的技術就可以執行,例如 API 的呼叫只需在瀏覽器中輸入 URL,或是在 terminal 或 bash script 上輸入 cURL 指令即可。工程師僅需使用基本的 HTTP library 就可以存取或執行 HTTP API。相較之下,gRPC 在客戶端和伺服器上都需使用特殊的軟體,gRPC 產生的程式在客戶伺服器建立的過程中自動被併入——這對於某些人來說可能會很麻煩,尤其是那些習慣使用 Javascript 或 Python 等動態語言的工程師,但至少在開發的過程中,較不會遇到例如此類的情況。Google Cloud Endpoints 產品能讓 gRPC API 可以透過 HTTP 和 JSON 存取,無需經過其它特殊軟體,這讓客戶重新有不同的選擇,相對的不是每個人都想要或能夠使用 Cloud Endpoints,也不是每個人都能找到類似的工具或自行建立一個同等價值的工具。

在沒有中繼資料的情況下寫一個抓取 REST API 的機器人很簡單,有點類似瀏覽器或爬蟲機器人在抓 HTML 網頁,但不能用 RPC-style 的 API 來做這件事,無論是用 gRPC 或 OpenAPI 的方式。因為 RPC 在每個實體類型上都有不同的 API,這需要客製軟體或原生資料才能夠使用。通常寫通用目的 API 的客戶端能發揮的程度有限,即便它有其好處。

HTTP API 通常會透過 Proxy 增加安全性,像是輸入驗證、對應數據格式等來解決其它可能發生的問題。這通常需要新增、刪除或修改 header 來對數據解析,有時甚至需要修內容。Proxy 則使用標準與自訂 header 的組合來實作這件事。這些功能通常是使用Apigee Edge類型的產品來執行,這些產品不需要傳統的程式技巧或是簡易的 gRPC 軟體開發環境。我認為在 gRPC 的環境下執行 Proxy 會困難許多。

gRPC 搭配以實體導向的方式對於新建立的項目很有幫助──您會發現要修改目前的 RPC API 並不容易。

gRPC 並不支援內容協商。HTTP 讓客戶端選擇他們要提供或接收數據的格式(例如 JSON、XML、YAML。)HTTP內容協商機制也能以簡單優雅的方式擴展,以支援最常見的 API 版本──如果使用 gRPC,您將必須找到自己的 API 版本控管方案。

當兩個客戶同時更新同一個資源時,gRPC 沒有定義防止資料外洩的機制,所以如果你使用 gRPC,你很可能需要自己發明一個機制。 HTTP 為解決這個問題定義了標準 Etag 和 If-Match headers—我們設計大多數的 HTTP API 都是使用這些 header。

gRPC 也沒有定義部分更新機制,所以您可能需要自己建立部分更新機制。HTTP 定義了一種用於部分更新的方法 (PATCH),但並未說明 PATCH 的架構或應用方式。還有兩個額外的 IETF 標準填補了 JSON 的缺點:JSON merge patchJSON patch。前者使用起來較簡單,但無法適用所有情況,尤其是更新;後者雖可套用的情況多,但使用起來比較複雜。我最近建立大部分的 HTTP API 都用到了這兩種方法,並讓客戶選擇,Kubernetes API 的運作方式也是如此。

結論

有一些 API 使用了與 HTML web 相同的 REST 超文本模型。他們的目標是繼承 HTML web 的核心特性,例如穩定性,統一性和通用性。如果您已經知道如何用這些方式設計 API,或者有學習的動機,那麼我個人覺得這是一種很好的方法。

用 OpenAPI 描述的 API 和 RPC 的概念十分類似,但使用到 HTTP 的自訂對應。這種方法讓客戶端只能使用常見的 HTTP 技術來存取結果的 API ,雖然它也替這些 API 增加了其它選擇,但這可能會增加設計和建立的難度,同時也會更難學習。

如果您正在考慮將 OpenAPI 套用到您的 API,您也應該考慮使用 gRPC 來建立設計。兩者基本的 API 模型相似,且 gRPC 避免了建立對應到 HTTP 這段門檻。

無論您的 API 是使用 gRPC 還是 OpenAPI,如果您以實體導向為主的方式組織 API,標準規範的命名,並加強其它的命名規則,您就可以享受到 REST API 帶來的好處,但並不是全部。若有以下類似的情況,使用 gRPC 的優勢就會凸顯出來:

  • 您可以使用 Cloud Endpoint,這樣您的客戶就不會因為您使用 gRPC 的技術,而被迫跟著使用 gRPC 技術。
  • API 為內建技術,您可以控伺服器和客戶所使用的技術。

 

如果您使用 gRPC 代替 OpenAPI 或 REST,那麼您必須了解在 proxy 中執行 API 新增或修改會十分有限,尤其是 API 管理類型的工具(像是 Apigee Edge 等)。這根據您使用 gRPC 的方式和目的而定。

與大多數的設計挑戰一樣,API 設計也有許多需考量和權衡的因素。希望以上的討論有助於解釋 HTTP 和 RPC 風格的 API 之間的對應方式。

(原文翻譯改編自 Google Cloud。)

相關文章

API 設計:瞭解 gRPC、OpenAPI 和 REST 以及使用它們的時機(上)

[手把手教學] Apigee 使用 OpenAPI Spec 快速建立反向代理服務 Reverse Proxy

App Economy 最佳領航員!Google API 管理平台 Apigee 四大優勢


連絡「GCP 專門家」