天天看點

4 種主流的 API 架構風格對比

本文讨論了四種主要的 API 架構風格,比較它們的優缺點,并重點介紹每種情況下最适合的 API 架構風格。

兩個單獨的應用程式需要中介程式才能互相通信。是以,開發人員經常需要搭建橋梁——也就是應用程式程式設計接口(API),來允許一個系統通路另一個系統的資訊或功能。

為了快速、大規模地內建不同的應用程式,API 使用協定或規範來定義那些通過網絡傳輸的消息的語義和資訊。這些規範構成了 API 的體系結構。

在過去,人們已經釋出了多種不同的 API 架構風格。每個架構風格都有它獨有的标準化資料交換的模式。這一系列的 API 架構風格的選項,引發了大量的關于哪種架構風格才是最好的争論。

4 種主流的 API 架構風格對比

今天,許多 API 的使用者将 REST 稱作“消亡的 REST”(REST in peace),并且為 GraphQL 感到歡欣鼓舞。而十年前,又完全是另一幅光景:REST 是替代 SOAP 的赢家。這些觀點的問題在于,它們的出發點隻是為某種技術背書,而不是去考慮它實際的屬性和特性如何與目前的需求相比對。

4 種主流的 API 架構風格對比

1RPC:調用另一個系統的函數

遠端過程調用是一種允許在不同上下文中遠端執行函數的規範。RPC 擴充了本地過程調用的概念,并将其放在 HTTP API 的上下文中。

最初的 XML-RPC 是存在問題的,因為很難確定 XML 有效負載的資料類型。是以,後來 RPC API 開始使用一個更具體的 JSON-RPC 規範,該規範被認為是 SOAP 的更簡單的替代方案。gRPC 是 Google 在 2015 年開發的最新 RPC 版本。gRPC 可插拔支援負載均衡、追蹤、運作狀況檢查和身份驗證,它非常适合連接配接不同的微服務。

RPC 的工作機制

用戶端調用一個遠端的過程,将參數和附加資訊序列化為消息,然後将消息發送到服務端。服務端在接受到消息後,将資訊的内容反序列化,執行所請求的操作,然後将結果發送回用戶端。用戶端和服務端各自負責參數的序列化和反序列化。

4 種主流的 API 架構風格對比

RPC 的優勢

簡單直接的互動。 RPC 使用 GET 來擷取資訊,使用 POST 來處理其他所有操作。服務端和用戶端之間互動的機制歸結為調用端點并獲得響應。

易于添加新函數。 如果 API 有了新的需求,我們可以輕松地添加另一個執行這個需求的端點:1)編寫一個新函數,并将其放在一個新端點之後;2)現在,客戶可以通路這個端點,并擷取符合其需求的資訊。

高性能。輕量級的有效負載不會對網絡産生壓力,以此提供高性能,這對于共享伺服器和在工作站網絡上執行并行計算非常重要。RPC 還能夠優化網絡層,使得不同服務之間每天發送海量消息變得非常高效。

RPC 的不足

和底層系統緊密耦合。 API 的抽象級别有助于其可重用性。API 與基礎系統的耦合越緊密,對其他系統的可重用性就越差。RPC 與基礎系統的緊密耦合不允許其在系統函數和外部 API 之間建立抽象層。這很容易引起安全問題,因為關于基礎系統的細節實作很容易會洩漏到 API 中。

RPC 的緊密耦合使得可伸縮性要求和松散耦合的團隊難以實作。是以,用戶端要麼會擔心調用特定端點的帶來的任何可能的副作用,要麼需要嘗試弄清楚要調用的端點,因為用戶端不了解伺服器如何命名其函數。

可發現性低。 在 RPC 中,無法對 API 進行檢驗總結,或者發送請求來開始了解根據需求應該調用哪個函數。

函數爆炸性增長。建立新函數非常容易。是以,相較于重新編輯現有的函數,我們會傾向于建立新的功能,最終産生大量難以了解的、功能重疊的函數。

RPC 的用例

RPC 模式在八十年代開始使用,但這并不意味着它已經過時了。諸如 Google、Facebook(Apache Thrift)和 Twitch(Twirp)這樣的大公司如今正在内部使用高性能的 RPC 版本,來執行極高性能、低開銷的消息傳遞。它們龐大的微服務系統要求内部通信在使用短消息的情況下也保持清晰。

