API 快速開發平臺的設計和思考

在我之前談 API 網關的時候曾經談到過快速開發平臺,即將 API 快速開發的一些內容放入到 API 網關中,實際來看圍繞 API 全生命週期管理,本身包括了開發態,運行態,運維態。

對於 API 網關更多的是解決運行態的問題,API 網關本身應該輕量化設計,不做太多的協議轉換,適配,數據映射等工作,這些工作應該放到 API 開發平臺來完成。API 開發平臺最終就是開發完成並暴露一個標準的 Http API 接口,並將接口註冊和接入到 API 網關。

API 全生命週期管理

圍繞 API 全生命週期管理來看,整個子系統劃分如下:

簡單來講這部分可以分解爲四個子系統,即 API 開發平臺,API 網關引擎,API 監控運維平臺,API 全生命週期管控平臺。

對於傳統 ESB 總線裏面的適配器,協議轉換等相關比較重的內容,都可以轉移到 API 快速開發平臺來完成,即 API 開發平臺暴露標準的 API 服務接口,註冊和接入到 API 網關引擎。而對於 API 監控平臺則從引擎採集日誌信息,進行 API 性能監控和日誌監控分析。

API 全生命週期管控平臺實現 API 接口從設計,開發,測試,部署上線的全生命週期管理,也可以理解爲底層三個子系統的一個統一管理門戶,實現和下面三個子系統集成。

對於 API 開發平臺開發和配置完成的微服務 API 接口,可以支持自動部署到微服務運行平臺。

基於對象建模驅動

在整個 API 開發平臺實現中,核心思想仍然應該是基於對象建模驅動,通過對象建模很好的實現接口和底層數據庫,數據庫表之間的解耦,也方便實現底層多數據庫,多表的支持能力。

當前很多 API 快速開發平臺都是基於數據庫對象或表,直接發佈類似 CRUD 的 API 接口服務,但是基於是數據庫表的直接發佈,我們仍然建議逆向對象這層,方便後續在對象層進行相關的組合,規則擴展等操作。

對象建模和 API 接口契約

可以直接在 API 開發平臺創建對象,並對數據項進行定義,對象是一個多層的樹狀結構實體。一個對象可以向數據庫生成多張表。對於已經存在的數據對象,也可以進行組合,將多個組合爲一個複合對象結構。

對象的好處即是一個完整的對象屬於同一生命週期,可以一起進行事務控制。

一個設計好的對象可以默認生成標準的 POST,GET,DELETE 等接口操作方法,類似下圖,整個對象接口契約的生成也應該是自動的。

定義好的對象可以直接生成類似 RAML,YAML,WADL 等接口契約文件。

類似 Swagger 工具一樣,完成的對象建模本身也可以直接導出不同語言,不同開發框架下的客戶端消費框架,服務端提供框架代碼。

對象適配到數據庫

前面講到了,既可以是數據庫直接逆向對象,也可以是在對象建模完成後,將對象適配到數據庫。完成對象和數據庫表之間的映射。一個對象可以映射到多張數據庫表,因此在映射過程中除了完成數據庫表和字段映射外,還需要完成主外鍵關聯關係的映射操作。

在完成對象模型和數據庫表之間的映射和適配後,基本發佈的 API 接口已經可用。

API 接口發佈

對於完成的對象定義,可以選擇具體發佈哪些 API 接口服務能力。比如可以只選擇發佈查詢接口,也可以只選擇發佈數據導入的 POST 接口等。

注意 API 接口的發佈,具體可以基於全局的對象建模,配置具體需要發佈到接口的數據項信息。很多時候我們對數據對象的操作,並不是操作整個對象全集,而僅僅是部分數據項。

API 接口模擬測試和驗證

可以對發佈的 API 接口進行模擬測試和驗證,因此需要提供在線的 API 測試工具,能夠方便在線進行 API 接口的測試工作。同時可以對測試過的用例和測試數據進行保存。

API 接口文檔生成

支持自動生成 API 接口文檔的能力。這個地方可以直接對接類似開源 Swagger 等工具來實現 API 接口文檔的自動生成功能。

對象常用接口操作

當對象定義完成後,可以基於對象進行相關 API 接口的自動生成。在這裏簡單列下基於對象常用的接口方法,主要包括新增一條數據,基於主鍵更新,查詢,刪除數據。其它的則是基於條件查詢對數據進行查詢相關操作等。

在 GtiHub 裏面開源又一個 xmysql 的工具,可以直接將整個 MySQL 數據庫中的數據庫表發佈爲 RestAPI 接口,具體可以安裝試用。

npm install -g xmysql
xmysql -h localhost -u mysqlUsername -p mysqlPassword -d databaseName
http://localhost:3000

注意需要提前安裝 Node.js,部分接口方法列表如下:

由於生成的 API 接口都沒有相關的權限控制,因此該開源工具也僅僅用於自己測試和驗證使用。但是生成的方法和 API 可以作爲 API 開發工具時候參考。

實際上對於 API 接口的生成,我們並不建議對於複雜查詢條件下的查詢都通過 GET 方法來實現,更好的思路還是通過 POST 方法,將查詢條件作爲 POST 輸入進行處理。

複合對象一次生成

比如將訂單作爲一個對象,實際包括了訂單頭和訂單明細表,而在進行 API 生成時候可以一次生成基於訂單對象的插入操作,查詢操作。最終查詢出來的是一個訂單複合實體 Json 數據。而對於訂單插入,也是先準備好整個訂單實體信息,一次調用 API 接口完成數據插入,也方便在 API 接口實現的時候進行事務控制。

複合對象生成的 API 接口更類似於領域對象暴露的 API 接口服務能力。

分頁支持

對於查詢 API 接口服務的生成,應該支持分頁能力,具體分頁的大小,本次查詢訪問具體頁數等信息都可以作爲 API 接口的查詢輸入參數進行設置。

直接定義 API 接口併發布

在前面談到了基於對象來發布 API 接口服務,但是還有一些業務規則邏輯類接口,複雜的管理數據查詢類接口等並不能簡單的通過對象來自動生成。

因此還需要能夠實現基於方法來發布 API 接口服務。

即在 API 快速開發平臺能夠進行 API 接口的自定義,詳細的定義 API 接口的輸入參數和輸出參數信息。同時對於定義完成的接口實現和後臺方法的綁定。

實現和 JAR 包裏面的 API 接口的綁定

可以實現和一個 JAR 包裏面方法或函數的綁定,將一個方法或函數發佈爲一個 Http API 接口方法。在當前很多公有云的雲服務總線產品上可以看到這個實現方式。

實現和動態 SQL 的綁定

可以將定義的一個 API 接口方法和動態 SQL 進行綁定。其中動態 SQL 本身具體動態輸入參數,這些輸入參數和 API 接口定義中的輸入進行數據映射。同時 SQL 語句查詢的輸出結果和 API 接口定義的輸出字段進行映射。

如果動態 SQL 是插入或更新類,同樣也可以通過參數化變量方式進行數據映射和綁定操作。

和存儲過程進行綁定

一個數據庫的存儲過程,實際即是一個方法函數,因此可以將 API 接口定義的輸入和輸出和數據庫存儲過程的輸入和輸出進行映射綁定。

要注意的是針對不同的數據庫存儲過程 schema 信息獲取和適配本身有差異,這也是在上圖中構建一個獨立的統一數據庫適配層的原因。

規則處理

在 API 接口開發過程中,可以進行一些簡單的規則處理。具體如下:

在輸入的消息頭中往往包括了類似用戶名,Token 等用於訪問安全校驗的字段,也包括了類似路由,分頁等相關擴展字段信息。對於輸出字段,需要對返回的異常類型,編碼,異常信息等進行約定。特別是涉及到數據 CUD 操作的時候,需要按約定的輸出字段進行輸出。

服務組合和編排

對於 API 開發平臺還可以進一步提供服務組合和服務編排的能力。這個能力的實現也不適合放在 API 網關來完成,而是應該規劃到 API 開發平臺來實現。

服務組合編排是服務組合,服務組裝等,希望通過服務編排能夠完成這些事情,而不是簡單的完成單一服務的設計和開發。即將多個原子服務組合或組裝在一起,最終形成一個新的服務並提供的能力。我們舉例來說明下。

比如存在 A,B,C 三個原子服務,我們通過服務編排形成一個新的 D 服務。

三個原子服務全部是查詢服務,希望組裝一個新服務,一次返回 A,B,C 三個服務查詢結果

這個即我們說的服務組合能力,比如我們可以對合同基本信息查詢,合同條款信息查詢,合同執行信息查詢三個基本原子服務進行組合,最終返回一個服務綜合信息查詢的服務,一次返回三個查詢結果。

在這種場景下我們需要考慮查詢結果是並行返回還是按層次返回即可。

二個查詢類的原子服務,最終需要返回兩個數據集關聯查詢的結果集

這個在微服務架構做了底層數據庫拆分後經常會遇到,比如對於物料基本信息查詢,和採購訂單明細查詢是在兩個獨立的數據庫獨立服務提供。而我們希望返回的查詢結果集是物料編碼,名稱,型號,單位,價格,採購數量的複合結果集。

這種場景下往往一般都是在前端功能開發的時候進行組裝,而實際上可以考慮是否可以在服務編排層解決這個問題,該問題寫代碼來解決容易,但是要做爲可視化服務編排組態方式來做實際上有一定的難度。

對單個已有服務進行裁剪和豐富並形成一個新服務輸出

這個暫時也將其納入到服務編排的範疇,即仍然是輸入服務,但是輸出是提供了一個新服務。

即對單個已有的服務進行服務裁剪和豐富,比如對於輸出結果過濾掉一些數據項,對於輸入固定輸入一些數據項等。這些簡單的服務裁剪,豐富,或簡單的數據轉換可以在服務編排的時候完成,並提供一個新服務。

對多個原子服務進行流程式的前後串接並形成服務提供

這個是我們經常看到的一種服務編排場景,即 A,B,C 三個服務直接進行編排,即 A 服務的輸出直接變爲 B 服務的輸入,B 服務的輸出又變爲 C 服務的輸出。如果僅僅是上面假設的這樣,那麼這種流程式的服務編排仍然很簡單,也很容易去實現。

但是實際上的難點在於 A 服務的輸出本身也需要作爲 C 服務的輸出,同時 A,B 服務的輸出也可能是整體輸出的一部分,這本身就加大了服務編排可視化設計的難度。

單一業務服務爲主體服務,但是編排多個業務規則邏輯處理類服務

這也是經常會遇到的場景,比如我們在進行合同信息導入的時候,首先要調用合同有效性校驗服務,同時還有調用預算信息檢查和扣減服務進行相關的完整性和業務規則校驗。在這些校驗完成後再調用實際的合同信息導入服務,如果校驗失敗則直接返回失敗結果。

這類服務編排往往也正是我們實際在進行前端功能開發時候服務進行組裝的邏輯。

多個導入服務組裝爲一個導入服務合併導入並形成一個新服務

這個場景實際上和場景 1 是對應的,既然多個服務可以組合後形成組合結果返回,那麼自然可以將多個導入服務合併爲一個導入服務,一次性的完成數據導入。

比如有項目信息導入和項目 WBS 信息導入兩個原子服務,那麼我們就可以提供一個新的項目信息導入服務,一次完成項目基本信息和項目 WBS 信息的導入。

在這些場景裏面可以看到,實際上服務編排就是服務串聯,服務並聯下的輸入和輸出合併,服務內容豐富和裁剪等常見場景。在一個理想的場景下,我們最希望實現的就是一個業務功能點的實現完全能夠通過服務編排可視化設計方式來完成。

關於服務編排詳細說明可以參考:https://www.toutiao.com/i6860399450171376141/

源代碼導出

對於 API 快速開發平臺,很難去實現複雜的業務規則編碼。因此在存在複雜業務規則實現的時候仍然是建議開發人員自己開發代碼來完成。因此整個平臺應該提供源代碼導出功能,導出的源代碼應該直接能夠編譯通過,脫離 API 開發平臺部署和運行。

對於導出的源代碼,考慮到後續 API 接口變更的場景,建議是對擴展部分進行約定。

比如一個標準的 API 接口服務實現方法,可以在前後增加擴展處理。

//BeforeDo();
//ProcessAPI();
//AfterDo();

這樣在接口實現前可以進行額外的業務規則處理和完整性校驗,在接口返回數據前還可以對輸出的數據進一步進行處理和加工。

微服務應用

可以將多個對象或多個 API 接口服務打包到一個微服務應用再進行部署和發佈。因此在這裏引入一個微服務集的概念,對微服務 API 進行打包處理。

打包完成的微服務可以導出爲獨立的 JAR 包進行部署,也可以直接在 API 開發平臺進行託管部署。對於 API 開發平臺本身應該對接到微服務運行平臺。

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