1. 程式人生 > >基於OAS設計可擴展OpenAPI

基於OAS設計可擴展OpenAPI

not format urn design 通配 默認 rms 核心 消費者

前言

隨著互聯網行業的興起,開發模式已逐步轉換為微服務自治:小團隊開發微服務,然後通過Restful接口相互調用。開發者們越來越渴望能夠使用一種“官話”進行流暢的溝通,甚至實現多種編程語言系統的自動化交互。

開放API戰略(Open API Initiativev)於2017年1月發表聲明,2月發布實現草案,經過反復討論, 標準API規範OAS(OpenAPI-Specification)3.0版本在2017年6月誕生。

本文通過對OAS 3.0的分析解讀,希望拋磚引玉,和大家一起了解OAS如何定義一種機器和人都能夠發現與識別的規範,使得OpenAPI消費者可使用最小數量的實現邏輯來理解遠程服務。

OpenAPI-Specification規範架構

OAS 3.0架構中將OpenAPI賦予了以下8個模塊的定義,其中黃色模塊為必選字段,綠色模塊為可選字段:

技術分享圖片

各個主要模塊工作流如下所示:

技術分享圖片

以下重點說明用戶獲取OAS API信息的三個必選部分:

1.API基本信息

用戶查詢獲取OpenAPI的基本定義及信息,涉及以下兩個模塊內容:

openapi

是否必選:必選

對象類型:String

類似於XML聲明(<?xml version="1.0"?> ),用於設定文件應該使用哪一種規範進行解析。

info

是否必選:必選

對象類型:Info Object

這個模塊主要提供API的元數據。

以下為一個Info Object樣例:

title: Sample Pet Store App    #必須,應用名稱 
description: This is a sample server for apetstore.   #應用的描述 
termsOfService: http://example.com/terms/      #應用的服務條款連接 
contact:      #應用提供商的聯系方式 
   name: API Support 
   url: http://www.example.com/support 
   email: [email protected] 
license:   #應用所遵循的協議 
   name: Apache 2.0 
   url: http://www.apache.org/licenses/LICENSE-2.0.html 
version: 1.0.1       #應用版本

2.目標服務器信息

用戶查詢獲取服務器的基本定義及信息,涉及以下模塊信息:

servers

是否必選:必選

對象類型:[Server Object]

這個模塊主要提供和目標服務器的連接信息,如果這個模塊沒有定義url,根據規範會自動生成一個url為/的Server Object。

例如:

servers: 
- url: https://development.gigantic-server.com/v1  #必選, 
  description: Development server   #非必選,url描述

3.API路徑及定義

查詢API具體參數,涉及OAS剩余的模塊,本文主要介紹paths和components模塊。

paths

是否必選:必選

對象類型:Paths Object

這個模塊主要提供OpenAPI所在的目標服務器的連接信息,如果這個模塊沒有定義,根據規範會自動生成一個url為/的Server Object。通過多級定義,分別確定API的paths/method,並且通過$ref引用comonents模塊中的定義,可以復用響應碼等相關信息。對於攜帶body體的請求類型,requestBody可以提供example(或數組examples),這是非常靈活的(可以傳入一個完整的例子,一個參考,甚至是一個URL的例子)。

例如:

/pets:        #URL 
     get:     #方法,get/post/.. 
             description: Returns all pets .    #描述 
                     responses:         #響應模塊 
                         200:         #返回碼為200,可以使用通配符定義響應 
                                 description: A list of pets.    #響應描述 
                                 content:           #Content字段 
                                     application/json: 
                                                 schema: 
                                                             type: array  
                                                                     items: 
                                                                         $ref: #/components/schemas/pet #引用componets

components

是否必選:非必選

對象類型:Components Object

這個模塊主要提供每個OpenAPI自定義的字段定義,這部分定義的對象往往被paths中具體API進行引用:

?響應 responses

?參數 parameters

?示例 examples

?請求體 requestBodies

?標題 headers

?鏈接 links

?回調 callbacks

?模式 schemas

?安全體系 securitySchemes

以下為一個Components Object樣例:

components: 
     schemas: #協議定義
         Category: 
             type: object 
             properties: 
                 id: 
                         type: integer 
                         format: int64 
                 name: 
                         type: string 
         Tag: 
             type: object 
             properties: 
                     id: 
                         type: integer 
                         format: int64 
                     name: 
                         type: string 
     parameters: #參數定義
         skipParam: 
             name: skip 
             in: query 
             description: number of items to skip 
             required: true 
             schema: 
                 type: integer 
                 format: int32 
         limitParam: 
             name: limit 
             in: query 
             description: max records to return 
             required: true 
             schema: 
                 type: integer 
                 format: int32 
     responses: #返回信息定義
         NotFound: 
             description: Entity not found. 
         IllegalInput: 
             description: Illegal input for operation. 
     GeneralError: 
         description: General Error 
         content: 
             application/json: 
                     schema: 
                         $ref: #/components/schemas/GeneralError 
     securitySchemes: 
         api_key: 
             type: apiKey 
             name: api_key 
             in: header 
     petstore_auth:  #認證定義
         type: oauth2 
         flows: 
             implicit: 
                     authorizationUrl: http://example.org/api/oauth/dialog 
                     scopes: 
                         write:pets: modify pets in your account 
                         read:pets: read your pets

如何使用OAS 設計可擴展的OpenAPI

OpenAPI規範包含一組有關如何設計REST API的強制性準則,首推協議優先的方法,而非實現優先,因此需要首先設計API接口,然後實現協定接口的代碼。

如何實現一個優雅的API是一個非常具有挑戰性的工作,開發者需要在龐大的後端系統的支持下,通過合適的方式將API暴露出去,除去單詞拼寫,路徑設計等以外,設計優良的OpenAPI往往具有以下特性:

單一職責

單一職責是軟件工程中一條著名的原則,實際在設計API時應確保每個API具有單一核心的職責,當某個API職責發生改變時不應該導致其他API發生故障和風險。OAS中不同的API可以在paths模塊中引用多個schema,當我們設計新的API或者擴展原有API功能時,如果發現多個API多次引用相同schema,需重點審視每個API是否仍然保持單一職責。

抽象API

合適的抽象API 與業務無關的,更通用,而且方便擴展。 具體的API接口設計能解決特定的問題,但是在系統的擴展性和普遍適用性上則相應欠缺,因此需要針對特定的場景分析,避免over-designed(過度設計)和under-engineering(懶惰設計)。

舉個簡單的例子,我們設計一個paths為/dog的API,那麽這個API返回的是具體dog的相關信息,而如果我們進行抽象設計一個paths為/pet的API,將dog作為參數配置在components的parameters中,這樣該API的擴展性進行了提升,後續擴展其他寵物比如cat的業務可以在不改變API路徑的基礎上進行開發,只需要更新component的parameters即可。

收斂API

提供給用戶的OpenAPI最好支持批量數據處理,而不是讓用戶一次一次地調用。通過考慮多個API間的關聯性,讓用戶體會到API的簡潔性。舉例來說,如果用戶有可能在調用 API2之前需要API1的結果,那麽API提供者應該把API1和API2進行包裝。這會減輕用戶的記憶負擔,API收斂需要符合最少知識的原則,作為用戶應該對他所使用的系統有最少的了解,而不是過多介入到系統的細節中,因此在設計API時候,在滿足用戶訴求的情況下,components模塊字段越少越好。設計者往往容易在收斂API時候出現無法保證單一職責的原則的情況,好的設計需要在兩者之間取得一個平衡,聚焦於最終的目的:讓使用者快好省的用起來。

擴展機制

在設計API時需要考慮未來可擴展性,為後續API兼容歷史API提供支持。一方面便於開發者自身增加功能,另一方面用戶也能參與進來,共建API生態。通過設計定義OAS,可以方便的按照OAS架構設計出面向對象、擴展性良好的API。

版本控制

版本控制其實是擴展的一部分,鑒於大量項目在版本控制方面都做的比較糟糕,諸如隨心所欲的版本命名、前後格式不一致的版本設定、沒有規範的功能叠代,因此在大版本號不變的情況下,需要保障API向前兼容。當API的大版本號改動時,意味著API整體有大的改動,很可能不兼容之前的API,同時可以提醒用戶需要查詢API更新文檔進行適配,否則用戶可能在更新API之後出現各種各樣難以預測的故障。反之,如果修改小版本號則意味著這是個向前兼容的優化升級,用戶可以在例行更新中采用新的API。這種和用戶約定好的默契,可以激發用戶采用新版本的熱情,而不是永遠不升級依賴。

面向擴展開發

在通過OAS定義完相關信息之後,優雅的OpenAPI在開發過程中應著重思考API的可配置性,API的實現應該面向修改開放的,因此需要將相關諸如參數校驗、字段長度等配置項進行抽取,在提供默認配置項的前提下可配置可修改,同時應當允許配置項的新增,例如引入java的可變參數類型等,這樣當OAS文檔進行修改時,可以盡可能的較少整體API實現的變動量。

以上列舉了優雅的OpenAPI所具有的部分特性,與其說OAS設計規範是一個強制的法則,不如說是一種引導式框架,開發者通過遵循規範從而實現高效的敏捷叠代。

當完成OpenAPI的設計開發之後,我們需要將API托管到合適的平臺上進行能力開放,優秀的平臺減少API提供者的工作量,抽取公共能力使API提供者更加專註於業務功能開發。華為雲的API網關集成了監控、流控、負載均衡等一系列功能,可以為開發者提供高性能、高可用的API 托管服務,實現個人、企業API能力的快速開放。

關於API網關的詳情,可以點擊這裏免費體驗

參考文獻:

《OpenAPI Specification》 :https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#componentsObject

《Microsoft REST API Guidelines》 :https://github.com/Microsoft/api-guidelines/blob/master/Guidelines.md

《API 設計》 :https://docs.microsoft.com/zh-cn/azure/architecture/best-practices/api-design

《從達標到卓越 —— API 設計之道》 :http://taobaofed.org/blog/2017/02/16/a-guide-to-api-design/

基於OAS設計可擴展OpenAPI