指令 API。RPC 是用于将指令發送到遠端系統的正确選擇。例如,Slack API 是非常以指令為中心的:加入頻道、離開頻道、發送消息。是以,Slack API 的設計者以類似于 RPC 的樣式對其進行了模組化,使其小巧、緊湊并且易于使用。

用于内部微服務的客戶特定的 API。由于是在單個提供者和單個使用者之間建立直接的內建,我們不想像 REST API 那樣,花太多時間通過網絡傳輸大量的中繼資料。憑借高消息速率和消息性能,gRPC 和 Twirp 成為了用于微服務的可靠用例。通過在底層使用 HTTP 2,gRPC 能優化網絡層,使其非常高效地在不同服務之間每天傳送大量資訊。然而,如果你并不是要着眼于提高網絡性能,而是要在釋出高度獨立的微服務團隊之間建立一個穩定的 API 聯系。REST 就能做到。

2SOAP:使資料作為服務可用

SOAP 是一個 XML 格式的、高度标準化的網絡通訊協定。在 XML-RPC 釋出的一年後,SOAP 由微軟釋出、并繼承了許多 XML-RPC 的特性。在 REST 緊随其後釋出,一開始它們是被同時使用,但很快 REST 赢得了這次比賽,成為了更流行的協定。

SOAP 的工作機制

XML 資料格式拖累了很多資料規範。伴随着大量的消息結構,XML 資料格式使得 SOAP 成為了最冗長的 API 架構風格。

SOAP 的消息由這些部件組成:

一個信封标簽:用于開始和結束每條消息

包含請求或響應的正文

一個标頭:用于表示消息是否由某些規範或額外要求的來确認

故障通知:包含了可能在請求處理過程隻能夠發生的任何錯誤

4 種主流的 API 架構風格對比

SOAP API 的邏輯由 Web 服務描述語言(WSDL)編寫。該 API 描述語言定義了端點并描述了可以執行的所有過程。這使得不同的程式設計語言和 IDE 能夠快速建立通信。

SOAP 支援有狀态和無狀态消息傳遞。在有狀态的情況下,伺服器存儲接收到的資訊可能非常繁瑣複雜。但這對于涉及多方和複雜交易的操作是合理的。

SOAP 的優勢

獨立于語言和平台。内置建立 Web 服務的功能使得 SOAP 能夠處理消息通信的同時發送獨立于語言和平台響應。

綁定到各種協定。SOAP 在适用于多種場景的傳輸協定方面是十分靈活的。

内置錯誤處理。SOAP API 規範允許傳回帶有錯誤碼及其說明的的 XML 重試消息。

一系列的安全拓展。SOAP 與 ES-Security 內建,是以 SOAP 可滿足企業級事務要求。它在事務内部提供了隐私和完整性,同時允許在消息級别進行加密。

4 種主流的 API 架構風格對比

SOAP 的不足

如今,由于如下幾種原因,許多開發人員在聽到必須內建 SOAP API 的想法後都會感到不安。

僅使用 XML。SOAP 消息包含大量的中繼資料,并且在請求和響應時僅支援繁冗的 XML 格式。

重量級。由于 XML 檔案的大小,SOAP 服務需要很大的帶寬。

非常專業化的知識。建構 SOAP API 伺服器需要對所有涉及到的協定以及它們及其嚴格的限制都有很深的了解。

乏味的消息更新。由于需要額外的工作來添加或者删除某個消息屬性,這種死闆的 SOAP 模式減慢了其被采用的速度。

SOAP 的用例

目前,SOAP 體系結構最常用于企業内部或與其信任的合作夥伴的内部內建。

高度安全的資料傳輸。SOAP 嚴格的消息結構,安全性和授權功能使其成為在 API 和用戶端之間執行正式軟體協定的最合适的選擇,同時又符合 API 提供者與 API 使用者之間的法律合同。這就是為什麼金融組織和其他企業使用者選擇适用 SOAP 的原因。

3REST:使資料作為資源可用

REST 如今是一種無需解釋的 API 架構風格,它由一系列的架構限制所定義,旨在被廣泛 API 使用者采用。

目前最常見的 API 架構風格最初時由 Roy Fielding 在其博士論文中提出的。REST 使得服務端的資料可用,并以簡單的格式(通常是 JSON 和 XML)來表示它。

REST 的工作機制

REST 的定義并不像 SOAP 那樣嚴格。RESTful 體系結構應該遵守如下六個體系結構限制:

統一接口:無論裝置或應用程式類型如何,都可以采用統一的方式與給定的服務端進行互動。

無狀态:請求本身包含處理該請求所需要的狀态,并且服務端不存儲與會話相關的任何内容。

緩存

用戶端 - 伺服器體系結構:允許雙方獨立發展

應用程式的層級系統

服務端向用戶端提供可執行代碼的能力

實際上,某些服務僅在某種程度上是 RESTful 的。而它們的核心采用了 RPC 樣式,将較大的服務分解為資源,并有效地使用 HTTP 基礎結構。但 REST 的關鍵部分是超媒體(又稱 HATEOAS),是超文本作為應用程式狀态引擎(Hypertext As The Enginer Of Application State)的縮寫。

基本來說,這意味着 REST API 在每個響應中都提供中繼資料,該中繼資料連結了有關如何使用該 API 的所有相關資訊。這樣便可以使用戶端和服務端解耦。是以,API 提供者和 API 使用者都可以獨立發展,而這并不會阻礙他們的交流。

4 種主流的 API 架構風格對比

“HATEOAS 才是 REST 的關鍵功能,因為它真正使得 REST 成為 REST。但由于大多數人不使用 HATEOAS,是以他們實際上是在使用 HTTP RPC。”這是 Reddit 上表達的一些激進觀點。确實,HATEOAS 是 REST 的最成熟版本。

但是,這非常難以實作,因為這要求 API 用戶端要比它們如今建構和使用的方式變得更先進和智能得多。是以,即便是如今非常好的 REST API 也不一定總是能做到這一點。這就是為什麼 HATEOAS 主要是作為 RESTful API 設計的長期開發的願景而存在。

當服務端實作 REST 的某些功能和 RPC 的某些功能時,在 REST 和 RPC 之間确實可能存在這樣一個灰色區域。但 REST 是基于資源或名詞的,而不是基于動作或動詞。

4 種主流的 API 架構風格對比

在 REST 中,使用例如 GET、POST、PUT、DELETE、OPTIONS 可能還有 PATCH 等 HTTP 方法來完成操作。

4 種主流的 API 架構風格對比

REST 的優勢

用戶端和服務端的解耦:由于 REST 盡可能地解耦了用戶端和服務端,REST 相較于 RPC 可以提供更好的抽象性。具有抽象級别的系統能夠封裝其實作細節,以更好的标示和維持它的屬性。這使得 REST API 足夠靈活,可以随着時間的推移而發展,同時保持穩定的系統。

可發現性:用戶端和服務端之間的通信描述了所有内容,是以不需要外部文檔即可了解如何與 REST API 進行互動。

緩存友好:REST 重用了許多 HTTP 工具,也是唯一一種可以在 HTTP 層面上緩存資料的 API 架構風格。與其相對的是,在任何其他 API 上實作緩存都需要配置其他緩存子產品。

多種格式支援:REST 擁有支援多種格式用于存儲和交換資料的能力,這是它如今成為搭建公共 API 的主要選擇的原因之一。

REST 的不足

沒有标準的 REST 結構:在建構 REST API 方面,沒有具體的正确方法。如何對資源進行模組化以及哪些資源需要模組化取決于不同的情況。這使得 REST 在理論上很簡單,但在實踐中卻很困難。

龐大的負載: REST 會傳回大量豐富的中繼資料,以便用戶端可以僅從響應中了解有關應用程式狀态的所有必要資訊。對于具有大量帶寬容量的大型網絡系統來說,這種“啰嗦”的通信并不算很大的負載。但帶寬容量并非總是足夠的。這也是 Facebook 在 2012 年提出 GraphQL 架構風格的關鍵驅動因素。

響應過度和響應不足問題。REST 的響應包含的資料會過多或不足,通常會導緻用戶端需要發送另一個請求。

REST 的用例

管理 API。在系統中,專注于管理對象并面向許多使用者的 API 是最常見的 API 類型。REST 幫助此類 API 具有強大的可發現性,良好的文檔編制,是以 REST 非常适合此對象模型。

簡單的資源驅動型應用程式。在用于連接配接不需要查詢靈活性的資源驅動型應用時,REST 是一種非常有效的方法。

4GraphQL:僅請求所需要的資料

REST API 需要被多次調用才能傳回所需要的資源。是以,GraphQL 被發明了,并改變了這一切遊戲的規則。

