1. 程式人生 > 實用技巧 >基於 NodeJS 的 serverless 架構實踐

基於 NodeJS 的 serverless 架構實踐

通過將 BFF 構建於 serverless 之上,將人工智慧實驗室(天貓精靈)數十個中後臺應用整合到了一個統一入口。用雲函式的方式取代了傳統基於 Nodejs的 BFF 層,提供了在一個站點下不同應用以及不同環境的快速切換能力。從而極大程度的降低了開發成本和運維成本,使機器數量從 200 餘臺縮減為 10 臺,同時有效減少了業務方的學習和理解成本。

本文主要講述了 BFF 侷限性以及我們對應的 serverless 解決方案,其中平臺核心功能包括:

  • 雲函式:

    將 BFF 層的 Node 應用程式碼拆解成獨立雲函式,支援動態編寫、秒級部署,平臺提供隔離的沙箱容器進行執行,並自動接入日誌和監控系統,使開發者可實時掌握函式的執行狀況;

  • 應用:

    將各平臺的前端程式碼打包部署,入口路由進行統一註冊,我們將這些平臺稱為應用。

    這些應用將直接支援各環境切換及多套預發環境解決方案;

  • SDK:

    框架將集團中介軟體封裝為 BaaS SDK 供應用直接呼叫,提供一套統一的 API 抹平了 Web 和 Node 的差異;

  • CLI:

    提供命令列工具便於開發者可脫離 web 管理平臺,而直接快速進行開發、除錯和釋出。

BFF 的侷限

從傳統大型機到伺服器叢集,從虛擬技術到容器化,我們正在走向那些更加輕量、更俱靈活性的解決方案。

阿里各 BU,在“大中臺,小前臺”的大背景下,也逐漸從巨石應用拆分為了更為靈活的微服務,以便以更小的粒度服務於更多的需求方。

而前端也在以往前後端分離的基礎上,更進一步的演變為了 BFF 架構。根據最終端上的需求,通過 BFF 層將各個微服務進行聚合和裁剪後返回。根據”誰享受誰負責“原則,該 BFF 層通常由前端使用 Nodejs維護。

然而,作為橫向支撐的前端團隊,我們在實施 BFF 架構1年後,卻發現它可能並沒有想象的那麼美好。為什麼會這麼說?截止目前,我們大概有40個左右不同的平臺服務於我們的各個團隊(包括運營、市場、測試、工程、演算法、硬體和資料),對於大量的平臺的存在,對開發人員的維護和業務方的理解,都成為了一種負擔。

  • 首先,每個平臺都有一個對應的 Node 層來作為 BFF,我們仍然需要針對每一個平臺部署程式碼、安裝依賴的各種軟體,關心究竟需要多少臺伺服器,這極大的增加了我們的運維成本;

  • 其次,由於各個平臺十分分散,均由獨立域名進行訪問,不同團隊可能並不清楚已經存在一個類似平臺從而導致提出相似需求,並且各個平臺對於賬戶、許可權、檔案上傳等中介軟體都需進行接入,對開發資源造成嚴重浪費;

  • 最後,作為業務方,需要記住大量不同平臺域名和對應的功能,也成為了一項挑戰。

    而每個平臺還有對應還有多套環境,其也增加了他們的溝通成本和使用成本。

所以,我們核心面臨的問題總結起來就是運維成本難降低、重複開發難避免、入口分散難管理。那麼有沒有一種更輕量的架構,使我們所有人能從上述這些繁瑣的工作中解放出來?

我們想到了 serverless,它讓 NoOps 成為可能,實現零配置釋出業務程式碼,這能極大降低運維成本。但傳統的 serverless 仍然只能解決一個點的問題,如果我們做的更進一步,將 serverless 與已有的 BFF、FE 整合,那是不是有可能同時解決上述問題?基於上述思考,我們提出了自己的 serverless 架構。

在此之前,先介紹一下什麼是 serverless。

serverless

serverless 的定義如下

無伺服器架構是基於網際網路的系統,其中應用開發不使用常規的服務程序。相反,它們僅依賴於第三方服務,客戶端邏輯和服務託管遠端過程呼叫的組合。

目前我們說的 serverless,最常是指 Amazon 在 2014 年釋出的 AWS Lambda 服務,為在服務端中執行的程式提供了一種全新的架構。我們不需要在伺服器上持續執行程序以等待請求,而是可以通過某種事件機制來觸發容器從而動態的執行程式碼。

不需要再關心應該配置多少機器,需要預裝哪些依賴,這些統統由平臺搞定,而我們只需要維護一個功能的集合,這些功能以“函式”的方式被呼叫。這種模式我們通常也把它稱為 Faas(Function as a Services),一種比微服務粒度更小的程式碼組織方式。

關於 serverless 的介紹網上已有很多,具體可以從下面這篇文章開始,這裡不再進行贅述。

從IaaS到FaaS—— Serverless架構的前世今生

BFF in serverless

然而獨立的 FaaS 其實並不具備實用性,因為他是無狀態的,無法進行儲存意味著無法針對不同使用者提供服務。Amazon 的解決方案是讓 Lambda 打通 AWS 大量基礎服務,通過簡單的 API 呼叫,即可使用 S3、RDS 等儲存服務來儲存使用者資料。即使這樣,仍然有很多工作需要開發者完成。

我們結合的實際情況,在平臺中統一了 FE、BFF,並封裝了大量集團中介軟體,使其成為一體化解決方案,讓開發者僅需在一個平臺,即可完成應用的開發、除錯、構建和部署。

