淺析 Open API 設計規範

背景

最近由於業務需求,我參與研發的雲產品 CSB 需要對外開放 Open API,原本不是什麼難事,因爲阿里雲內部的 Open API 開放機制已經非常成熟了,根本不需要我去設計,但這次的需求主要是針對一些獨立部署的場景,需要自行設計一套規範,那就意味着,需要對 Open API 進行一些規範約束了,遂有此文。

Open API 和前端頁面一樣,一直都是產品的門面, Open API 不規範,會拉低產品的專業性。在雲場景下,很多用戶會選擇自建門戶,對接雲產品的  Open API,這對我們提出的訴求便是構建一套成熟的 Open API 機制。

站在業務角度,有一些指導原則,指導我們完善 Open API 機制:

站在技術角度,有很多的 API 開放標準可供我們參考,一些開源產品的 Open API 文檔也都非常完善。一方面,我會取其精華,另一方面,要考慮自身產品輸出形態的特殊性。本文將圍繞諸多因素,嘗試探討出一份合適的 Open API 開放規範。

Open API 設計考慮因素

一個完善的 Open API 規範到底應該規範哪些東西?

站在設計角度,需要考慮:命名規範,構成規範,路徑規範,出入參規範,數據類型規範,統一返回值規範,錯誤碼規範,分頁規範。

站在團隊角度,團隊中的後端初級中級開發以及前端研發是否有足夠的經驗,領悟並落地好制定的 API 規範。同時,伴隨着人員流動,這份 Open API 規範是否可以很好地被傳承下去。

站在行業角度,需要考慮提供 Open API 的產品所在的市場是否已經成熟,API 風格可能已經有了對應的規範。

站在產品角度,每個產品適合的 API 風格是不同的,下文會着重探討這一角度。

總之,Open API 的設計是很難形成定論的一個東西,我在介紹自身產品最終採用的 Open API 規範之前,會先來聊一下大家耳熟能詳的一些概念,例如 restful。

restful 規範之爭

有人的地方就會有江湖。

有代碼的地方也是如此。

如果你在碼圈混,一定聽說過 restful 規範:

restful 規範看似美好,但如果你真正嘗試過落地,一定會遇到一些類似的問題:

基於此,restful 規範逐漸有了反對的聲音:

restful 風格的擁躉者,不乏對這些反對言論進行抨擊,社區中不免有 “拒絕 restful 風格的主要是低水平不思進取的架構師和前後端程序員們,不會設計是人的問題,不是規範的問題” 此類的言論。同時對 restful 進行了昇華:複雜參數的檢索問題,在 restful 語義中本就應當歸類爲 post,因爲該行爲並不是對資源的定位(GET),而是對資源的檢索(POST)

這顯然刺激了 restful 風格反對者的神經,不屑道:呵,愚蠢的 restful 原教旨主義者呀。

不知道你是 restful 的擁躉者還是反對者?亦或是,中立者。

restful 之爭暫時到此爲止,這番爭論純屬虛構,看官不必計較。無論你如何看待 restful,下面我的論述,你都可以作爲一箇中立者,否則效果減半。

ROA 與 RPC

API 設計並不只有 restful 一種規範,在更大的視角中,主流的 API 設計風格其實可以分爲

restful 便是 ROA 風格的典型例子,而 RPC 風格則相對而言不太容易被大家熟知,但實際上可能大多數的系統的接口是 RPC 風格的,只不過 RPC 風格這個概念不太爲人所知。

以用戶模塊的 CRUD 爲例,對比下兩個風格:

ROA 風格

創建用戶(POST)

Request:
POST /users

{"name""kirito""age": 18}

Response:
HTTP 201 Created

{"id": 1, "name""kirito""age": 18}

查詢用戶(GET)

Request:
GET /users/1

Response:
HTTP 200 OK

{"id": 1, "name""kirito""age": 18}

查詢用戶列表(GET)

Request:
GET /users

Response:
HTTP 200 OK

{[{"id": 1, "name""kirito""age": 18}]"next""/users?offset=1"}

創建 / 修改用戶 (PUT)

Request:
PUT /users/1

{"name""kirito""age": 19}

Response:
HTTP 200 OK

{"id": 1, "name""kirito""age": 19}

修改用戶(PATCH)

Request:
PATCH /users/1

{"age": 20}

Response:
HTTP 200 OK

{"id": 1, "name""kirito""age": 20}

刪除用戶(DELETE)

Request:
DELETE /users/1

Response:
HTTP 204 No Content

ROA 風格和 restful 規範說明的是一回事,爲方便其與 RPC 風格接口的對比,特此說明上面示例的一些值得關注的點:

RPC 風格

創建用戶(POST)

Request:
POST /user/createUser

{"name""kirito""age": 18}

Response:
HTTP 200 OK

{"code": 0, "message""""data"{"id": 1, "name""kirito""age": 18}}

查詢用戶(POST)

Request:
POST /user/getUser

{"id": 1}

Response:
HTTP 200 OK

{"code": 0, "message""""data"{"id": 1, "name""kirito""age": 18}}

查詢用戶列表(POST)

Request:
POST /user/listUsers

Response:
HTTP 200 OK

{"code": 0, "message""""data"{"user"[{"id": 1, "name""kirito""age": 18}]"next""/user/listUsers?offset=1"}}

修改用戶 (POST)

Request:
POST /user/modifyUser

{"id": 1, "name""kirito""age": 19}

Response:
HTTP 200 OK

{"code": 0, "message""""data"{"id": 1, "name""kirito""age": 19}}

修改用戶名稱 (POST)

Request:
POST /user/modifyUserAge

{"id": 1, "age": 20}

Response:
HTTP 200 OK

{"code": 0, "message""""data"{"id": 1, "name""kirito""age": 20}}

刪除用戶(DELETE)

Request:
POST /user/deleteUser

{"id": 1}

Response:
{"code": 0, "message"""}

RPC 風格不像 restful 一類的 ROA 風格存在一些約定俗成的規範,每個業務系統在落地時,都存在差異,故此處只是筆者個人的經驗之談,但願讀者能夠求同存異:

如何選擇 RPC 和 ROA,則需要根據產品自身的業務情況進行決策。有如下的指導原則:

AWS 主要採用 RPC 風格,Azure、Google 主要採用 ROA(restful)風格,阿里雲 OpenAPI 同時支持 RPC 和 ROA,以 RPC 爲主。

儘管規範是無罪的,但在 ROA 風格在實踐過程中,我還是見識過不少 “坑” 的:

CSB 的 Open API 規範希望滿足以下的需求:

綜上,在設計風格選擇上,我計劃採取 RPC 的設計規範。總結一下 RPC 風格的優勢:

一個詳細的 RPC 接口文檔示例

創建服務

請求參數

Aj02yi

返回參數

86n2ar

請求示例

POST /service/createService

Request:
{
  "name""httpbin",
  "protocol""http",
  "lb""random",
  "upstreamType""fixed",
  "nodes"[
    {
      "host""httpbin.org",
      "port""80",
      "weight""1"
    }
  ],
  "gatewayId""gw-1qw2e3e4"
}

Response:
{
  "code": 0,
  "message""",
  "serviceId""s-1qw2e3e4"
}

API 命名規範

總結

以本文推崇的一條規範爲例:"所有接口全部使用 POST",這不是爲了遷就低水平不思進取的架構師和前後端程序員們(我在社區論壇上看到的言論),而是爲了提高開發效率,降低溝通成本,降低運維和錯誤定位成本,把瞎折騰的成本,投入到了其他比如業務架構設計,測試體系,線上監控,容災降級等領域上。

接口規範也並非我總結的那樣,只有 RPC 和 ROA,也有一些言論將 GraphQL 單獨歸爲一類 API 設計風格,用於複雜查詢場景,有興趣的同學可以參考 es 的 API 文檔。

綜上,我計劃採用 RPC 的 API 設計風格。

參考資料

kong:https://docs.konghq.com/gateway/2.8.x/admin-api/

google restful api design:https://cloud.google.com/apis/design?hl=zh-cn

https://www.zhihu.com/question/336797348

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/NYDNOKl7RgH71njqcHueoA