與API交互:REST和GraphQL

作者:hj4511 · 2025-01-30 · 閱讀時間:8分鐘

開發者使用應用程序編程接口,或稱為API,來為新的移動或網絡應用組裝數據和功能,但在與API交互時,開發者經常面臨兩個流行的選擇:REST或GraphQL。

在本文中,我們將探討這些方法的比較,并提供可以應用于構建更一致的GraphQL API消費者體驗的REST API最佳實踐。一個選項并不比另一個更好,如果不同項目中,兩者都可以在同一團隊中使用——但無論項目涉及哪種類型的API,更一致的體驗將幫助開發者做得更多、更快。

REST和GraphQL比較

REST是一種軟件架構風格,API遵循這種風格,以便開發者可以以標準方式與服務交互。GraphQL是一種API查詢語言和運行時,用于滿足這些查詢。REST和GraphQL在識別資源為URL方面相似,應用程序可以通過這些URL獲取數據或功能——但存在許多差異:

  • GraphQL在單個端點交換數據,而REST通常涉及多個端點。GraphQL解析器檢索字段的數據,如果一個解析器失敗,其余的查詢仍然可以檢索并返回有用的數據。這種交互范式反映了執行多個REST查詢時的預期,因此,一個GraphQL查詢經常替換多個REST查詢。* GraphQL 可以防止數據的過度獲取和不足獲取——也就是說,一個端點響應調用時提供的信息過多或過少,與應用程序所需的信息相比。REST API 提供了不同級別的解析度。一些會檢索更多的數據,一些則檢索較少的數據。這意味著應用程序可能會接收到過多的數據,例如,當只需要員工姓名和ID號時,卻接收到了整個員工檔案。同樣,它可能會接收到過少的數據,迫使應用程序不得不進行多次API調用,而不是僅僅一次。
  • REST 使用 HTTP 動詞,并且通常使用 JSON 來交換負載數據,但在 GraphQL 中,最常使用的是 HTTP POST 動詞,不同的查詢類型在協議內部指定。GraphQL 還使用一種稱為 Schema Definition Language(SDL)的自定義查詢格式,盡管使用了這種自定義查詢語言進行請求,但返回的卻是 JSON,這使得客戶端更容易利用響應。GraphQL 客戶端庫具有與 ReactJS UI 框架的原生集成,并且也適用于其他語言和范式,使得它們今天能夠被許多開發者訪問。
  • 開發者發現的視角不同。要了解 REST API 的工作原理,開發者通常使用門戶作為商店來發現和與 API 交互。在 GraphQL 中,門戶是一個內置的游樂場,也支持開發。它幾乎就像是一個集成開發環境,允許開發者在飛行中探索新的查詢,并通過諸如標簽補全等功能得到輔助。文檔也有所不同。REST通常使用OpenAPI規范和門戶。OpenAPI有一些擴展存在。例如,Apigee SmartDocs根據這些OpenAPI規范構建交互式文檔。GraphQL開發者通常使用基于模式的交互式文檔,如Graphiql來開發和交互GraphQL端點。

這些特性使得GraphQL在越來越多的用例中變得流行,但也可能指向可能的采用挑戰。對于涉及互操作性和內部基礎設施分解的項目,GraphQL是創建幾個API以連接許多不同的遺留系統的有用工具。但它也可以在自助開發者計劃和相關增長策略中得到利用,這些策略通常涉及企業通過API管理平臺提供REST API,以鼓勵內部和外部創新。

這些計劃與傳統的以基礎設施為中心的API項目不同,因為這些API可能被許多構建它的團隊之外的人使用,用于該團隊從未想象過的許多用途。這篇文章再次強調了一致的、可靠的、直觀的開發者體驗的重要性——這也提出了適應GraphQL的一個障礙:相對而言,很容易看一眼一組REST API并直觀地理解它們的作用以及它們的工作方式,但我們還沒有達到與GraphQL相同的程度。

在GraphQL中使用基于REST的實踐

你應該愿意使用最適合這項工作的工具,這些工具可能包括GraphQL和REST。為了更高效地使用GraphQL,我們建議采納一些基于REST的最佳實踐,這些實踐是我們在多年構建開發者程序中發展起來的。

將API視為數字產品,讓企業能夠將他們的資產,為了增加這些資產的杠桿效應,交到開發者手中,無論是內部員工、合作伙伴還是外部客戶。因為API是數字產品,開發者需要一個一致的體驗,以便了解如何使用它們,并將引人注目的體驗推向市場。開發者的摩擦是API采用和數字公司增長戰略中的巨大挑戰,因此就像REST一樣,一致性是GraphQL的關鍵。

將圖視為由復數名詞定義的數據驅動層次結構

REST架構風格的一個關鍵原則是創建一個簡化的、一致的界面,以合理化基礎設施的復雜性。人們絕不會期望一個結構良好的REST查詢是GET/listEmployeesByDepartment——這看起來更像是一個Java函數。相反,一個結構良好的REST資源會使用復數名詞:GET /Employees,然后POST /Employees等。通過可靠地符合可預測的預期,REST API直接影響開發者能夠消費資源和構建新體驗的速度——時間就是金錢。

GraphQL的模式使用圖層次結構來定義實體之間的關系,例如目錄中書籍的標題和作者。這是一個根本上的數據驅動層次結構,但我們有時會看到它被當作一個看起來像Java函數的功能性層次結構——這可以通過破壞可預測的、直觀的、一致的體驗來引入摩擦。

一個結構良好的GraphQL應該看起來像一個結構良好的REST。如果你可以從/Books獲取,應該假設你可以向/Books發布。與此相比,一個更像Java的構造,由基于動詞的函數而不是基于數據的名詞定義,例如GET listBooksByGenre。你如何發布?到/BooksByGenre?到/Books?到/listBooks?誰知道。我們的建議是數據驅動,并把圖當作一個數據驅動的層次結構。

**當REST更有意義時,不要強迫使用GraphQL****在REST中,用戶經常從不同的URL請求和提交數據,特別是在使用命令查詢責任分離(Command Query Responsibility Segregation,簡稱CQRS)這種模式時,這是一種由Martin Fowler首次識別的設計模式,它將讀取數據的模型與更新數據的模型分離。開發者經常在微服務架構中使用CQRS來從多個服務中檢索數據。

在GraphQL中,變更(GraphQL開發者提交數據的方式)可能會迅速變得非常復雜,特別是當存在許多不同的數據類型或者提交的數據非常少時。我們推薦使用類似于CQRS的風格,將檢索數據與提交數據分離。這可能對大型企業特別有用,尤其是那些已經擁有基于REST的API層的企業。GraphQL可以在API管理層之上或代替API管理層檢索數據,但數據仍然可以通過現有的REST API提交。這表明開發者在REST有意義的情況下不應該強行使用GraphQL。

**優化重用性 **大型企業GraphQL部署經常面臨挑戰,當需要為開發者提供多種類型的后端時。不同的業務單元開發模式圖的不同部分,然后作為一個全面的圖呈現給開發者,通常是通過模式拼接的模式聯合。挑戰出現在查詢的行為從圖的不同部分返回不同的數據或行為時,因為數據的表示沒有一致性。在SDL中看起來相同的變量名不應該僅僅因為它們解析到不同的數據源就返回不同的值或格式。

此外,Relay游標連接和輸入提示應該無論請求圖的哪一部分都表現出統一的行為。

這尤其是一個與變更相關的問題,因為如果開發者以一種方式向模式的一個部分提交數據,并且以一種方式記錄,他們可能沒有意識到當他們在模式的另一個部分提交時,它是以另一種方式記錄的。由于變更在優化可重用性和API產品化時是一個特別的挑戰,我們建議在GraphQL中開發和設計它們時要特別小心。

最后,讓我們看看字段名。如果具有相同名稱的字段名因為它們在模式的不同部分而提供不同的數據和行為,這對開發者來說是不友好的。例如,當模式的一個部分有一個期望第一、中間、最后一個名字的名稱字段,而模式的另一個部分有一個期望最后一個名字.第一個名字的名稱字段時,這種不一致可能導致開發者放棄。

在GraphQL中,優化查詢效率很容易,但要有意識地優化可重用性。避免API讓開發者感到困惑的情況將帶來回報。

原文地址:https://cloud.google.com/blog/products/api-management/interacting-with-apis-rest-and-graphql