下面將詳細介紹平臺幾大核心功能及其背後的思考。

1. 雲函式

函式執行可以說是 serverless 架構的基礎,為此我們建立了一個獨立的 sandbox 模組來提供該功能的基礎環境。

其實現方式類似 egg 的 master/worker 模式。不同之處在於請求進來時,會根據 request 查詢到具體的程式碼片段,然後啟動 worker 程序來執行,最後將執行的結果 response 到客戶端,worker 再進行自銷燬。

這麼做的好處是我們可以針對任何一個函式進行監控和限制,瞭解和控制它的執行時長、記憶體佔用,防止惡意程式碼侵害公共環境,不同函式之間也不會造成相互干擾。

2. 開發者工作臺(應用)

維護一個統一的入口,是平臺其他功能能正常運轉的基石。通過系統釋出的所有平臺,均通過同一域名進入,在導航處提供了在不同平臺之間切換的功能,我們將這些平臺稱為”應用“。

這裡和“阿里內外工作臺”的實現方式略有不同,“工作臺”是通過統一門戶,再導航至不同二級域名,其每二級站點實際為獨立機器進行部署。而我們在不同應用之前的切換,只是同一域名下不同路由的切換,實際背後提供服務的都是同一個伺服器叢集。

這樣做的好處是一些業務無關的框架級功能可以在平臺上進行統一實現,比如後面提到的環境切換和多套預發環境管理。對於業務來說,需求方再也不需要記住不同平臺的各種域名,在任意平臺也實現了各平臺間的導航。

而開發者工作臺,提供了應用管理的所有功能,包括 BaaS 配置、函式釋出、監控日誌等,以滿足開發者的日常需求,並極大的改善開發者開發體驗。

3. 線上環境切換

利用統一入口的優勢,我們可以在線上、預發、日常之間實現無縫切換。然而由於阿里日常與線上的天然隔離,以及中介軟體的環境限制,我們並沒有辦法在線上環境的函式中,呼叫日常環境的 API 介面。為了實現各環境互通,我們在統一入口處增加了一層線上環境 Proxy。通過這層 Proxy,線上環境仍是正常訪問,而當訪問的是預發、日常的函式時,將通過 HTTP 的方式,到真正平臺對應環境的機器上再執行相應函式。

4. 多套預發環境管理

由於我們特殊情況,在預發部署了多套環境用於專案聯調,然而因為我們業務較為複雜,一套完整鏈路往往涉及100個左右的應用,因為別個專案的修改需要每個應用都進行部署顯然是不合理的。

那麼有沒有一種方式,只部署有修改的應用,而沒有修改的應用,當在該環境訪問時如果缺失,自動進入預設標準環境中,並且後續鏈路能維持這個邏輯呢?

我們通過在請求加入標誌位的方式,實現了實現這一需求。

5. BaaS SDK

如果 egg 沒有通過外掛化機制來支援集團的各種中介軟體,如果 AWS 只是單純的 serverless 而沒有與 S3、RDS 等服務打通,那麼其實很難規模化應用。

為了有效降低開發門檻和成本,我們建立了一套 Web 與 Node 端 API 基本一致的 SDK,使開發者在進行開發時,不必顯著的區分當前環境是在瀏覽器中還是在服務端中,從而有效降低學習成本。

下面舉個栗子:

//  初始化 app,只需執行一次
import genie from '@ali/cloud-genie';
const app = genie.initApp();

// 1.  雲函式呼叫
const { cf } = app.cf();
const data = await cf.invoke('functionName', params);

// 2. 根據花名查詢使用者資訊
const buc = app.buc();
const userInfo = await buc.getUserByNickNameCn('花名');

通過上述簡單的呼叫,即可實現呼叫集團包括 DB 在內的各個中介軟體及服務。

6. CLI

除此之外,我們還提供了一個 CLI工具,用於開發者快速的進行開發、除錯和釋出。

由於我們基於 serverless 架構,實際上在本地進行除錯已沒有太大必要,所以我們針對函式的除錯,實際上都是連線到日常或預發機器直接執行的,再將執行的結果同步會開發者的終端,開發者本地並不需要搭建 serverless 的執行環境。

廣州品牌設計公司https://www.houdianzi.com

More

雖然平臺已可完成基本開發,為了更好的支撐更多的業務,我們後面的計劃主要包括租戶隔離、多協議支援、視覺化編寫。

租戶隔離:目前平臺自帶 Portal,故只支援了天貓精靈相關需求在上面進行開發,租戶隔離期望實現不同 Portal 在資料上的隔離,以支援更多的業務線。

多協議支援:目前平臺只支援 HTTP 協議,後續將支援更多協議,以便於服務更多的業務場景。

視覺化編寫:目前平臺主要以 CLI 的方式編寫函式,但其實 BFF 層很多隻是簡單的聚合和裁剪,如果我們能通過視覺化的方式,選擇一些 API 進行聚合,再根據需求進行裁剪,那麼對於客戶端等其他同學將更加友好,進一步降低開發成本。

寫在最後

serverless 對業務開發者具有極大的友好性,使開發者不用瞭解應用伺服器如何配置、資料庫如何連結、訊息服務中介軟體如何搭建,不需瞭解到底需要多少臺伺服器才能支撐,尤其是針對前端開發人員,NoOps 的特性正好彌補了前端運維能力的短板,使其從前端到全棧的轉變提供了一個良好的平臺。

而 BFF in serverless 在 serverless 架構的基礎上,提供了一套完善的 BaaS SDK、監控日誌體系以及前端解決方案,從而更進一步降低了開發者門檻。