高效開發(fā):你的項目有接口聚合服務(wù)嗎貌夕?

本文首發(fā)于個人微信公眾號:coder小黑

服務(wù)拆分的痛

服務(wù)拆分之后,前后端同學(xué)之間關(guān)于 API 粒度的爭吵越來越常見:

「前端同學(xué)請求兩個接口踊挠,聚合一下數(shù)據(jù)不就行了?」后端同學(xué)想只提供業(yè)務(wù)領(lǐng)域基礎(chǔ) API 服務(wù)能力冲杀,數(shù)據(jù)組裝處理則希望由前端同學(xué)完成效床。

「后端聚合一下,前端可以少一次請求权谁,只負(fù)責(zé)頁面渲染剩檀!」前端同學(xué)希望只負(fù)責(zé)頁面渲染,而 H5旺芽、APP沪猴、小程序同一個聚合邏輯可能會出現(xiàn)在三端,后端聚合則只需要一次采章。

接口聚合服務(wù)就是我們的一個解決思路运嗜。

接口聚合服務(wù)是什么?

接口聚合服務(wù)就是一個搬運工悯舟,只是幫助前端同學(xué)聚合多個接口的返回數(shù)據(jù)担租,聚合之后一次性返回相應(yīng)請求的結(jié)果給客戶端。我們希望通過接口聚合服務(wù)這個中間層抵怎,做到可以讓前端直接獲取數(shù)據(jù)奋救,而后端也能繼續(xù)專心于提供基礎(chǔ)業(yè)務(wù)領(lǐng)域 API 服務(wù)能力。

場景分析

  • 場景一:串行獲取數(shù)據(jù)反惕。多個請求尝艘,有關(guān)聯(lián)關(guān)系。
    • 例如:通過商品 ID 獲取評論信息承璃,通過評論中的 uid 獲取用戶信息
  • 場景二:并行獲取數(shù)據(jù)利耍。多個請求,無關(guān)聯(lián)關(guān)系。
    • 例如:通過商品 ID 獲取商品信息隘梨、獲取商品活動信息程癌、獲取當(dāng)前用戶已購信息

方案調(diào)研

方案 A 方案 B
調(diào)用者 客戶端 客戶端
API-Server 自研 GraphQL
Payload 約定 GraphQL
Response 約定 GraphQL
容錯 約定 約定
動態(tài)選取字段

最終我們選擇了方案 A,通過自研一套簡單的接口聚合中間層來解決這個問題轴猎。

于是嵌莉,就有了接口聚合服務(wù):api-aggregator。該框架有如下幾個特點:

  • 核心代碼在千行左右捻脖,輕量級實現(xiàn)锐峭。

  • 對現(xiàn)有代碼無侵入性,無需對現(xiàn)有服務(wù)和代碼做改造適配可婶,現(xiàn)有接口可直接使用沿癞。

  • 提供了 ApiAggregatePostProcessor 拓展點來干預(yù)接口聚合的各個階段,可拓展性強(qiáng)矛渴。

  • 對前端友好椎扬,前端同學(xué)可以自定義返回數(shù)據(jù)結(jié)構(gòu),支持字段動態(tài)選取具温。

  • 接口聚合邏輯直接通過配置文件和 api-aggregator 交流蚕涤,新增聚合接口,無需發(fā)布铣猩。

api-aggregator:接口聚合服務(wù)

api-aggregator

api-aggregator 認(rèn)為一個聚合接口應(yīng)該是由若干個接口的返回結(jié)果聚合而成的躁垛,因此在設(shè)計時寄猩,我們將其被劃分為兩個部分:接口元信息和接口之間的聚合邏輯召衔。

ApiDefinition:接口元信息

ApiDefinition 不僅定義了接口的元信息芥牌,同時也描述了接口所需參數(shù)的來源。

api-aggregator 認(rèn)為在一次接口聚合中鳞绕,元信息接口的參數(shù)可能有以下一些來源:

  1. 直接由客戶端傳遞過來失仁,即直接從 HttpRequest 中獲取參數(shù)尸曼。
  2. 從上個接口的返回值中獲取们何。例如:通過商品 ID 獲取評論信息,通過評論中的 uid 獲取用戶信息控轿。此時 uid 參數(shù)就需要從上個接口的返回值中獲取冤竹。

ResponseDefinition:接口間聚合邏輯

ResponseDefinition 描述了接口間的聚合邏輯,通過 ResponseDefinition 前端同學(xué)可以自定義接口返回的數(shù)據(jù)結(jié)構(gòu)茬射,也可以動態(tài)選取所需字段鹦蠕。

描述接口聚合關(guān)系

如果沒有 ResponseDefinition,則 api-aggregator 只能簡單的將兩個接口的數(shù)據(jù)平級的聚合在一起(如上左圖所示)在抛。而現(xiàn)在钟病,可以通過 ResponseDefinition 來定義返回結(jié)構(gòu)體,給前端同學(xué)更好的開發(fā)體驗(如上右圖所示)。

簡單聊聊設(shè)計

配置文件預(yù)加載

接口聚合配置信息是由前端開發(fā)同學(xué)在管理后臺配置的肠阱。

前端同學(xué)在提交配置文件之后票唆,api-aggregator 就會對配置文件做一些靜態(tài)分析:分析接口的依賴情況,是否存在循環(huán)依賴等問題屹徘。

為了提高性能走趋,api-aggregator 將相關(guān)的配置信息解析好之后,會直接緩存在內(nèi)存中噪伊,以減少對同一份配置文件的反復(fù)解析簿煌,同時,再通過定時刷新和 MQ 的 pub/sub 來保證數(shù)據(jù)的一致性鉴吹。

簡化 http 請求模型

HttpMethodInvoker

api-aggregator 抽象了 HttpMethodInvoker 來發(fā)起 HTTP 請求姨伟。通過 Supplier 來獲取返回結(jié)果,屏蔽了不同 Http Client 之間的 API 差異豆励。

還記得前文提到的場景嗎授滓?

場景一:串行獲取數(shù)據(jù)。多個請求肆糕,有關(guān)聯(lián)關(guān)系般堆。

場景二:并行獲取數(shù)據(jù)。多個請求诚啃,無關(guān)聯(lián)關(guān)系淮摔。

在 api-aggregator 中,將這兩個場景進(jìn)行了簡化合一始赎。

首先和橙, api-aggregator 在解析配置文件分析接口依賴時,會根據(jù)接口的依賴情況給出一個 api-aggregator 認(rèn)為是最優(yōu)的 HTTP 請求流程造垛,而不是根據(jù)配置文件定義的接口順序依次請求魔招。

舉個例子:

假設(shè)在一次接口聚合中,需要請求接口 A五辽、B办斑、C,而接口 B 的數(shù)據(jù)依賴于接口 A杆逗,接口 A 和接口 C 的請求參數(shù)均可直接從 HttpRequest 中獲取參數(shù)乡翅。

那么,在實際的接口聚合過程中罪郊,api-aggregator 會先請求接口 A 和接口 C蠕蚜,然后阻塞獲取接口 A 的返回結(jié)果,最后請求接口 B悔橄。

提供擴(kuò)展點

api-aggregator 提供了 ApiAggregatePostProcessor 來方便后續(xù)擴(kuò)展靶累。

通過 ApiAggregatePostProcessor腺毫,api-aggregator 可以干預(yù)一個接口聚合的整個流程,例如:緩存接口信息挣柬、增加監(jiān)控日志等等拴曲。

ApiAggregatePostProcessor

雖然通過 ApiAggregatePostProcessor 可以來干預(yù)接口的聚合流程,但是想要添加新的 Processor 時還是需要重啟api-aggregator凛忿。而 api-aggregator 作為接口聚合點澈灼,和網(wǎng)關(guān)相似,也是流量的集中點店溢,在后續(xù)的版本中叁熔,可能會考慮引入 Groovy 腳本,來支持動態(tài)的開啟和停用 Processor床牧。

最后荣回,歡迎大家在評論區(qū)一起留言討論,感謝你的閱讀~~


歡迎關(guān)注個人公眾號:

Coder小黑
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
禁止轉(zhuǎn)載戈咳,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者心软。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市著蛙,隨后出現(xiàn)的幾起案子删铃,更是在濱河造成了極大的恐慌,老刑警劉巖踏堡,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件猎唁,死亡現(xiàn)場離奇詭異,居然都是意外死亡顷蟆,警方通過查閱死者的電腦和手機(jī)诫隅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來帐偎,“玉大人逐纬,你說我怎么就攤上這事∠鞣” “怎么了豁生?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長嫉父。 經(jīng)常有香客問我沛硅,道長眼刃,這世上最難降的妖魔是什么绕辖? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮擂红,結(jié)果婚禮上仪际,老公的妹妹穿的比我還像新娘围小。我一直安慰自己,他們只是感情好树碱,可當(dāng)我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布肯适。 她就那樣靜靜地躺著,像睡著了一般成榜。 火紅的嫁衣襯著肌膚如雪框舔。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天赎婚,我揣著相機(jī)與錄音刘绣,去河邊找鬼。 笑死挣输,一個胖子當(dāng)著我的面吹牛纬凤,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播撩嚼,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼停士,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了完丽?” 一聲冷哼從身側(cè)響起恋技,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎逻族,沒想到半個月后猖任,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡瓷耙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年朱躺,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片搁痛。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡长搀,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出鸡典,到底是詐尸還是另有隱情源请,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布彻况,位于F島的核電站谁尸,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏纽甘。R本人自食惡果不足惜良蛮,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望悍赢。 院中可真熱鬧决瞳,春花似錦货徙、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至屡贺,卻和暖如春蠢棱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背甩栈。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工裳扯, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人谤职。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓饰豺,卻偏偏與公主長得像,于是被迫代替她去往敵國和親允蜈。 傳聞我的和親對象是個殘疾皇子冤吨,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容