NGW,前端新技術賽場:Serverless SSR 技術內幕

blank

NGW,前端新技術賽場:Serverless SSR 技術內幕

騰訊IVWeb team(負責騰訊互動視頻NOW 直播、花樣直播等產品) 經驗分享~

▎目錄:

  1. 前言
  2. Serverless 的演進
  3. 雲函數SCF 的開發
  4. NGW Serverless 同構直出方案

前言

最近Serverless 又火了,有不少業務上雲實裝了Serverless 雲函數,取得了不錯的落地效果,業界也在不斷探索Serverless 更多的落地場景。

那麼對於前端來說,Serverless 意味著什麼?對於Node 服務來說,哪裡可以落地Serverless?

答: Serverless同構直出渲染。

Serverless + SSR = ?

Serverless 雲函數:雲計算發展過程中出現的一種計算資源的抽象,它以雲計算平台為基礎,為開發者提供業務程序的運行環境,開發者無需關注底層資源分配、擴容部署,代碼執行所必要的全部服務由平台提供。

SSR 服務端渲染: 指在服務端將HTML 渲染到前端,早期常用php jsp 技術來在服務端生成HTML,近年來JS 同構化趨勢演進下,逐步出現了在服務端上運行前端JS 代碼進行渲染的方案,如React、Vue 等主流框架的同構渲染。

若能將Serverless 技術落地到SSR 場景,將會有如下優點:

  1. 雲服務資源理論上無限擴容,前端不必考慮業務量對SSR 機器性能的影響
  2. 前端同學無需關注SSR 機器的運維、申請、擴容,減少部署運維成本,提高開發效率

目前騰訊NOW 直播IVWEB 團隊正逐步將SSR 業務遷移到騰訊云云函數平台上,精簡部署運維成本。

Serverless的演進

阿J 是一個前端開發仔,某天產品跟他說頁面白屏加載接口的時間太長了,體驗差,這對於優秀的前端開發仔的他並不是難事,他有99 種讓頁面加載變快的辦法。

因此他立馬將利用團隊直出框架,花了半天時間將頁面接入了直出,接下來要將直出服務部署到現網,這時他犯難了:

  1. 部署直出服務需要申請機器,申請多少台,申請幾核的?
  2. 這個業務量怎麼樣,有沒有高並發場景,機器有沒有擴容機制?
  3. Nginx 配置怎麼改才能接入直出,直出失敗的話又要怎麼接入兜底的靜態頁面?

一頭霧水之時,他看見騰訊雲的同事maxlong 關於Serverless 架構演進的PPT….

從IaaS到FaaS

在介紹雲函數SCF 之前,我們先來diff 一下傳統IaaS 業務架構和雲函數FaaS 業務架構:

blank
基於虛擬機的業務架構(IaaS)

而云函數架構是這樣的:

blank
基於雲函數的業務架構(FaaS)

阿J 對比了兩者架構之後發現,在基於雲函數的業務架構下,開發者無需再關注業務基礎層的相關配置,可以集中精力處理業務邏輯的開發,基礎層由平台負責維護迭代,只要將我們的直出服務部署上雲就可以解決部署直出業務中的運維痛點了。

FaaS + BaaS下的Serverless

FaaS的出現使得服務上雲變得容易起來,但是FaaS並沒有解決「公共基礎服務」的問題,而所謂公共基礎服務,就是形如對象存儲、KV存儲、消息推送這樣的基礎服務,這個問題最終落到了雲服務提供商這裡。

因此市面上的雲服務無一例外的都提供了上面的「公共基礎服務」,這樣的服務模式叫做BaaS(Backend as a Service)。

Serverless 直譯過來叫無服務器,這裡並不是說不需要服務器,而是說開發者不需要關注服務器,這部分由平台維護提供,開發者僅需關注業務邏輯的開發即可。

blank
Serverless 架構下的App

在這樣的一種架構下,開發者無須關注支撐應用服務運行的底層資源,以「函數」的形式承載業務邏輯,以「BaaS 服務」的形式支撐公共服務。

blank
公有云基礎設施上的Serverless 演進