GraphQL 是一種文法,它描述了如何進行精确的資料請求。有些應用程式的資料模型具有許多互相引用的複雜實體,在這種情況下,實作 GraphQL 是值得的。

4 種主流的 API 架構風格對比

如今,GraphQL 的生态系統正在蓬勃發展,出現了例如 Apollo、GraphiQL 和 GraphQL Explorer 等強大的庫和工具。

GraphQL 的工作機制

GraphQL 從構模組化式(Schema)開始。模式是對于使用者可以在 GraphQL API 中進行的所有查詢及其傳回的所有類型的描述。模式建構非常困難,因為它需要使用模式定義語言(SDL)進行強類型化。

因為在用戶端進行查詢之前已經定義好了模式,是以用戶端可以驗證其查詢語句,以確定服務端能夠對查詢語句進行響應。在查詢語句到達後端應用程式時,GraphQL 操作将根據整個模式進行解釋,并向前端應用程式傳回解析到的資料。API 向服務端發送一個龐大的查詢,該 API 傳回一個僅包含我們所需資料的 JSON 響應。

4 種主流的 API 架構風格對比

除了包含 RESTful 的 CRUD 操作,GraphQL 還有訂閱(subscriptions)機制,允許接收來自服務端的實時通知。

GraphQL 的優勢

具有類型的模式:GraphQL 提前公開了它能做什麼,進而提高了其可發現性。通過将用戶端指向 GraphQL API,我們可以發現什麼查詢語句是可用的。

沒有版本控制:版本控制的最佳實踐是不要對 API 進行版本控制。

盡管 REST 提供了不同的 API 版本,GraphQL 使用的是不斷更新的單一版本,這使使用者可以持續通路新功能,并有助于提供更整潔、更可維護的伺服器代碼。

詳細的錯誤消息:GraphQL 以類似于 SOAP 的方式提供所發生錯誤的詳細資訊。它的錯誤消息包括所有解析器,并指向确切的發生故障時的查詢部分。

靈活的權限:GraphQL 允許選擇性地公開某些功能,同時保留私人資訊。而相對應的是,REST 體系架構不能僅顯示部分資料,要麼是全部資料,要麼是沒有資料。

GraphQL 的不足

性能問題。GraphQL 權衡了複雜性,來實作其強大功能。一個請求中的嵌套字段太多會導緻系統過載。是以,對于複雜的查詢,REST 仍然是更好的選擇。

緩存複雜度。由于 GraphQL 不再使用 HTTP 緩存語義,是以使用者需要額外自定義緩存。

大量的預開發教育。由于沒有足夠的時間來了解 GraphQL 的某個操作和 SDL,是以許多項目決定采用衆所周知的 REST 方法。

GraphQL 的用例

移動 API。在這種情況下,網絡性能和單個消息有效負載優化很重要。是以,GraphQL 為移動裝置提供了更有效的資料加載方式。

複雜的系統和微服務。GraphQL 能夠隐藏其 API 背後的多個系統內建的複雜性。GraphQL 從多個地方聚合資料,并将它們合并為一個全局的模式。對于随時間推移而逐漸擴充的遺留基礎架構或第三方 API 來說,這尤其重要。

5哪種 API 模式最适用你的用例?

每個 API 項目都有不同的限制和需求。通常,API 架構的選擇取決于:

所使用的程式設計語言,

你的開發環境,以及

你的資源預算,包括人力資源和财務資源。

在了解了每種設計風格的利與弊之後,API 設計人員可以選擇最适合項目的那一種。

具有強耦合性的 RPC 很适用于内部微服務,但它對外部 API 或者 API 服務而言不是一個好的選擇。

SOAP 的使用有些麻煩,但它強大的安全拓展使它在計費操作、預訂系統和支付方面是無可替代的。

REST 是針對 API 的最進階别的抽象和最佳模型。但它往往會有些“啰嗦”而增加系統的負擔 —— 如果你使用的是移動裝置,這是個問題。

GraphQL 在資料擷取方面向前邁出了一大步,但并不是每個人都有足夠的時間後精力來掌握它。

歸根結底,去針對一些小型的用例來嘗試某種特定 API 架構,并去了解它是否适合你的用例以及是否解決了你的問題,這樣做是比較合适的。如果它适用于你的用例,就可以嘗試擴充并檢視它是否适用于更多的用例。