先說明一下背景。php
Serverless 雲函數: 雲計算髮展過程當中出現的一種計算資源的抽象,它以雲計算平臺爲基礎,爲開發者提供業務程序的運行環境,開發者無需關注底層資源分配、擴容部署,代碼執行所必要的所有服務由平臺提供。 SSR 服務端渲染: 指在服務端將 HTML 渲染到前端,早期經常使用 php jsp 技術來在服務端生成 HTML,近年來 js 同構化趨勢演進下,逐步出現了在服務端上運行前端 js 代碼進行渲染的方案,如 React、Vue 等主流框架的同構渲染。前端
若能將 Serverless 技術落地到 SSR 業務場景,將會有以下優勢webpack
目前 NOW 直播 IVWEB 團隊正逐步將 SSR 業務遷移到騰訊云云函數平臺上,精簡部署運維成本,響應公司自研上雲號召。nginx
阿 J 是一個前端開發仔,某天產品跟他說頁面白屏加載接口的時間太長了,體驗差,這對於優秀的前端開發仔的他並非難事,他有 99 種讓頁面加載變快的辦法,所以他立馬將利用項目中的團隊直出架構半天接入了直出,接下來要將直出服務部署到現網,這時他犯難了:git
- 部署直出服務須要申請機器,申請多少臺,申請幾核的?
- 這個業務量怎麼樣,有沒有突發請求,機器有沒有擴容機制?
- nginx 配置怎麼改,直出失敗的話要怎麼接入兜底的靜態頁面?
恍惚間,他看見騰訊雲的同事關於 Serverless 架構演進的 ppt ....github
在介紹 SCF 雲函數以前,咱們先來 diff 一下 傳統 IaaS 業務架構
和 雲函數 FaaS 業務架構
:web
而云函數架構是這樣的:ajax
阿 J 對比二者得出,在基於雲函數的業務架構下,開發者無需再關注業務基礎層的相關配置,能夠集中精力處理業務邏輯的開發,基礎層由平臺負責維護迭代,只要將咱們的直出服務部署上雲就能夠解決部署直出業務中的運維痛點了。數據庫
FaaS 的出現使得服務上雲變得容易起來,可是 FaaS 並無解決 「公共基礎服務」 的問題,而所謂公共基礎服務,就是形如對象存儲、KV存儲、消息推送這樣的基礎服務,這個問題最終落到了雲服務提供商這裏,所以市面上的雲服務無一例外的都提供了上面的「公共基礎服務」,這樣的服務模式叫作 BaaS(Backend as a Service)。瀏覽器
Serverless 直譯過來叫無服務器,這裏並非說不須要服務器,而是說開發者不須要關注服務器,這部分由平臺維護提供,開發者僅需關注業務邏輯的開發便可。
用戶無須關注支撐應用服務運行的底層資源,以「函數」的形式承載業務邏輯,以「BaaS 服務」的形式支撐公共服務。
考慮到直出服務的特性,阿 J 認爲直出業務十分適合上 Serverless,所以他立馬開始了前端上雲的預研,作 Serveless SSR 服務,免去運維部署煩惱,減小直出接入成本!
阿 J 認真研究了騰訊雲的雲函數(Serverless Cloud Function,SCF)發現雲函數它能夠將咱們的業務拆成更細的粒度「函數」,而函數的執行環境開發者不須要關注,由平臺負責,如下是阿 J 對雲函數執行的理解。
雲平臺在執行這些「雲函數」的過程其實就是在對外提供服務,一般狀況下,Serverless 函數會用於「響應 HTTP 請求」,即經過 HTTP 訪問事件來觸發雲函數的執行,以下圖所示:
而函數的執行不外乎:入參、上下文、返回值、反作用,如圖所示:
阿 J 還了解到根據必定配置部署完雲函數以後,雲平臺會給你一個**「Invoke URL」**,經過訪問這個 URL 就能夠觸發對應雲函數執行,獲得結果。
正當阿 J 着手進行 Serverless 直出開發的時候,他猛然發現,Serverless 環境下跟原有的直出環境有較大出入,原有的直出環境是這樣的:
除去前端 webpack 打包以外,對於 Serverless 雲函數平臺,咱們還得在原來的打包產物基礎上再作一些操做,其核心在於「打包爲 zip 上傳到雲函數」,以下圖所示:
在這裏須要引入一個 CLI 工具來打包 zip 和上傳雲函數,緣由是若是須要接入 CI 流程,就要提供命令式的部署來進行 CI 流程。
阿 J 考慮到原先業務的直出方案採用 TSW (github.com/tencent/tsw) 來作,可是在 Serverless 下,咱們不能把 TSW 搬進雲函數裏執行,而是抽取了其中咱們須要的組件出來,如 tsw ajax http、監控上報、tsw logger 等經常使用組件,由於:
除此以外,還要本身去實現 window.REQUEST plug 相似這樣的 TSW 全局注入的對象,由於舊有方案也有依賴這些。
原來的方案須要 Koa 監聽本地端口才能提供服務,而云函數的出入參是塊式的,Koa 的出入參是流式的,所以這裏須要處理一下雲函數的入參。阿 J 的作法是根據雲函數入參來動態構造 http 的 IncomingMessage 和 ServerResponse 而後透傳給 Koa App 進行直出渲染,最後從 ServerResponse 裏取得渲染結果構造爲雲函數返回值返回。
阿 J 考慮到業務的可用性以及以前鏈路接入的痛苦,決定接入 NGW(Node Gateway):
經過 NGW 能夠作到:
雲函數的無狀態模型使得其很是易於進行本地調試,咱們只須要在本地構造函數的入參、上下文便可直接進行直出調試了,阿 J 在實際實現中是經過本地起一個 Koa 服務監聽端口,利用這個端口的請求來構造入參、上下文,最後傳入函數執行結果,返回到前端顯示。
在最後,阿 J 完成了 Serverless 直出方案,其直出過程以下圖所示:
其中有三個核心步驟:
阿 J 在完成了新直出方案以後立刻進行了壓測,發現隨着壓測壓力的增長,收包率會出現斷崖式下跌,並且還發現部分函數執行耗費時間很是長,聯繫了雲函數的同事看了下發現是「冷啓動問題」,那什麼是冷啓動? 從雲函數的架構中能夠看到,雲函數觸發後並非立刻執行,它須要一個環境初始化的過程,這種啓動叫作冷啓動;還有種狀況是,此次請求的函數執行以後立刻接到下一次請求,這時候就不用從新初始化雲函數環境,而是直接啓動,這種稱謂熱啓動。
冷啓動問題在壓力低的狀況下不明顯,可是在高併發的狀況下就會額外影響回包了,這裏SCF 的同事進行了優化:提升最小實例數,減小冷啓動,最小實例越多就越能扛住瞬時併發。 此外咱們還發現了內存的問題,這裏聯繫了 SCF 的同事進行了 Node 內存模型的相關優化,優化後,已基本不存在 4xx 的問題。
到這一步,阿 J 終於初步完成了 Serverless 直出方案設計開發,並逐步在業務中使用推廣。
目前 NGW + Serverless SSR 已經應用到 NOW 直播、手 Q 附近、瀏覽器直播和手 Q 羣送禮等多個項目中,實際業務開發中,Node 業務的部署和運維工做量下降了 80% 以上。
阿 J 下一步的計劃:
關注【IVWEB社區】公衆號獲取每週最新文章,通往人生之巔!