API(Application Programming Interface,應用程式介面)大家都在用,一些架構術語像是 RPC、REST、GraphQL 等等也常常聽過,但是我覺得網路上絕大部分的文章都沒有講到它們的重點在哪裡、都是一直在重複艱澀且不容易體會的定義。在這篇文章中,我想用我的視角來簡單解釋一下這些架構。

內容目錄

RPC

大部分在談 API 架構比較的文章都會放上這一張時間軸的圖,所以這邊我也稍微借來用一下:

file

其中 CORBA(Common Object Request Broker Architecture)和 RDA(Remote Data Access)的概念跟我們現在心中想像的「API」概念差距比較大一點,所以不太需要多談。SOAP(Simple Object Access Protocol)並沒有太流行,所以各位也不用管。OData(Open Data Protocol)只是 REST 的一種實作,這邊也不多提細節。這些東西稍微知道一下有這麼一回事就好。

在我們今天會講到的幾種主要的 API 架構當中,最早出現的當屬 RPC(Remote Procedure Call,遠端程序呼叫),它甚至可以追溯到比上面這張圖畫出來的年代還更早。然而,從我這個數學背景來角度來看,網路上的資料對於 RPC 這則術語是很缺乏一個統一的定義的,有的時候人們很狹義地使用這個術語、但有時又很廣義,所以為了避免造成困惑,底下兩方面我都會講。

就字面上來說,RPC 的意思就是「想像我們直接呼叫遠端應用程式上面定義的函數或方法」。真正狹義而言,RPC 的 API 應該要有這樣的性質:

  1. 基本上只有一個 API 端點(也就是 API 的網址)。
  2. 在送過去的請求(格式不一定,從而衍生出了 XML-RPC、JSON-RPC 和 gRPC 這些變種)當中,會明確指出我們要使用的遠端方法之名稱,藉此區分我們想要使用的功能。
  3. 然後在請求的後半段會是我們要傳入給遠端方法的參數或資料。

耶,可是,也許是我見識少啦,在今天、這麼狹義的 RPC API 我還真的沒看過多少。取而代之地,比較多的 API 會是用不同的端點來區分不同的功能、然後請求的內容整個就是要傳入的參數或資料。像這樣的 API 我們可以說它是一種比較廣義的 RPC API;雖然其形式並非嚴格意義上的 JSON-RPC(例如啦),但是精神其實是差不多的,都是環繞著一個核心想法:

廣義的 RPC API,重點在於個別的「功能」是打包好的,也就是功能導向、是高階的 API。

而當網路上的文章在講「RPC vs REST」之間的對比時,通常那個作者是在指這種廣義的 RPC,而不僅限於狹義上的。

這個核心想法是一個兩面刃。一方面,功能導向意味著前端可以用最精簡的方式下達請求、並且收到完全符合需求的回應,不多也不少;但是另外一方面,功能導向也意味著前端跟後端是強耦合的。什麼意思呢?就是假如今天前端有新的功能需求是既有的 API 無法滿足的,那麼一定得找負責後端的團隊來修改、或者開出新的 API 來滿足新的需求。如此一來,前後端就沒辦法各自獨立開發、而需要密切配合;後端需要很清楚前端需要什麼功能,前端也需要很清楚後端開出來的 API 規格是什麼。

REST

而 REST(REpresentational State Transfer,表現層狀態轉換)的核心概念可以說就是為了解決這種耦合而誕生的。當然,如果去看網路上的定義,它還有一大堆更加根本的定義,像是利用 HTTP 方法(GET、POST、PUT、DELETE)來描述操作啦、通常是無狀態的(stateless)啦……但那些都不是重點!它相較於 RPC 的真正重點在於:

REST 著眼在「資源」的操作,也就是資源導向、是低階的 API。

