常見形式 Web API 的簡單分類總結

一、請求--響應API。

請求--響應類的API的典型做法是,通過基於HTTP的Web服務器暴露一個/套接口。API定義一些端點,客戶端發送數據的請求到這些端點,Web服務器處理這些請求,然後返回響應。響應的格式通常是JSON或XML。

在這種類型的Web API裡,比較流行的是這三種:RESTRPCGraphQL

1.1 REST

REST全稱是Representational State Transfer 表述性狀態傳遞。REST可能是現在最流行的一種Web API。

REST的核心就是資源,一個資源就是可以被標識的實體,它有名稱和地址。

REST API就是把數據以資源的形式暴露出來,並使用標準的HTTP方法來代表創建、讀取、更新和刪除資源等事務。

REST API有一些規則和約束,這裡我就簡單的寫一下(之前的文章有詳細描述):

  • 資源都是URL的一部分,例如/persons
  • 針對每個資源通常都會有兩個URL被實現:“/persons”表示資源的集合,“/person/321”表示特定的一個資源
  • 在資源裡,使用名詞而不是動詞,例如 /getUserInfo/123 這就不對了,應該是 /users/123
  • HTTP方法表明了要執行的動作,不同的HTTP方法作用於同一個URL上可實現不同的功能:
  • 創建 -- POST
  • 讀取 -- GET
  • 整體更新 -- PUT
  • 局部更新 -- PATCH
  • 刪除 -- DELETE
  • 服務器會返回標準的HTTP狀態碼,來表示請求成功或者失敗,以及原因。通常2xx表示成功,3xx表示資源被移動了,4xx表示客戶端引起的錯誤,5xx表示服務器端引起的錯誤。

如果兩個資源有主從關係,那麼子資源最好不採用頂級資源的URL,而是採用主資源的子資源URL地址。例如Province和City就是主從關係,那麼City資源的URL應該是:/provinces/{provinceId}/cities,/provinces/{provinceId}/cities/{cityId}

非CRUD操作

API難免會有一個非CRUD的操作,例如“存檔”這個操作。這時候我們可以採取以下幾種辦法:

  • 把這個動作作為資源的一個字段。例如把“存檔”作為輸入參數傳遞到API
  • 作為子資源。例如 /repos/{repoId}/issues/{issueId}/archive
  • 直接使用動詞。實在不行了,就用動詞吧,例如 /search/params?......

1.2 RPC

Remote Procedure Call。RPC是一種比較簡單的API,客戶端直接會執行另一個服務器上的代碼。

REST是關於資源的,而RPC就是關於動作的。

在RPC裡,客戶端通常是把方法名和參數傳遞給服務器,然後服務器返回JSON或XML。

RPC的規則比較少:

  • 端點要包含被執行操作的名字
  • 使用合理的HTTP動詞,GET用於讀取,POST用於其它類型。

RPC適用於那種無法用CRUD封裝的動作,或者其影響和資源無關的動作。

RPC不僅限於HTTP,還有其它協議可以支持,例如Apache Thrift和gRPC。

1.3 GraphQL

GraphQL 是 API的查詢語言。最近越來越火。它由Facebook於2012年開始開發,2015年被開源了。

GraphQL允許客戶端定義需要得到的數據結構,服務器精確的返回所需的數據結構,例如:

常見形式 Web API 的簡單分類總結

與REST和RPC不同,GraphQL API只需要一個端點;它也不需要使用不同的HTTP動詞,它只使用POST,你需要在JSON body裡面指定是要執行查詢還是修改。

相對REST和RPC,GraphQL有下面幾個優勢:

  • 節省了多重的請求往返,GraphQL可以一次把所需的關聯數據全部查詢出來。不會存在例如N+1這樣的問題
  • 避免了API版本問題。你可以隨時添加字段和類型,不會影響現有的查詢。可以標記棄用。通過Log可以追蹤出哪些字段被誰使用,如果字段沒人再去使用,就可以移除它了。
  • Payload比較小。REST和RPC的響應都包含客戶端發送一些不需要的數據。而使用GraphQL的話,客戶端得到的響應就是它所請求的那些東西,不多不少。
  • 強類型。GraphQL是強類型的,開發時有類型檢查能保證查詢的正確性和合理性。
  • 內省(Introspection)。像REST,就需要安裝Swagger等工具來幫助瀏覽API。而GraphQL本身就具備可發現性。它還帶有一個瀏覽器內的IDE用來瀏覽GraphQL API。下圖就是Github的GraphQL API:
常見形式 Web API 的簡單分類總結

GraphQL的缺點就是它為服務器添加了許多複雜性,服務器需要額外的工作來處理這些複雜的查詢。根據查詢內容的不同,性能也是一個變數.

綜上所述,那麼什麼時候應該用哪種Web API呢?

  • 針對CRUD類的API,使用REST
  • 針對暴露很多動作的API,使用RPC
  • 當你需要查詢的靈活性以及維護的連續性時,使用GraphQL

二、事件驅動式 Web API

針對用請求-響應式API,如果服務的數據經常變化,那麼響應就可能無法保持新鮮了。開發者如果想與變化的數據保持同步,就只能對API進行polling操作了。

但是如果poll的頻率較低,客戶端仍有可能無法獲得從上次poll到現在所有的數據事件。如果poll的頻率較高,還特別浪費資源。

所以我們需要實時的分享事件的數據,通常使用下面三種機制:

WebHookWebSocketHTTP Streaming

2.1 WebHooks

WebHook就是一個接收HTTP POST(或GET,PUT,DELETE)的URL。一個實現了WebHook的API提供商就是在當事件發生的時候會向這個配置好的URL發送一條信息。與請求-響應式不同,使用WebHook,你可以實時接受到變化。

下面是Polling和Webhook的比較:

常見形式 Web API 的簡單分類總結

WebHook非常適合於從一個服務器向另外一個服務器分享實時數據。

但是實現WebHook,也引入了新的複雜性:

  • 失敗和重試。為了保證WebHook被成功的傳輸,你需要構建一個可以再發生錯誤時進行重試操作的系統。
  • 安全性。對於安全的調用REST API,現在的方案都比較成熟;而對於WebHook來說,這方面依然在探索中前進。
  • 防火牆。防火牆後運行的應用可以通過HTTP訪問API,但是它們可能無法接收入站的流量。所以這是一個很大的問題。
  • 噪聲。通常每個WebHook調用代表了一個事件,但當短時間內發生了成千上萬個事件的時候,再通過WebHook來傳輸,就可能會有噪音。

2.2 WebSocket

WebSocket這個協議,它通過一個TCP協議建立一個雙向全雙工的流式通信。WebSocket通常用在客戶端和服務器之間的通信,也可以用在服務器之間的通信。

ASP.NET Core SignalR就是優先使用該協議

WebSocket支持全雙工(服務器和客戶端可以同時雙向通信),而且開銷不高。經常使用的端口式80或443,這樣就很容易穿過防火牆了。

WebSocket特別適合於快速的,現場的路i數據和長連接。

如果連接掛掉了,客戶端會嘗試重新初始化連接。但是WebSocket有一些擴展性的問題,因為如果在線的客戶端太多,那麼服務器端就需要維持這些客戶端打開的連接。

常見形式 Web API 的簡單分類總結

2.3 HTTP Streaming

使用請求-響應式API,客戶端發送一個請求,服務器端返回一個響應,這個響應的長度是有限的。

而使用HTTP Streaming,服務器端可以在一個由客戶端打開的長生存的連接裡持續的推送新數據。

常見形式 Web API 的簡單分類總結

為了讓數據通過一個可長時間存在的連接上進行傳輸,有兩個方案:

  • 首先可以讓服務器把Transfer-Encoding這個Header設為chunked。這表示客戶端是按塊接收數據的,塊與塊之間用換行符分割:“\r\n”。
  • 另一個選項是通過Server-Sent Events (SSE)來進行流數據。這個比較適合於瀏覽器內的客戶端,因為這樣它們就可以使用標準的EventSource API了。(SignalR在無法使用WebSocket的時候就會使用SSE)

HTTP Streaming用起來好像很容易,但是有個問題,是關於緩存的。客戶端和代理經常會有緩存的限制。因為只有達到某個閾值之後,它們才會把數據渲染給應用。

綜上,針對事件驅動式Web API:

  • 如果想要進行服務器間的實時事件通信,可以選擇WebHooks
  • 如果需要瀏覽器和服務器間的雙向實時通信,可以選擇WebSocket
  • 如果需要使用簡單的HTTP進行單向通信,可以使用HTTP Streaming


分享到:


相關文章: