<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          如何在中后臺(tái)領(lǐng)域玩轉(zhuǎn)BFF架構(gòu)

          共 4143字,需瀏覽 9分鐘

           ·

          2021-08-20 10:26

          點(diǎn)擊上方 程序員成長(zhǎng)指北,關(guān)注公眾號(hào)

          回復(fù)1,加入高級(jí)Node交流群

          2021年08月14日,平臺(tái)前端在「前端早早聊」分享了哈啰出行在BFF領(lǐng)域的實(shí)踐,以下是由平臺(tái)前端趙存分享的主題

          哈啰出行平臺(tái)前端:Allan91(作者授權(quán)轉(zhuǎn)載)

          鏈接:https://juejin.cn/post/6997250621627858957

          分享大綱

          本次分享主要從業(yè)務(wù)背景、BFF 核心架構(gòu)、基于 Serverless 的 BFF 改造、總結(jié)四個(gè)部分組成。

          業(yè)務(wù)背景

          我們的供應(yīng)鏈場(chǎng)景有很多供應(yīng)商,每個(gè)供應(yīng)商都有物流、資產(chǎn)、倉(cāng)儲(chǔ)等多個(gè)域,而這些域我們的后端都基于 DDD 領(lǐng)域模型做了微服務(wù)化,此時(shí)前端在開發(fā)面向這些供應(yīng)商使用的中后臺(tái)應(yīng)用時(shí),遇到了以下問題:

          • 頁(yè)面顯示需要請(qǐng)求多個(gè)域:比如一個(gè)商家的詳情頁(yè),可能既需要請(qǐng)求倉(cāng)儲(chǔ)數(shù)據(jù),還需要請(qǐng)求資產(chǎn)數(shù)據(jù),才能將一個(gè)頁(yè)面顯示出來(lái)。
          • 接口格式不滿足前端需求:后端微服務(wù)化后,是面向多項(xiàng)目,通用性的,其接口格式不一定能滿足前端需求,前端需要自己做轉(zhuǎn)換,比如單位轉(zhuǎn)換,字段裁減。
          • 需求變化快:業(yè)務(wù)在快速迭代,需要接口的大量支持,而我們的后端域是面向多項(xiàng)目的,更改成本較大,需要投入更多的測(cè)試,此時(shí)如果在前端和后端中間存在一個(gè)中間層,來(lái)做這些事情,那么效率會(huì)有比較好的提高。
          • 部門協(xié)作成本大:有些需求需要其它部門的后端同學(xué)支持,而其它部門的同學(xué)因?yàn)樽约翰块T的需求緊張,排期較滿,導(dǎo)致我們的需求遲遲無(wú)法排期,此時(shí)如果存在一個(gè)中間層,在中間層去請(qǐng)求其它部門提供的領(lǐng)域服務(wù)來(lái)組合數(shù)據(jù)提供給前端,此時(shí)就可以在其它部門同學(xué)不參與的情況下,前端自己完成需求開發(fā),部門之間的協(xié)作成本會(huì)大大降低。

          基于以上背景,前端這邊引入了 BFF 架構(gòu),BFF 架構(gòu)能做哪些事情:

          • 業(yè)務(wù)編排:從后端域多接口獲取數(shù)據(jù)合并輸出給頁(yè)面。比如一個(gè)商家詳情頁(yè)即需要倉(cāng)儲(chǔ)數(shù)據(jù),也需要資產(chǎn)數(shù)據(jù),此時(shí)我們?cè)?BFF 層將倉(cāng)儲(chǔ)和資產(chǎn)數(shù)據(jù)請(qǐng)求回來(lái)組裝吐給前端。
          • 字段轉(zhuǎn)換:字段過濾、數(shù)據(jù)格式化等工作。比如資產(chǎn)域的商戶名字段叫 businessName,而倉(cāng)儲(chǔ)域的商戶名字段叫 shopName,此時(shí)可以在BFF層統(tǒng)一掉,這樣前端就不需要做判斷了。
          • 個(gè)性化數(shù)據(jù):為前端提供個(gè)性化服務(wù),如數(shù)據(jù)壓縮,單位轉(zhuǎn)換等。

          BFF 核心架構(gòu)

          核心架構(gòu)

          以上是 BFF 的核心架構(gòu)圖,前端即中后臺(tái)應(yīng)用,后端域即后端服務(wù),右側(cè)的工具支撐是公司的一些基礎(chǔ)公共服務(wù),中間的就是 BFF 核心實(shí)現(xiàn),我們從上往下看:

          • 業(yè)務(wù):可以在這一層做業(yè)務(wù)編排,字段轉(zhuǎn)換,個(gè)性定制等業(yè)務(wù)邏輯,同時(shí)提供了一個(gè) node-auth 包,可以利用該包做用戶鑒權(quán)。
          • 基礎(chǔ)框架:基礎(chǔ)框架這層,主要封裝了 node-soa 這個(gè) npm 包,node-soa 里面包含了 node-log 日志工具、node-hook 代碼規(guī)則校驗(yàn)工具、node-zk 集群鏈接工具等。
          • Node框架:Node 框架這塊選型的是 Koa2。

          調(diào)用鏈路

          核心架構(gòu)講完后,再看下整個(gè) BFF 架構(gòu)的調(diào)用鏈路:

          調(diào)用鏈路從上往下,我們的中后臺(tái)應(yīng)用通過 HTTP 請(qǐng)求到 Nginx 服務(wù)器上,Nginx 轉(zhuǎn)發(fā)到 BFF 層,BFF 層通過 RPC 調(diào)用后端域的微服務(wù),完成整個(gè)調(diào)用過程。這里有兩個(gè)概念需要說明下:

          • ZooKeeper:可簡(jiǎn)單理解為服務(wù)注冊(cè)中心,后端的各個(gè)微服務(wù)都統(tǒng)一注冊(cè)到這個(gè)注冊(cè)中心,然后 BFF 層充當(dāng) ZooKeeper Client 去連接這個(gè)注冊(cè)中心,連接后,就可以枚舉到注冊(cè)中心每個(gè)服務(wù)的 Host 和 Port,拿到 Host 和 Port 就可以發(fā)起 RPC 調(diào)用了。
          • RPC:遠(yuǎn)程過程調(diào)用,也就是說兩臺(tái)服務(wù)器 A、B,一個(gè)部署在 A 服務(wù)器上的應(yīng)用需要訪問 B 服務(wù)器上的一個(gè)應(yīng)用的某個(gè)方法,由于不在一個(gè)內(nèi)存空間,因此需要通過網(wǎng)絡(luò)來(lái)表達(dá)調(diào)用的語(yǔ)義和傳達(dá)的數(shù)據(jù),可以簡(jiǎn)單理解為 A 服務(wù)器上部署了我們的 BFF 應(yīng)用,B 服務(wù)器上部署了我們的微服務(wù)。RPC 通信協(xié)議可基于 HTTP 或者 TCP 協(xié)議,我們采用的是 gRPC,即使用 HTTP/2 的一種 RPC 調(diào)用方式。

          以上介紹了 BFF 的核心架構(gòu)和整個(gè)調(diào)用鏈路,下面來(lái)看看 node-soa 的具體實(shí)現(xiàn)細(xì)節(jié)。

          服務(wù)初始化

          通過調(diào)用 node-soa 提供的 init 方法來(lái)完成服務(wù)的初始化,其中 dep 即為各后端域的微服務(wù)。

          我們?cè)倏纯?init 的具體實(shí)現(xiàn):

          首先創(chuàng)建了一個(gè) ZooKeeper Client 去連接 ZooKeeper 集群,連接上以后通過 listChildren 方法枚舉 ZooKeeper 集群的所有子節(jié)點(diǎn),拿到子節(jié)點(diǎn)的Host 和 Port 后創(chuàng)建了一個(gè) grpcClient,之后就可以通過這個(gè)grpcClient 發(fā)起 RPC 調(diào)用了。

          服務(wù)調(diào)用

          服務(wù)初始化后就可以發(fā)起 RPC 調(diào)用了,node-soa 提供了request 方法,通過這個(gè)方法即可發(fā)起 RPC 調(diào)用,其中 service 就是后端域,method 即為 java 側(cè)提供的方法。

          我們?cè)诳纯?request 里面的具體實(shí)現(xiàn):

          通過服務(wù)初始時(shí)創(chuàng)建的 grpcClient 發(fā)起 RPC 調(diào)用,拿到數(shù)據(jù)后 resolve 回去,即完成一次 RPC 調(diào)用,在整個(gè) RPC 調(diào)用過程中利用 Jaeger + OpenTracing 做了調(diào)用鏈路的追蹤,利用 node-log 做了請(qǐng)求日志的落盤。以上即為我們第一代BFF架構(gòu)的核心內(nèi)容,這套架構(gòu)在當(dāng)時(shí)的業(yè)務(wù)背景下是一個(gè)比較好的解決方案,但隨著業(yè)務(wù)的快速發(fā)展,這個(gè)架構(gòu)也遇到了一些問題:

          • 運(yùn)維成本增大:隨著 BFF 應(yīng)用的增多,需要更多的機(jī)器來(lái)部署B(yǎng)FF應(yīng)用。
          • 發(fā)布流程長(zhǎng):新增一個(gè) BFF 的接口,需要走完編譯,構(gòu)建,部署一整套流程,無(wú)法做到秒級(jí)部署。
          • 域名不收斂:每個(gè) BFF 都有各自獨(dú)立的域名,增加記憶成本。

          鑒于這些痛點(diǎn),我們引入了 SFF(Serverless For Frontend)架構(gòu),通過將 BFF 構(gòu)建于 Serverless 之上,用云函數(shù)的方式取代傳統(tǒng)基于 NodeJS 的 BFF 層。

          基于 Serverless 的BFF改造

          SFF 架構(gòu)

          上圖是改造后的BFF架構(gòu),相比于一代的 BFF 架構(gòu),這里主要多了兩塊內(nèi)容,一塊是 FaaS 層,另外一塊是開發(fā)者平臺(tái)。

          • 開發(fā)者平臺(tái)是在線編寫云函數(shù)的,主要提供了函數(shù)管理、發(fā)布管理等功能,發(fā)布的每個(gè)函數(shù)都會(huì)保存在數(shù)據(jù)庫(kù)中。

          • FaaS 層主要就是一個(gè)個(gè) Function,一個(gè) BFF 接口請(qǐng)求過來(lái),首先會(huì)去數(shù)據(jù)庫(kù)獲取對(duì)應(yīng)的函數(shù),然后執(zhí)行該函數(shù)。

          實(shí)現(xiàn)方案選型

          目前主流的方案主要是基于容器和基于進(jìn)程兩種方式。

          容器方案:基本實(shí)現(xiàn)是利用K8s + Docker,每個(gè)云函數(shù)執(zhí)行的時(shí)候都啟動(dòng)一個(gè)容器去執(zhí)行,執(zhí)行完后容器銷毀,整個(gè)容器的管理、并發(fā)處理、擴(kuò)縮容都是用K8s來(lái)管理。

          進(jìn)程方案:每個(gè)云函數(shù)的執(zhí)行都啟動(dòng)一個(gè)新的進(jìn)程去執(zhí)行,執(zhí)行完后進(jìn)程銷毀。

          對(duì)于實(shí)現(xiàn)方案的選型,我們需要考慮以下幾個(gè)方面:

          • 業(yè)務(wù)場(chǎng)景復(fù)雜性:高并發(fā)采用容器方案更好;并發(fā)少,選用進(jìn)程更輕量,也更容易實(shí)現(xiàn)。
          • 基建&運(yùn)維能力:容器方案對(duì)基建和運(yùn)維能力有更高的要求,要考慮公司的運(yùn)維能不能 Cover 住。
          • 團(tuán)隊(duì)人力/能力:基于容器方案技術(shù)上的要求會(huì)更高一些,實(shí)現(xiàn)難度也會(huì)更大一點(diǎn),要考慮團(tuán)隊(duì)的小伙伴這方面的經(jīng)驗(yàn)有沒有,團(tuán)隊(duì)的人手夠不夠。

          我們的業(yè)務(wù)并不復(fù)雜,中后臺(tái)應(yīng)用幾乎沒有高并發(fā),目前公司對(duì)于容器的使用還沒有大推,團(tuán)隊(duì)人手也不是很夠,加上缺少容器這方面的實(shí)戰(zhàn)經(jīng)驗(yàn),最終采用了基于進(jìn)程的方式來(lái)實(shí)現(xiàn)。

          實(shí)現(xiàn)

          基本的實(shí)現(xiàn)如下:

          用戶發(fā)起 HTTP 請(qǐng)求,Node 主進(jìn)程去數(shù)據(jù)庫(kù)讀取該請(qǐng)求的函數(shù)實(shí)現(xiàn),拿到函數(shù)實(shí)現(xiàn)后會(huì) Fork 一個(gè)子進(jìn)程執(zhí)行函數(shù),函數(shù)執(zhí)行完后子進(jìn)程銷毀。這里需要注意的一點(diǎn)是控制子進(jìn)程的執(zhí)行時(shí)間,防止因?yàn)楹瘮?shù)執(zhí)行異常,導(dǎo)致子進(jìn)程無(wú)法銷毀。我們?cè)诳聪聢?zhí)行函數(shù)的具體實(shí)現(xiàn):

          通過 VM2 模塊來(lái)執(zhí)行我們的云函數(shù),從而保證子進(jìn)程和主進(jìn)程之間的 Context 隔離,如果不進(jìn)行隔離,有可能出現(xiàn)的一種情況是,子進(jìn)程里面如果調(diào)用了 process.exit(),此時(shí)我們的 Node 主進(jìn)程就會(huì)被退出去。

          做了進(jìn)程的 Context 隔離還不夠,我們可以利用進(jìn)程池來(lái)優(yōu)化每次 Fork 子進(jìn)程的時(shí)間,利用 CGroup 來(lái)限制子進(jìn)程的 CPU 使用率、內(nèi)存占用、磁盤IO等。CGroup 是 Linux 內(nèi)核中的一個(gè)核心能力,提供了將不同進(jìn)程按分組進(jìn)行管理的能力,并且能對(duì)不同的分組限制其所使用的計(jì)算資源(CPU、內(nèi)存、磁盤IO等),我們可以通過限制用來(lái)執(zhí)行函數(shù)的子進(jìn)程所能消耗的最大內(nèi)存、磁盤及網(wǎng)絡(luò)帶寬,同時(shí)控制進(jìn)程所能使用的最大 CPU 占用率等方式來(lái)保證系統(tǒng)的穩(wěn)定性。最終的實(shí)現(xiàn)如下:

          以上就是基于 Serverless 的 BFF 改造的核心內(nèi)容,相比于一代的 BFF 架構(gòu),基于 Serverless 的BFF改造有以下幾點(diǎn)優(yōu)勢(shì):

          • 效率提升:獨(dú)立云函數(shù),動(dòng)態(tài)編寫,秒級(jí)部署。
          • 降本:應(yīng)用收斂,有效降低運(yùn)維、機(jī)器成本。

          總結(jié)

          以上就是平臺(tái)前端本次分享的主要內(nèi)容,我們做下總結(jié):

          后端領(lǐng)域微服務(wù)化后,需要一套能提供業(yè)務(wù)編排、字段轉(zhuǎn)換、個(gè)性定制的機(jī)制來(lái)保證業(yè)務(wù)的快速迭代。BFF 架構(gòu)能夠有效的做到業(yè)務(wù)編排、字段轉(zhuǎn)換、個(gè)性定制,且讓前端進(jìn)入全棧領(lǐng)域。構(gòu)建于 Serverless 之上的 BFF 進(jìn)一步的降低了運(yùn)維、機(jī)器成本,提高了人效。

          Node 社群


          我組建了一個(gè)氛圍特別好的 Node.js 社群,里面有很多 Node.js小伙伴,如果你對(duì)Node.js學(xué)習(xí)感興趣的話(后續(xù)有計(jì)劃也可以),我們可以一起進(jìn)行Node.js相關(guān)的交流、學(xué)習(xí)、共建。下方加 考拉 好友回復(fù)「Node」即可。


             “分享、點(diǎn)贊、在看” 支持一波 

          瀏覽 109
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲综合精品在线 | 午夜试看120秒体验区的特点 | 伊人久久免费 | 日韩国产在线一区 | 五月激情啪啪 |