邊緣計算聽說過嗎?
前情
在開始正題之前,我先講一個內(nèi)容詳情的業(yè)務(wù)場景和其面臨的性能問題
業(yè)務(wù)特點
圖文內(nèi)容詳情業(yè)務(wù)本身有三個比較大的特點:
- 內(nèi)容量大,幾十億的內(nèi)容量,并且每天還在瘋狂增長;
- 流量大,為了支撐這么大的業(yè)務(wù),需要很多服務(wù)器成本;
- 內(nèi)容數(shù)據(jù)極具靜態(tài)化,頁面參考如下,除了藍色標識的數(shù)據(jù),其他數(shù)據(jù)很少會改動;
那我們看這么一個頁面的加載和渲染過程大概是什么樣的?
總結(jié)問題
從上面的流程可以看出幾個問題:
- 首屏渲染依賴多次請求,導(dǎo)致首屏渲染性能差,尤其是低端機
- 服務(wù)端壓力大,每次請求都需要請求到服務(wù)端,對服務(wù)器也會帶來非常大的壓力
- 內(nèi)容重復(fù)渲染,同樣一篇內(nèi)容每個人看到都一樣,但是渲染結(jié)果又無法共享
大膽思考
這時候我們要結(jié)合業(yè)務(wù)本身的特性進行一些大膽的思考:
研發(fā)時預(yù)渲染
首先想到的是在研發(fā)過程中就對內(nèi)容進行預(yù)渲染并存儲起來,但是這個方案很快被 pass 了,有兩個主要原因:
- 內(nèi)容量太大:內(nèi)容數(shù)量特別大,并且一篇內(nèi)容在不同的場景(上百)還會展示出不同的風(fēng)格,全部靜態(tài)化存儲 CDN 資源浪費嚴重
- 更新成本大:內(nèi)容會被達人修改,或者一些打擦邊球的內(nèi)容需要盡快下線
按需渲染結(jié)果靜態(tài)化
既然數(shù)據(jù)絕大部分是靜態(tài)化的,為什么不能把用戶訪問時靜態(tài)數(shù)據(jù)和代碼渲染后的結(jié)果進行靜態(tài)化,這樣不是省去了 renderToHTML 的過程了嗎?,如下圖所示
那講到這里,我們首先想到的是通過 SSR renderToHTMLString,然后把渲染后的結(jié)果進行緩存,這樣訪問到相同內(nèi)容的請求可以直接將緩存結(jié)果返回,那這樣有什么好處呢:
- 減少重復(fù)渲染,提升首屏性能
- 降低接口服務(wù)的壓力
- 基于訪問存儲,避免資源浪費
但是同時也帶來了其他的問題:
- SSR 應(yīng)用服務(wù)器距離用戶遠帶來的白屏?xí)r間延長
- SSR 本身的壓力也會提升,因為這樣意味著每一個用戶請求都要經(jīng)過 SSR(雖然可以走緩存)
- 緩存數(shù)據(jù)存儲的問題,存哪里,內(nèi)存肯定不滿足需求,因為剛開始就講到了內(nèi)容量特別大,這時候要借助于其他的一些快速存儲的云服務(wù),顯得特別復(fù)雜
這時候我們就在想,如果能夠?qū)秩镜慕Y(jié)果或者渲染的過程放在 CDN 上就好了,因為 CDN 節(jié)點比較多,并且在世界范圍部署廣泛,所以我們嘗試著將 SSR 渲染的結(jié)果存儲在 CDN 上,但是隨之帶來另外一些問題:
- SSR 服務(wù)器出錯了怎么辦,現(xiàn)在 CDN 是一種配置生效系統(tǒng),如下圖所示,我們上文說到了圖文詳情的流量特別大,這也就意味著各種異常情況都要考慮,像 SSR 服務(wù)器宕機帶來的風(fēng)險我們也必須有降級方案,保障不影響用戶
- 對于兩種特殊場景需要及時更新緩存:擦邊球內(nèi)容要能夠及時下線,頁面代碼更新要能夠批量更新緩存,目前通過 CDN 的配置項是解決不了這些問題的
這時我們正好了解到了 CDN 正在推廣一種邊緣計算的能力(EdgeRoutine,下面會做簡單的介紹),簡單點理解就是可以在 CDN 請求返回結(jié)果之前加上你的自定義腳本,并且可以訪問 CDN 的數(shù)據(jù),那就意味著我們可以控制 CDN 請求返回的內(nèi)容或者HTTP 狀態(tài),好像基本能夠解決我上面說的兩個問題,所以按照當(dāng)前的技術(shù)能力和我們的需求我們針對請求鏈路進行了改造:
具體的降級和緩存清除的邏輯沒有畫出來,因為那是解決安全生產(chǎn)的問題,我主要想強調(diào)方案調(diào)整帶來的性能提升。
所以從上圖可以看出,一個正常的請求首先會請求到 CDN,CDN 如果發(fā)現(xiàn)緩存中沒有的話會回源到 SSR 服務(wù)器,這樣首屏其實只需要一個網(wǎng)絡(luò)請求,有效的提升的首屏性能和降低了服務(wù)器壓力。細心的你會發(fā)現(xiàn)頁面首屏后還進行了一次請求動態(tài)數(shù)據(jù)的動作,因為還有一個對實時性要求比較高的數(shù)據(jù)需要展示給用戶,但是并不影響用戶瀏覽,另外雖然內(nèi)容不怎么會更新但也會存在更新的情況,所以我們會在瀏覽器端做一次緩存的時間和內(nèi)容最新更新時間的對比,如果發(fā)現(xiàn)不一致,會主動做緩存更新,這樣,既保證了性能,又避免了緩存過期
收益
通過做如上的方案我們在性能,業(yè)務(wù)指標提升,服務(wù)器壓力上都有很大的收獲
性能提升明顯,低端機首屏 1S 內(nèi)
業(yè)務(wù)指標提升明顯
服務(wù)器壓力降低 80%
邊緣計算 ER
關(guān)于邊緣計算,大家可以參考:developer.aliyun.com/article/757…
本篇文章貼出幾張核心的圖供大家參考:
簡單總結(jié)就是我們可以在 CDN 返回結(jié)果之前進行一些邏輯計算,并且這部分代碼兼容 ES6 的規(guī)范,并且可以通過 HTTP 和外界服務(wù)進行溝通,達到有效的控制的 CDN 返回的表現(xiàn)的目的
優(yōu)勢-共享
在此我想重點介紹下邊緣計算的共享優(yōu)勢,對于邊緣計算來說,它不僅可以處理一些邏輯計算,還可以將計算的結(jié)果進行存儲,存儲能力是 Swift 的 Open API ,實現(xiàn)數(shù)據(jù)的 KV 存儲,這就意味著,這個存儲空間可以非常大。說道這里大家可能會感覺比較抽象,可以看下面這張圖,上面是指我們正常的網(wǎng)絡(luò)請求,用戶手機直連數(shù)據(jù)服務(wù)器和頁面 CDN,這就意味每個人都要經(jīng)歷加載頁面,加載數(shù)據(jù),渲染頁面等邏輯。下面是指 CDN ER 做了一層代理,這就意味著用戶手機鏈接 CDN,CDN 負責(zé)和數(shù)據(jù)服務(wù)器和頁面 CDN 進行溝通。那樣這樣有什么好處呢,這就意味著我們可以將像內(nèi)容詳情這種數(shù)據(jù)或者渲染的結(jié)果直接存儲在 CDN 上,并且不用擔(dān)心存儲內(nèi)容太多影響性能,這就就像一群人公用一部手機,你看完傳遞給下一個人刷新看相同的內(nèi)容
優(yōu)勢-計算能力
既然能在 CDN 的 ER 節(jié)點上寫 ES6 的代碼,并且可以請求數(shù)據(jù),這就意味著我們可以在ER上執(zhí)行很多邏輯,在這里我整理一些常用的:
那基于這些能力我們還能支持哪些合適的場景落地呢,所以我們針對淘系的場景進行了調(diào)研
場景調(diào)研
整體調(diào)研有一個統(tǒng)一的思路,就是要找適合靜態(tài)化的高流量場景,就是說頁面是否有可被緩存的數(shù)據(jù)或者渲染結(jié)果,為此我們整理了一個簡單的表格:
接下來我做一些簡單的說明:
- 末端類型的頁面一般是有內(nèi)容主體,并且這些主體數(shù)據(jù)不是千人千面的,例如上圖提到的,內(nèi)容詳情、商品詳情、個人主頁、評論列表、評論詳情
- 搭建類業(yè)務(wù),配置信息目前需要異步加載,模塊還要異步加載,這些配置化的東西是否可以直接和頁面一起輸出
- 榜單類型的頁面,同樣的一個榜單,每個人看到的都一樣,但是榜單要更新,但是這個更新并非真正的實時,一般為了承載更大的流量,數(shù)據(jù)都是準實時,例如分鐘級更新,小時級更新,甚至一天更新一次,那在有效期內(nèi)其實可以將榜單數(shù)據(jù)或者榜單的渲染結(jié)果緩存起來的
總結(jié)一下標準的頁面請求過程如下:
這里說一下,其實在數(shù)據(jù)側(cè)有很多靜態(tài)化策略已經(jīng)被用的游刃有余,例如借助于 CDN、Tair、OSS,如果我們能夠讓靜態(tài)化的過程變得更加簡單和通用,例如將數(shù)據(jù)或者頁面渲染結(jié)果直接存儲在 CDN,下次請求就可以直接復(fù)用渲染結(jié)果,有沒有可能變成如下模式:
其實就是兩個原則:
- 減少 HTTP 請求次數(shù),盡可能一次請求出首屏;
- 復(fù)用渲染結(jié)果:將渲染過程放在 ER 上并緩存下來,直接復(fù)用渲染結(jié)果,或者針對我們常用的骨架圖方案,是否能夠換成靜態(tài)數(shù)據(jù)的渲染結(jié)果;
場景標準化
最終結(jié)合 ER 的能力和我們的業(yè)務(wù)場景,我們抽象為以下四種:
- SSR 靜態(tài)化:指快速將 SSR 的結(jié)果緩存在 CDN 上
- ESR(Edge Side Render):顧名思義,將 renderToHTMLString 的過程放在 ER 節(jié)點上,并且緩存渲染結(jié)果
- 數(shù)據(jù)預(yù)請求:就是指將本來需要渲染后再請求數(shù)據(jù)的邏輯前置在 ER 上,將請求的結(jié)果合并返回給瀏覽器
- Redirect:重定向,是指在 ER 上根據(jù)邏輯實現(xiàn)重定向的能力,相對于以往我們前端通過制定 location.href 的方式要快很多了,這個可以滿足邏輯分流需求,例如 AB
- Include:片段注入,可以注入任何文字內(nèi)容到任意文件類型中,一種更加通用的方案
經(jīng)過我們的測試和實踐,針對前三種產(chǎn)出了一些性能報告也可以分享給大家,雖然不全面,但是能說明問題,由于測試的頁面場景不一樣,所以相互(數(shù)據(jù)預(yù)加載、 ESR、SSR 靜態(tài)化)沒有必要作對比,以下指標是相對沒有使用 TESI 的能力進行的對比
標準化接入
雖然 ER 有這么多優(yōu)勢,但是接入成本還是比較大的,例如要注意 ER 容器本身的各種限制、調(diào)試成本、云資源申請成本等,所以我們需要提供一種標準的接入方式,初步了解到 W3C 有一個 ESI 的標準,維基百科介紹如下:
簡單翻譯一下:ESI 是一種邊緣級 web 動態(tài)化的小型標記語言。ESI 的目的是解決 web 基礎(chǔ)設(shè)施的擴展問題。它是邊緣計算的一種應(yīng)用方案
原理如圖:
其實就是說,可以通過標簽注入的方式,實現(xiàn)動靜內(nèi)容混合混合輸出,比較符合我們的訴求,并且其在語法上也比較豐富
但問題是 ESI 是一種 XML 的標準,阿里有很多頁面資源類型并不是 HTML,例如 weex、小程序等等,它們加載的頁面并不是 HTML,并且我們要滿足標準化場景的接入,所以我們需要在 ESI 的基礎(chǔ)上進行改造-TESI(Taobao Edge Side Includes),合適的才是最好的
基本的代碼形式如何,我們以數(shù)據(jù)預(yù)加載為例,如下 H5 中出現(xiàn) TESI 標簽(鼠標選中部分)
TESI 標簽描述了一個 http 接口的信息,并且配置了其緩存時長 s-maxage,ER 會解析這個標簽,并且在 ER 上發(fā)起請求,并將請求的數(shù)據(jù)按照 s-maxage 配置的值進行緩存,這就意味著下一次請求到相同的節(jié)點,就會直接返回緩存結(jié)果
渲染結(jié)果如下:
我們看其實像數(shù)據(jù)預(yù)加載這種情況,在 HTML 中會渲染成一個 script 標簽,其中存儲的是一個全局變量方便運行時獲取。
其實 TESI 標簽不僅可以用于 HTML 中,JS 中可以出現(xiàn) TESI 標簽,如下:
渲染后
其基本渲染原理如下,比較簡單,這里不做贅余:
還有其他幾種類型的標簽如下:
標簽名 | 描述 |
tesi:data | 數(shù)據(jù)預(yù)加載 |
tesi:esr | 邊緣渲染 |
tesi:ssr | SSR 靜態(tài)化 |
tesi:redirect | 邏輯跳轉(zhuǎn) |
tesi:include | 區(qū)塊引入 |
穩(wěn)定降級
整個 ER 執(zhí)行的過程會遇到各種各樣的問題,甚至 ER 都有掛掉的風(fēng)險,所以需要有穩(wěn)定降級的預(yù)案保證不影響用戶,所以我們會將 CDN 源站指向頁面 CDN 的源站,這樣,及時 ER 解析出現(xiàn)問題,可以把解析前的頁面直接返回給瀏覽器
緩存管理
存儲
ER 提供了兩種緩存:內(nèi)存緩存(以下簡稱 Cache)和 Swift KV 緩存(以下簡稱 KV),這兩種模式在存取速度、體積大小、QPS 上都有差別,總結(jié)基本如下:
指標 | VS | 勝出 |
存儲空間 | Cache ﹤ KV | KV,可達 幾十 GB |
QPS | Cache ﹥ KV | Cache |
存取速度 | Cache ﹥ KV | Cache |
存儲副作用 | Cache ﹥ KV | KV |
這里指的存儲副作用是指,存儲大小對于 ER 性能的影響,存儲在緩存中,如果存儲體積接近內(nèi)存大小,首先會影響 ER 執(zhí)行性能,嚴重會導(dǎo)致 ER 容器重啟
綜合以上兩種對比結(jié)果來看各有千秋,但合適的場景用合適的模式才是最好,為此我們設(shè)計了二級緩存模式,一級緩存存入內(nèi)存,二級緩存存入 KV,主要完成如下三個重點邏輯:
- 動態(tài)計算熱度內(nèi)容推入一級緩存
- 采用 LRU(最近最久未使用算法)的模式實現(xiàn)一級緩存和二級緩存的數(shù)據(jù)推出,充分利用緩存空間
- 每一個標簽設(shè)定指定的緩存空間,避免緩存分配不均,導(dǎo)致相互影響
緩存失效
緩存的內(nèi)容需要具備快速清除的能力,因為數(shù)據(jù)會更新、頁面 bundle 會更新,特別是遇到緊急情況,例如線上問題緊急修復(fù),需要能夠?qū)崿F(xiàn)緩存及時清除,所以需要一定的策略來滿足需求,總體清除的邏輯會依賴請求,根據(jù)標簽的身份信息進行清除
接入過程
為了滿足系統(tǒng)穩(wěn)定性和安全生產(chǎn)的要求,TESI 標簽的生產(chǎn)過程是需要被管控起來的,所以我們要提供一個 TESI 的運維系統(tǒng)主要滿足以下幾個需求:
運維系統(tǒng)使用過程如下:
運維系統(tǒng)主要為了生成一個可用的 TESI 標簽,真正發(fā)布生效我們會借助于 DEF 發(fā)布系統(tǒng),這樣既沿用了標準,安全生產(chǎn)相關(guān)能力我們也不用重復(fù)建設(shè)了,基本流程如下:
附錄
名詞介紹:
- ER:EdgeRoutine
- ESR: Edge Side Render
- SSR: Server Side Render
- ESI: Edge Side Includes
- TESI: Taobao Edge Side Includes
- DEF: 阿里前端發(fā)布系統(tǒng)
- Swift:阿里云 CDN 文件存儲
幾種常用服務(wù)類型簡介:
其基本的配置信息和執(zhí)行過程如下,大家可以參考下:
作者:淘系前端團隊FED
鏈接:https://juejin.im/post/5ecf90b7f265da76e7651a96
來源:掘金
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。
寬泛科技專注為人工智能、邊緣計算、影視后期、動漫設(shè)計、商務(wù)應(yīng)用等領(lǐng)域,
提供基于人臉識別、深度學(xué)習(xí)、視覺計算、VR/AR/MR、桌面虛擬化、
數(shù)據(jù)存儲及數(shù)據(jù)可視化、視訊會議等信息化解決方案及服務(wù)。
如果您有合作需求或?qū)氋F建議,歡迎來信。
郵箱:hezuo@kuanfans.com
合作熱線:(021) 5415 5559