呃,可是什麼是資源?這就有點抽象了,但具體一點來說的話,不妨理解成資料庫裡面的每一種資料表都是一種資源就好。於是 RESTful API(加上那個「ful」只是英文文法的問題而已,還是同一回事)就會用個別的端點來對應各種資源,然後前端就可以用 GET 等方法去操作對應資源的 CRUD(增查改刪)動作。

耶,等一下,那不就等於是直接把資料庫的操作曝光給前端了嗎?相信第一次學到 REST 的人應該很多都會有這個疑惑。嗯,是啦,很大的成份上來說就是這樣沒錯,但是也沒有到 100% 曝光資料庫的地步,因為後端還是會在中間做一道把關的動作,例如會去檢查 API 傳過來的 token、看看打 API 的人是否有對應資源的存取權,以及確保寫入的資料格式正確等等的。

資源導向的作法也是有其利弊:首先,它確實在很大的程度上解耦了前後端的開發,因為只要資源的種類不變,前端可以自己根據其需求去拼湊撈出來的資料等等,不會受限於後端提供的高階功能、而是可以自己用低階操作去組合出想要的高階功能。其次,雖然 REST 整體來說並沒有統一的實作方式,但是至少在同一個專案當中、在操作各種資源的時候是統一的,前端開發人員很容易舉一反三知道要怎麼使用、而不用多看後端團隊的文件。但是反過來,它的缺點則包括:

  1. 比較沒效率:在用低階操作去組合高階功能的時候,可能會需要打很多次 API 才組得出想要的效果,而且其中可能會傳輸了很多前端其實並不需要的資料。
  2. 不適合牽涉到商業邏輯的交易:如果某一項高階操作必須正確地組合若干低階操作才能反應商業邏輯,用 REST 就不適合了,因為它比較難防範各種操作上的錯誤(包括使用者惡意自己打 API、前端的商業邏輯實作錯誤、或是低階操作到一半的時候網路斷線等等;這些要防不是不可能,但會比較麻煩)。REST 比較適合的情境是單純的內容,例如論壇或社交平台這種張貼的內容之間不需要存在什麼邏輯的東西。

所以對於講究商業邏輯的功能來說,廣義的 RPC API 還是比較適合的。當網路上在對比「RPC vs REST」的時候,其實他們真的在講的是「功能導向 vs 資源導向」之間的差異,而不是狹義的 RPC 跟 REST。尤其,資源導向的 API 除了 REST 之外還有更新的 GraphQL。

GraphQL

GraphQL 簡單來說就是要解決 REST 最為人詬病的傳輸問題。它透過一套獨特的語法來定義「我到底想要什麼樣的資料」,然後讓後台根據這個語法來組合出前端想要的資料、或是類似地進行資料的修改。除此之外,它還多了一個「訂閱」的功能,可以讓前端持續訂閱資源的變動、並且在變動的時候接到通知(例如透過 WebSocket)。

它跟 REST 一樣是資源導向的(只是它可以比較靈活地存取多種資源),所以也同樣有規格統一的優點(而且比 REST 更加統一,因為語法都有規範,回傳格式也固定都是 JSON)、但也一樣有商業邏輯方面的弱點。而 GraphQL 通常是單一端點的,這部份它則比較像狹義的 RPC。相較於 REST,它適合的情境是當整個系統有比較複雜的資料結構、而且前端可能會有很多樣化的查找需求的時候。但是也要小心,如果 GraphQL 打包了太複雜的查找,它的效率可能反而會比 REST 要差。

結語

總而言之,在 RPC、REST 和 GraphQL 這三種最常被提到的 API 架構中,它們是各有各的長短處、也各有其適合的場域。這邊解釋了它們之間最重要的對比之處,希望對各位的理解會有所幫助。

我的文章對您有幫助嗎?請我喝杯咖啡吧:

分享此頁至:
最後修改日期: 2023/12/08

留言

撰寫回覆或留言

發佈留言必須填寫的電子郵件地址不會公開。您的留言可能會在審核之後才出現在頁面上。