推薦閱讀:
「前端同學請求兩個介面,聚合一下資料不就行了?」後端同學想只提供業務領域基礎 API 服務能力,資料組裝處理則希望由前端同學完成。
「後端聚合一下,前端可以少一次請求,只負責頁面渲染!」前端同學希望只負責頁面渲染,而 H5、APP、小程式同一個聚合邏輯可能會出現在三端,後端聚合則只需要一次。
介面聚合服務就是我們的一個解決思路。
介面聚合服務是什麼?
介面聚合服務就是一個搬運工,只是幫助前端同學聚合多個介面的返回資料,聚合之後一次性返回相應請求的結果給客戶端。我們希望通過介面聚合服務這個中間層,做到可以讓前端直接獲取資料,而後端也能繼續專心於提供基礎業務領域 API 服務能力。
最終我們選擇了方案 A,通過自研一套簡單的介面聚合中間層來解決這個問題。
於是,就有了介面聚合服務:api-aggregator。該框架有如下幾個特點:
核心程式碼在千行左右,輕量級實現。對現有程式碼無侵入性,無需對現有服務和程式碼做改造適配,現有介面可直接使用。提供了 ApiAggregatePostProcessor 拓展點來干預介面聚合的各個階段,可拓展性強。對前端友好,前端同學可以自定義返回資料結構,支援欄位動態選取。介面聚合邏輯直接通過配置檔案和 api-aggregator 交流,新增聚合介面,無需釋出。api-aggregator:介面聚合服務
api-aggregator 認為一個聚合介面應該是由若干個介面的返回結果聚合而成的,因此在設計時,我們將其被劃分為兩個部分:介面元資訊和介面之間的聚合邏輯。
ApiDefinition:介面元資訊
直接由客戶端傳遞過來,即直接從 HttpRequest 中獲取引數。從上個介面的返回值中獲取。例如:通過商品 ID 獲取評論資訊,通過評論中的 uid 獲取使用者資訊。此時 uid 引數就需要從上個介面的返回值中獲取。ResponseDefinition:介面間聚合邏輯
ResponseDefinition 描述了介面間的聚合邏輯,通過 ResponseDefinition 前端同學可以自定義介面返回的資料結構,也可以動態選取所需欄位。
如果沒有 ResponseDefinition,則 api-aggregator 只能簡單的將兩個介面的資料平級的聚合在一起(如上左圖所示)。而現在,可以通過 ResponseDefinition 來定義返回結構體,給前端同學更好的開發體驗(如上右圖所示)。
簡單聊聊設計配置檔案預載入
介面聚合配置資訊是由前端開發同學在管理後臺配置的。
前端同學在提交配置檔案之後,api-aggregator 就會對配置檔案做一些靜態分析:分析介面的依賴情況,是否存在迴圈依賴等問題。
為了提高效能,api-aggregator 將相關的配置資訊解析好之後,會直接快取在記憶體中,以減少對同一份配置檔案的反覆解析,同時,再通過定時重新整理和 MQ 的 pub/sub 來保證資料的一致性。
api-aggregator 抽象了 HttpMethodInvoker 來發起 HTTP 請求。通過 Supplier 來獲取返回結果,遮蔽了不同 Http Client 之間的 API 差異。
還記得前文提到的場景嗎?
場景一:序列獲取資料。多個請求,有關聯關係。
場景二:並行獲取資料。多個請求,無關聯關係。
在 api-aggregator 中,將這兩個場景進行了簡化合一。
首先, api-aggregator 在解析配置檔案分析介面依賴時,會根據介面的依賴情況給出一個 api-aggregator 認為是最優的 HTTP 請求流程,而不是根據配置檔案定義的介面順序依次請求。
舉個例子:
假設在一次介面聚合中,需要請求介面 A、B、C,而介面 B 的資料依賴於介面 A,介面 A 和介面 C 的請求引數均可直接從 HttpRequest 中獲取引數。
那麼,在實際的介面聚合過程中,api-aggregator 會先請求介面 A 和介面 C,然後阻塞獲取介面 A 的返回結果,最後請求介面 B。
提供擴充套件點
api-aggregator 提供了 ApiAggregatePostProcessor 來方便後續擴充套件。
通過 ApiAggregatePostProcessor,api-aggregator 可以干預一個介面聚合的整個流程,例如:快取介面資訊、增加監控日誌等等。
雖然通過 ApiAggregatePostProcessor 可以來干預介面的聚合流程,但是想要新增新的 Processor 時還是需要重啟api-aggregator。而 api-aggregator 作為介面聚合點,和閘道器相似,也是流量的集中點,在後續的版本中,可能會考慮引入 Groovy 指令碼,來支援動態的開啟和停用 Processor。
作者:程式設計師小黑原文連結:https://juejin.im/post/5e094adff265da33c90b5804