考慮到直出服務的特性,阿J 認為直出業務十分適合上Serverless,因此他立馬開始了直出上雲的預研,做Serveless SSR 服務,免去運維部署煩惱,減少直出接入成本!

SCF雲函數開發

阿J 認真研究了騰訊云云函數(Serverless Cloud Function,SCF),發現它可以將我們的業務拆成更細的粒度「函數」,而函數的執行環境開發者不需要關注,由平台負責,以下是阿J 對雲函數執行的理解。

雲函數執行過程

雲平台在執行這些「雲函數」的過程其實就是在對外提供服務,通常情況下,Serverless 函數會用於「響應HTTP 請求」,即通過HTTP 訪問事件來觸發雲函數的執行,如下圖所示:

blank
雲函數用戶請求鏈路

而「函數的執行」不外乎:入參、上下文、返回值、副作用四個要素,如圖所示:

blank
函數執行的四個要素

四要素:

  1. 「入參」: 雲函數的入參即HTTP 請求中的請求頭、請求體
  2. 「上下文」: 包含此次函數請求的id、函數執行的環境變量等等
  3. 「副作用」: 雲函數執行可能調用外部服務,如數據庫、對象存儲、數據監控
  4. 「返回值」: 即HTTP 響應如{retcode:0,msg:"ok"}

阿J 還了解到根據一定配置部署完雲函數之後,雲平台會給你一個URL,通過訪問這個URL 就可以「觸發」對應云函數的執行,得到結果。

NGW Serverless同構直出方案

正當阿J 著手進行Serverless 直出開發的時候,他猛然發現,Serverless 環境下跟原有的直出環境有較大出入,原有的直出環境是這樣的:

  1. 原方案直出是使用TSW 執行Koa App 的方式進行直出的,這意味著原方案需要監聽端口而不是作為函數來運行,這個要怎麼處理?
  2. 老業務能不能做到無縫遷移到雲函數?能不能做到新直出方案兼容老直出方案?
  3. 雲函數怎麼做到工程化打包發布,接入到團隊現有的CI 流程中?
  4. 原方案可以做本地調試,而云函數直出怎麼做本地調試?
  5. 雲函數發布後,會得到一個URL,那麼這個URL 要怎麼接入我們的業務域名下?

工程化打包

除去前端webpack 打包之外,對於Serverless 雲函數平台,我們還得在原來的打包產物基礎上再做一些操作,其核心在於「打包為zip 上傳到雲函數」,如下圖所示:

blank
雲函數打包圖示

從圖示中可以看到,打包部署的流程由「CLI 工具」承擔,原因是為了提供命令式的部署原語,方便CI 接入。

Serverless下的同構環境

阿J 考慮到原先業務的直出方案採用TSW 來做,但是在Serverless 下,我們不能把TSW 搬進云函數里執行,而是抽取了其中我們需要的組件出來,如ajax 發送請求、監控上報、日誌logger 等常用組件,因為:

  • 方便老業務無縫遷移到雲函數直出,解決直出業務的運維痛點
  • TSW 很大,壓縮後近20 MB,解壓出來大很多,不利於雲函數的性能

除此之外,還要自己去實現window.REQUEST plug 類似這樣的TSW 全局注入的對象,因為舊有方案也依賴這些全局對象。

「流式」和「塊式」

原來的方案需要Koa 監聽本地端口才能提供服務,而云函數的出入參是塊式的,Koa 的出入參是流式的,因此這裡需要處理一下云函數的入參。阿J 的做法是根據云函數入參來動態構造http 的IncomingMessage 和ServerResponse 的實例,然後透傳給app.callback() 進行直出渲染,最後從ServerResponse 裡取得渲染結果構造為雲函數返回值返回。

NGW作網關轉發

阿J 考慮到業務的可用性以及之前鏈路接入的痛苦,決定接入NGW(Node Gateway):

blank
NGW 下的Serverless 直出鏈路

通過NGW 可以做到:

  1. 實現兜底邏輯: 雲函數可能會crash,這時候走靜態頁面接入機
  2. 灰度邏輯: 直出上現網的過程中可以通過NGW 的配置進行部分灰度測試
  3. 鏈路日誌收歸: 長期以來,前端不好查具體的鏈路訊息,現在有了NGW 一切皆有可能

