前言
2022年1月,京東成為央視總檯2022年春節聯歡晚會獨家互動合作伙伴,雙方在紅包互動、電商等方面展開全方位深度合作。在除夕當天產生691億次互動,送出15億元紅包好物。
如何在這種大規模、高併發的場景下,確保系統的穩定性和效能,為使用者提供穩定流暢的互動體驗,成為了我們亟待解決的問題。
接下來我們主要從靜態資源最佳化、快取、容錯、工程化幾個方面來詳細介紹前端團隊所做的努力和創新。
靜態資源最佳化
首屏資源載入策略
在春晚主持人口播之後,大量使用者會集中在一段時間內湧入互動頁面,這會導致流量峰值。為了降低頁面開啟時的請求次數和資源體積,我們根據頁面互動,將所需資源分為三類:首屏、次屏以及操作後。
首屏資源主要包括:HTML文件、JavaScript、CSS以及樣式圖片。由於這是單頁面應用,我們可以透過常規技術將JS和CSS進行打包。對於樣式圖片,我們可以透過按需載入的方式,顯著減小首屏資源體積。
頁面包含兩個樓層,首屏的互動樓層和次屏的萬券齊發樓層。其中,首屏會展示兩排優惠券,因此,我們需要在首屏載入這部分券樓層的樣式圖片。互動主玩法中主要包括抽獎彈窗、邀人彈窗和擊鼓遊戲。透過拆分最佳化,首屏的樣式圖片體積減少約41%。再加上CDN
降質和WebP
引數的最佳化,樣式圖片的體積可以降低到178KB。
同時,我們將需要單獨載入的擊鼓遊戲精靈動畫圖從首屏載入清單中剝離,使得首屏樣式圖片的載入次數從2次減少到1次。這樣一來,使用者在開啟頁面時,所需的請求次數和資源體積都得到了顯著降低,進而提高了使用者體驗。
動畫圖片低損壓縮
動畫是頁面資源消耗的主要部分。在春晚頁面中,我們需平衡使用者互動體驗與資源最佳化。經過與設計和CDN
團隊多次溝通,我們決定採用技術手段降低資源消耗,同時保證使用者體驗。
首先是確定技術方案。設計團隊最初提議使用3D模型,需藉助WebGL
進行渲染。但這存在兩個問題:一是資源消耗大,3D模型通常包含3~4個檔案,首屏載入請求數增加;二是相容性問題,WebGL在低端機型上表現不佳。考慮到觀眾範圍廣泛,我們決定選用相容性更好的方案。
經過技術調研,我們最終確定採用幀動畫方案:設計團隊將3D動畫轉化為精靈圖,並將不變部分(如鼓架)單獨抽離。精靈圖僅包含運動部分(如鼓面敲擊動畫),有效降低資源消耗。
在確定方案後,設計團隊匯出了第一版資原始檔。然而,精靈圖大小為1236KB,主光效也有400KB,離我們的目標還有一定差距。經過雙方反覆嘗試,我們透過抽幀方式將擊鼓精靈圖從24幀降至4幀,大小從1236KB降至265KB。結合降質引數和WebP
格式,最終大小僅為78KB,下降了93%。此外,我們將主光效換成放大一倍的一倍圖,並透過CSS屬性scale實現放大,進一步節省資源。
雪碧圖方案的演進
元素背景圖使用雪碧圖模式,是前端基本最佳化手段,可以顯著降低請求次數。我們在首屏資源拆分後的情況下,可以將18個樣式背景圖合併成1個。相較於常規方案,春晚紅包還擴充套件了2個功能:
1、css雪碧圖在執行時為圖片URL新增CDN
降質引數和webp格式轉換引數(someimage.png!q70.webp),極限降低CDN頻寬。我們擴充套件開發了自動雪碧圖指令碼,可以支援自動生成2套background-image
樣式程式碼,分別對應普通圖片URL和帶!q70.webp的URL。透過執行時檢測webp支援特性,切換HTML標籤上的class名,來使對應的後代選擇器的background-image
屬性生效。對於webp
的特性檢測的技術方案,我們考慮過如下兩種方案:
a、透過版本判斷,從caniuse看,可以按照只有iOS14以下不支援webp來作為判斷依據。
b、透過建立一個Image物件,其src為一個基於base64的webp圖片,根據load是否成功來判斷是否支援webp。
比較這2個方案,方案a的優勢是透過UA判斷系統版本是同步執行的,可以在呼叫渲染頁面前的任意地方執行並修改HTML標籤的class屬性。確保內容渲染後有正確的背景圖css生效。不會對原有渲染邏輯產生入侵性修改。而方案b的優勢是經過大規模實踐,判斷邏輯的可靠性較高,缺點是非同步邏輯的,需要修改原來的渲染邏輯。由於我們這次需要支援全國億萬使用者,為確保穩定可靠,所以最終選擇方案b。
css檔案中的背景圖樣式,是在渲染相應DOM的時候才發起請求,又由於React渲染是同步的,我們需要調整執行render的時機,以確保在渲染頁面內容之前完成HTML的class屬性設定,避免請求兩次圖片。
2、動態雪碧圖。萬券齊發樓層首屏露出2排8個坑位,對應8次logo圖片請求,由於券和logo的資料是透過介面下發的,所以無法使用編譯時雪碧圖方案。為了將圖片請求次數減少到1次,我們和後臺、視覺、產品溝通後,設計了一套多團隊協作的方案。設計同學可以根據產品提前確認的券位置將logo圖合併成雪碧圖,並上傳到雲端儲存。展示如下:
雪碧圖規格確定後,透過固定的background-position
屬性,以及動態設定logo元素的className
和背景圖,即可實現動態雪碧圖。
自動衍生WebP背景圖css程式碼
上面提到執行時判斷是否使用webp背景圖,那對應的css程式碼就需要兩套,利用PostCSS外掛可以在編譯時自動基於原有背景圖樣式程式碼生成webp背景圖的程式碼,在緊張的開發過程中避免出錯和遺漏。透過使用PostCSS外掛中,CSS物件的walkDecls
方法,我們可以遍歷所有的background-image
屬性。然後,使用正規表示式匹配對應的樣式,在編譯打包時生成一套.webp .origin-class選擇器的樣式。在執行時,如果HTML標籤具有webp
屬性,系統將後代選擇器的樣式覆蓋原有樣式。
除了img標籤,我們在背景圖也進行了webp最佳化,使得全站圖片由902.4kb減小到512.6kb,經過多種流量和相容性測試效果表現良好。由此可見,在專案中大量使用圖片時,WebP
格式已成為一個不容忽視的效能最佳化關鍵。
降低伺服器成本及風險
春晚活動是一個典型的秒殺業務場景:隨著春晚主持人一聲令下,全國觀眾會同一時間湧入活動頁面,給介面帶來超高的流量壓力。下面將從流量削峰、降級處理兩個個方面介紹前端如何與後臺合作應對這類高併發場景。
流量削峰
在高併發場景下,流量削峰有助於系統平穩度過流量高峰。本次活動中,初始化介面和擊鼓抽獎介面流量最大,因此我們主要針對這兩個介面進行削峰。
1.初始化介面:在頁面載入之前,即資源位入口,配置一個“載入中”頁面連結。這個頁面隨機載入1-3秒後跳轉到活動頁面。當流量超過系統承載能力時,開啟灰度開關,部分使用者進入此頁面,然後等待幾秒後進入活動頁面。
2.擊鼓抽獎介面:本次活動的核心玩法介面。如果僅僅是簡單地隨機延時幾秒請求,會極大地影響使用者體驗。我們採用更精細化的處理方式。已知擊鼓互動在使用者敲擊滿次數或倒數計時結束時觸發抽獎介面,因此,隨機設定敲鼓次數,將原本集中在1-2秒內的請求打散至10秒區間,使用者幾乎無感知。
即時狀態的本地儲存
針對使用者優惠券領取狀態的儲存問題,權衡了多種因素,如活動規模、伺服器端壓力和活動持續時長等。最終,我們決定採用前端本地快取來儲存使用者領券狀態,從而提升效能並最佳化使用者體驗。
我們對比了前端常用的本地儲存機制,如cookie
、localStorage
和sessionStorage
。然而,這些機制各有優缺點:
1.cookie
儲存空間較小(4K),且在與服務端通訊時會佔用請求頭部,可能導致請求頭過大,超過服務端設定的最大值,進而引發報錯,並增加不必要的網路消耗。
2.sessionStorage
生命週期較短,僅適用於會話期間。
綜合考慮後,我們選擇了localStorage
作為最佳化方案。它具有較長的生命週期和較大的儲存空間(2.5M-4M),能滿足業務需求。採用localStorage
快取資料,不僅可以簡化呼叫鏈路、降低風險和節約成本,還能直接從本地讀取券的領取狀態,避免網路延遲導致的響應時間過長,提升使用者體驗。
工程化
為了使業務開發人員能更專注於自身業務開發,我們將手機相容性、裝置分級、環境判斷、自動合成雪碧圖、自動圖片壓縮、自動上傳雲端儲存、合併程式碼檔案等通用解決方案統一納入工程化層面處理。
透過工程化,可以最大程度的釋放生產力和創造力。上述的各種前端各種最佳化方案,離不開工程化的助力,與此同時保證了在快速開發交付的效率和穩定性。
提供擬真的MOCK
環境
我們搭建了一個擬真的MOCK
環境,以在短時間內模擬所需場景,確保在任意場景下都能提供友好互動。該環境1:1還原了服務端的MOCK
環境,能快速模擬正常資料,同時還能模擬請求超時、HTTP狀態碼異常、資料結構異常、非常規業務異常碼等場景。在ajax模組中,我們採用透明轉發方式,降低業務開發同學創作mock資料的成本,避免mock資料進入生產環境。如圖所示,MOCK
開發環境與聯調開發環境對比,可以看出mock環境對業務開發來說是透明且無副作用的,同時又能快速MOCK
資料。
編寫穩定高效的釋出指令碼
春晚參與使用者的裝置種類繁多,我們需在不同裝置上實現極致體驗,同時減輕CDN
過高QPS
的壓力。為此,我們與客戶端團隊聯合,根據不同裝置的不同版本,提供了內建包、離線包和線上CDN
包等多套環境。結合多輪內測和公測,在短短27天內,需部署10多套環境。線上環境部署錯綜複雜,還包括資源收集和大小計算等工作。若採用人工方式,極易出現誤操作,帶來不良後果。幸運的是,專案初期便引入了環境變數,透過環境變數解決不同環境間的差異。此外,在編譯前後加入了一系列指令碼,替代人工複製上傳、資源收集、大小計算等操作,避免人工操作失誤,提高穩定性,確保每個環境穩定部署。
工程化的目標,始終是提升開發效率,降低開發難度,分離關注點,讓業務研發同學更專注於自身業務的開發。
容災
作為一檔全球直播節目,現場不免會出現各種狀況,需要做好各種緊急預案。降級處理分為主動降級和被動降級兩類:
1.主動降級:各個資源位和互動按鈕上新增降級開關,上游介面或下游頁面出現緊急情況時,可透過配置CMS快速開啟降級開關。
2.被動降級:透過不同樣式和文案提示區分各類介面異常碼及系統環境,快速定位問題原因。這樣一來,客服同學可以第一時間安撫客戶,並提供相應處理方案。
總結
2022年央視春晚互動專案是一次大規模、高併發的挑戰,前端團隊透過靜態資源最佳化、快取、容錯和工程化等方面的努力和創新,確保了系統的穩定性和效能,為使用者提供了一個穩定流暢的互動體驗。在靜態資源最佳化方面,團隊透過首屏資源拆分、幀動畫方案替代3D模型、動態雪碧圖和WebP
格式最佳化等技術手段,顯著降低了資源消耗和請求次數。在降低伺服器成本及風險方面,選擇localStorage
作為非常規最佳化方案,提升使用者體驗。在容錯方面,流量削峰和降級處理,確保系統穩定執行。在工程化方面,統一處理通用解決方案、提供擬真的MOCK
環境和編寫穩定高效的釋出指令碼,降低開發難度,確保每個環境穩定部署。透過這些技術手段和創新,前端團隊成功應對了春晚互動專案帶來的技術難題,為使用者提供了一個穩定流暢的互動體驗。
作者:京東零售 趙越
來源:京東雲開發者社群 轉載請註明來源