雲函數本地調試

雲函數的無狀態模型使得其非常易於進行本地調試,我們只需要在本地構造函數的入參、上下文即可直接進行直出調試了,阿J 在實際實現中是通過本地起一個Koa 服務監聽端口,利用這個端口的請求來構造入參、上下文,最後傳入函數執行結果,返回到前端顯示。

同構直出過程

在最後,阿J 完成了Serverless 直出方案,其直出過程如下圖所示:

blank
新方案下的同構直出三步
  • 「Init」: 初始化雲函數環境、接受並處理雲函數的入參
  • 「Koa」: React 同構業務邏輯以Koa App 的形式體現
  • 「Clear」: 清理雲函數環境、處理Koa Response 返回直出結果

特別需要提出的一點是,其中的Koa 其實就是原方案的打包結果,新方案在此基礎上作了一些環境遷移、重寫,使其可以在雲函數環境下執行渲染。

雲函數的性能瓶頸和優化

阿J 在完成了新直出方案之後馬上進行了壓測,發現隨著壓測壓力的增加,收包率會出現斷崖式下跌,而且還發現部分函數執行耗費時間非常長,聯繫了雲函數的同事看了下發現是「冷啟動問題」,那什麼是冷啟動?

從雲函數的架構中可以看到,雲函數觸發後並不是馬上執行,它需要一個環境初始化的過程,這種啟動叫做冷啟動;還有種情況是,這次請求的函數執行之後馬上接到下一次請求,這時候就不用重新初始化雲函數環境,而是直接啟動,這種稱謂熱啟動。

blank
壓測雲函數執行時間分佈圖
blank
收包率優化前後(右邊為優化後)

冷啟動問題在壓力低的情況下不明顯,但是在高並發的情況下就會額外影響回包了,這裡SCF 的同事進行了優化:提高最小實例數,減少冷啟動,最小實例越多就越能扛住瞬時並發,優化效果如上圖右邊所示。

此外我們還發現了內存的問題,這里聯係了SCF 的同事進行了Node 內存模型的相關優化,優化後,已基本不存在4xx 的問題。

(業務中的內存使用也可以進行優化,要避免JS 內存洩漏)

blank
內存超限導致4xx 問題,壓測壓力越大越多這種錯誤
blank
內存模型優化後的表現

到這一步,阿J 終於初步完成了Serverless 直出方案設計開發,並開始逐步在業務中使用推廣。

現狀和下一步計劃

blank

目前NGW + Serverless SSR 已經應用到NOW 直播、手Q 附近、瀏覽器直播和手Q 群送禮等多個項目中,實際業務開發中,Node 業務的部署和運維工作量降低了80% 以上。

阿J 下一步的計劃:

  1. 完善的雲函數版本管理;
  2. 配合webpack 進一步優化本地直出調試體驗;
  3. 配合騰訊云同事進一步優化雲函數性能;
  4. 完善React Chunked 流式渲染方案,進一步提升首屏加載速度;
  5. 完善Node 服務雲函數,計劃做前端BFF 方案;
  6. 完善直出和鏈路日誌收歸,增強服務監控能力。

Serverless Framework 30 天試用計劃

我們誠邀您來體驗最便捷的Serverless 開發和部署方式。在試用期內,相關聯的產品及服務均提供免費資源和專業的技術支持,幫助您的業務快速、便捷地實現Serverless!

詳情可查閱: Serverless Framework試用計劃

One More Thing

3 秒你能做什麼?喝一口水,看一封郵件,還是——部署一個完整的Serverless應用?

複製鏈接至PC瀏覽器訪問: serverless.cloud.tencent.com

3秒極速部署,立即體驗史上最快的Serverless HTTP實戰開發!

傳送門:

歡迎訪問: Serverless中文網,您可以在最佳實踐裡體驗更多關於Serverless應用的開發!

What do you think?

Written by marketer

blank

聲明式UI框架在類小程序運行的原理

blank

知源· 致遠- AntV 11.22 年度發布