[转载] 全方位提升网站打开速度:前端、后端、新的技术
- 原文地址:Building a Shop with Sub-Second Page Loads: Lessons Learned
- 原文作者:Erik Witt
- 譯文出自:掘金翻譯計(jì)劃
- 譯者:luoyaqifei
- 校對(duì)者:Romeo0906,L9m
全方位提升網(wǎng)站打開速度:前端、后端、新的技術(shù)
這里是?我們?充分利用對(duì)于網(wǎng)絡(luò)緩存和 NoSQL 系統(tǒng)的研究,做出一個(gè)可以容納幾十萬通過電視宣傳慕名而來的訪問者的?網(wǎng)上商城?的故事,以及我們從中學(xué)到的一切。
"Shark Tank"(美國),"Dragons’ Den"(英國)或" Die H?hle der L?wen(DHDL)"(德國)等電視節(jié)目為年輕初創(chuàng)公司供了一次在眾多觀眾前向商業(yè)大亨推銷自己產(chǎn)品的機(jī)會(huì)。然而,主要的好處往往不在于評(píng)審團(tuán)提供的戰(zhàn)略投資——只有少數(shù)交易會(huì)完成——而是在電視節(jié)目播放期間引發(fā)的關(guān)注:即使是幾分鐘的直播也能給網(wǎng)站帶來幾十萬的新用戶,同時(shí)能夠提高幾周、幾個(gè)月甚至永久性的網(wǎng)站基本活躍水平。也就是說,如果網(wǎng)站可以抓住初始負(fù)載尖峰,并且不拒絕用戶請(qǐng)求……
僅僅可用是不夠的——延遲是關(guān)鍵!
網(wǎng)上商城的盈利壓力特別大,因?yàn)樗麄儾恢皇窍岔?xiàng)目(諸如博客),但通常由于創(chuàng)始人本身有大量投資支持,必須轉(zhuǎn)化為利潤。很明顯,對(duì)于商業(yè)業(yè)務(wù)來說,最壞的情況是網(wǎng)站過載,在此期間服務(wù)器不得不丟掉部分用戶請(qǐng)求甚至可能完全崩潰。這并不像你想象的那樣罕見:在 DHDL 的這一季,大約有一半的網(wǎng)上商店在直播現(xiàn)場(chǎng)就無法連接了。并且,保持在線只有一半的租金,因?yàn)橛脩魸M意度是強(qiáng)制連接到轉(zhuǎn)化率,從而直接轉(zhuǎn)化為產(chǎn)生的收入的。
Source
關(guān)于頁面加載時(shí)間對(duì)客戶滿意度和轉(zhuǎn)換率的影響,有很多?研究?支持這種說法。例如,Aberdeen Group 發(fā)現(xiàn),額外延遲的 1 秒會(huì)導(dǎo)致頁面瀏覽量減少 11%,轉(zhuǎn)化次數(shù)損失 7%。 但你也可以詢問?Google?或?Amazon,他們會(huì)告訴你同樣的說法。
怎樣讓網(wǎng)站加速
為初創(chuàng)公司?Thinks?搭建的網(wǎng)上商城參與了 DHDL,并在 9 月 6 日播出。我們面臨著一個(gè)挑戰(zhàn),搭建一個(gè)能夠承受數(shù)十萬訪客量的網(wǎng)上商店,并且加載時(shí)間穩(wěn)定在 1 秒以內(nèi)。以下都是我們?cè)谶@個(gè)過程中以及從近些年對(duì)數(shù)據(jù)庫和網(wǎng)絡(luò)的性能研究中學(xué)到的。
在現(xiàn)有的 web 應(yīng)用技術(shù)中有三個(gè)影響頁面加載時(shí)間的主要原因,展示如下:
為了讓我們的網(wǎng)店加速,讓我們一一解決這三個(gè)瓶頸。
前端性能
影響前端性能最重要的因素是關(guān)鍵呈現(xiàn)路徑(CRP),它描述了在瀏覽器中向用戶顯示頁面所需的 5 個(gè)必要步驟,如下所示。
關(guān)鍵呈現(xiàn)路徑的步驟:
- DOM:當(dāng)瀏覽器解析HTML時(shí),它會(huì)增量式地生成一個(gè) HTML 標(biāo)簽的樹模型,稱為?文檔對(duì)象模型(DOM),該模型描述了頁面內(nèi)容。
- CSSOM:一旦瀏覽器接收到所有的 CSS,它會(huì)生成一個(gè) CSS 中包含的標(biāo)簽和類的樹模型,稱為?CSS 對(duì)象模型,在樹節(jié)點(diǎn)上還附有樣式信息。這棵樹描述了頁面內(nèi)容是如何設(shè)置樣式的。
- 渲染樹:通過組合 DOM 和 CSSOM,瀏覽器構(gòu)造一個(gè)渲染樹,它包含頁面內(nèi)容以及要應(yīng)用的樣式信息。
- 布局:布局這一步計(jì)算屏幕上頁面內(nèi)容的實(shí)際位置和大小。
- 繪制:最后一步使用布局信息將實(shí)際像素繪制到屏幕上。
單個(gè)步驟是相當(dāng)簡單的,使事情變得困難并限制性能的是這些步驟之間的依賴。DOM 和 CSSOM 的構(gòu)造通常具有最大的性能影響。
這個(gè)圖表顯示了關(guān)鍵呈現(xiàn)路徑的步驟,里面包括等待依賴,如箭頭所示。
關(guān)系呈現(xiàn)路徑中重要的依賴
在加載 CSS 和構(gòu)造完整的 CSSOM 之前,什么都不能顯示給客戶端。因此 CSS 被稱為是阻塞渲染的。
JavaScript(JS)更糟糕,因?yàn)樗梢栽L問和更改 DOM 和 CSSOM。 這意味著一旦發(fā)現(xiàn) HTML 中的腳本標(biāo)記,DOM 構(gòu)造就會(huì)被暫停,并從服務(wù)器請(qǐng)求腳本。一旦腳本被加載,只有在所有 CSS 被提取和 CSSOM 被構(gòu)造以后,它才能被執(zhí)行。在 CSSOM 構(gòu)建之后 JS 被執(zhí)行,在下面的例子中,它可以訪問和改變 DOM 以及 CSSOM。只有這樣之后,DOM的構(gòu)造才能進(jìn)行,并且頁面才能顯示給客戶端。因此 JavaScript 被稱為是阻塞解析的。
JavaScript 訪問 CSSOM 和更改 DOM 的示例:
<script>...var old = elem.style.width;elem.style.width = "50px";document.write("alter DOM");... </script>JS 甚至?xí)绊懜鼝毫印@?jQuery 插件?訪問計(jì)算后的 HTML 元素的布局信息,然后開始一次又一次地改變 CSSOM,直到實(shí)現(xiàn)了所需的布局。因此,在用戶將看到白色屏幕以外的任何東西之前,瀏覽器必須一次又一次地重復(fù)地執(zhí)行 JS、構(gòu)造渲染樹和布局。
有三個(gè)優(yōu)化 CRP 的?基本概念:
此外,瀏覽器緩存?是非常有效的,應(yīng)該在所有的項(xiàng)目中加以使用。它對(duì)于這三個(gè)優(yōu)化項(xiàng)都很合適,因?yàn)榫彺娴馁Y源不必先從服務(wù)器加載。
CRP 優(yōu)化的整個(gè)主題是相當(dāng)復(fù)雜的,特別是內(nèi)聯(lián)、級(jí)聯(lián)和異步加載,它們可能會(huì)破壞代碼的可重用性。幸運(yùn)的是,有很多強(qiáng)大的工具,可以為你做好這些優(yōu)化,這些工具可以被集成到你的構(gòu)建和部署鏈里。你的確應(yīng)該地看看下面的工具……
- 分析:?GTmetrix?用來衡量網(wǎng)頁速度,webpagetest?用來分析你的資源,以及 Google 的PageSpeed Insights,為你的網(wǎng)站生成有關(guān)如何優(yōu)化 CRP 的提示。
- 內(nèi)聯(lián)和優(yōu)化:[Critical]((https://github.com/addyosmani/critical) 非常適合自動(dòng)將你的明顯位置的 CSS 內(nèi)聯(lián)并且異步加載其余 CSS,processhtml?連接你的資源和?PostCSS?進(jìn)一步優(yōu)化 CSS。
- 最小化和壓縮:?我們使用?tiny png?來進(jìn)行圖像壓縮,UglifyJs?和?cssmin?來進(jìn)行最小化,Google Closure?來進(jìn)行 JS 優(yōu)化。
有了這些工具只需很小的工作量,你就可以打造一個(gè)前端性能極好的網(wǎng)站。這里是?Thinks?商城第一次訪問時(shí)的頁面速度測(cè)試:
thinks.com 的 Google 網(wǎng)頁速度分?jǐn)?shù)
有趣的是,PageSpeed Insights 內(nèi)部唯一的抱怨是,Google 分析的腳本緩存生命周期太短。所以 Google 基本上在抱怨它自己。
來自加拿大(GTmetrix)的第一次頁面加載,服務(wù)器托管在法蘭克福(Frankfurt)
網(wǎng)絡(luò)性能
網(wǎng)絡(luò)延遲是頁面加載時(shí)間最重要的因素,它也是最難優(yōu)化的。但在我們進(jìn)行優(yōu)化之前,讓我們看一下對(duì)初始的瀏覽器請(qǐng)求的劃分:
當(dāng)我們?cè)跒g覽器中輸入?https://www.thinks.com/?并按下回車鍵時(shí),瀏覽器開始使用?DNS 查找來識(shí)別與域相關(guān)聯(lián)的 IP 地址,這種查找必須對(duì)每個(gè)單獨(dú)的域進(jìn)行。
使用接收到的 IP 地址,瀏覽器初始化與服務(wù)器的?TCP 連接。TCP 握手需要 2 次往返(1 次是?TCP 快速打開)。使用安全的?SSL 連接,TLS 握手需要額外的 2 次往返(1 次是?TLS False Start?或?Session Resumption)。
在初始連接之后,瀏覽器發(fā)送實(shí)際請(qǐng)求并等待數(shù)據(jù)進(jìn)入。第一個(gè)字節(jié)到達(dá)的時(shí)間主要取決于客戶端和服務(wù)器之間的距離,包括服務(wù)器渲染頁面所需的時(shí)間(包括會(huì)話查找、數(shù)據(jù)庫查詢和模板渲染等)。
最后一步是在可能的多次往返中下載資源(在這種情況下指的是 HTML )。新連接尤其通常需要很多往返,因?yàn)槌跏紦砣翱诤苄 _@意味著 TCP 不是從一開始就使用全帶寬,而是隨著時(shí)間的推移而增加帶寬(參見?TCP擁塞控制。下載速度受到慢啟動(dòng)算法的支配,該算法在每次往返的擁塞窗口中將報(bào)文段數(shù)量加倍,直到丟包發(fā)生。在移動(dòng)網(wǎng)絡(luò)和 Wifi 網(wǎng)絡(luò)上丟失數(shù)據(jù)包因此具有很大的性能影響。
另一件要記住的事是:使用 HTTP/1.1,你只能得到?6 個(gè)并行連接(如果瀏覽器仍然遵循原始標(biāo)準(zhǔn),則連接數(shù)為 2)。因此,你最多只能請(qǐng)求 6 個(gè)資源并行。
為了對(duì)網(wǎng)絡(luò)性能對(duì)于頁面速度的重要性有一個(gè)直觀的認(rèn)識(shí),你可以查看?httparchive?,上面有很多統(tǒng)計(jì)數(shù)據(jù)。例如,網(wǎng)站平均在 100 多個(gè)請(qǐng)求中加載大約 2.5 MB的數(shù)據(jù)。
來源
所以網(wǎng)站發(fā)出了很多小的請(qǐng)求來加載很多資源,但網(wǎng)絡(luò)帶寬一直在增加。物理網(wǎng)絡(luò)的演進(jìn)將拯救我們,對(duì)吧?嗯,其實(shí)并不是……
來自?High Performance Browser Networking,作者為 Ilya?Grigorik
事實(shí)證明,將帶寬增加到 5 Mbps 以上并不真的影響頁面加載時(shí)間。但減少單個(gè)請(qǐng)求的延遲會(huì)降低網(wǎng)頁加載時(shí)間。這意味著帶寬加倍帶來的是相同的加載時(shí)間,而減少一半的延遲將給你一半的加載時(shí)間。
因此,如果延遲是網(wǎng)絡(luò)性能的決定因素,我們可以在這上面做些什么呢?
- 持久連接是必須有的。沒有什么比當(dāng)你的服務(wù)器在每個(gè)請(qǐng)求后關(guān)閉連接,并且瀏覽器必須一次又一次地執(zhí)行握手操作和 TCP 慢啟動(dòng)更糟糕的事情了。
- 盡可能地避免重定向,因?yàn)樗鼈儠?huì)大大減慢你的初始網(wǎng)頁加載速度。永遠(yuǎn)鏈接完整的網(wǎng)址(例如使用?www.thinks.com?而不是 thinks.com)。
- 如果可以的話,請(qǐng)使用?HTTP/2。它附帶服務(wù)器推送,能為單個(gè)請(qǐng)求傳輸多個(gè)資源;頭壓縮來減小請(qǐng)求和響應(yīng)的大小;并請(qǐng)求流水線和多路復(fù)用通過單個(gè)連接發(fā)送任意并行請(qǐng)求。使用服務(wù)器推送,你的服務(wù)器可以發(fā)送你的 html ,緊接著推送網(wǎng)站所需的 CSS 和 JS,而無需等待實(shí)際請(qǐng)求。
-
為你的靜態(tài)資源(CSS,JS,靜態(tài)圖像如 logo)設(shè)置顯式的緩存頭。這樣,你可以告訴瀏覽器需要將這些資源緩存多長時(shí)間以及何時(shí)重新驗(yàn)證。緩存可以節(jié)省大量的往返和需要下載的字節(jié)。如果沒有設(shè)置明確的緩存頭,瀏覽器會(huì)做?啟發(fā)式緩存,這比不緩存好,但遠(yuǎn)不是最佳。
-
使用內(nèi)容分發(fā)網(wǎng)絡(luò)(CDN)來緩存圖像、CSS、JS 和 HTML。這些分布式緩存網(wǎng)絡(luò)可以顯著地減少與用戶的距離,從而更快地提供資源。它們還加速了你的初始連接,因?yàn)槟闩c附近的 CDN 節(jié)點(diǎn)進(jìn)行 TCP 和 TLS 握手,而這些節(jié)點(diǎn)會(huì)依次建立熱的和持久的后端連接。
- 建議你使用一個(gè)小的初始頁來創(chuàng)建單頁應(yīng)用程序,這個(gè)初始網(wǎng)頁會(huì)異步地加載其它組件。這樣,你可以使用可緩存的 HTML 模板,在小請(qǐng)求中加載動(dòng)態(tài)數(shù)據(jù),并在導(dǎo)航(navigation)期間只更新頁面的各個(gè)部分。
總而言之,當(dāng)涉及到網(wǎng)絡(luò)性能時(shí),有一些要做的(do) 和不要做的(don't),但限制因素總是往返次數(shù)與物理網(wǎng)絡(luò)延遲的結(jié)合。克服這種限制的唯一有效方法是使數(shù)據(jù)更接近客戶端。最先進(jìn)的網(wǎng)絡(luò)緩存狀態(tài)的確如此,但這僅適用于靜態(tài)資源。
對(duì)于?Thinks,我們遵循上述準(zhǔn)則,使用?Fastly?CDN 和主動(dòng)的瀏覽器緩存,甚至對(duì)動(dòng)態(tài)數(shù)據(jù)使用一種新的?布隆過濾器算法(Bloom Filter algorithm)?來使得緩存數(shù)據(jù)保持一致。
www.thinks.com?重復(fù)加載,來顯示瀏覽器緩存覆蓋率
對(duì)于重復(fù)網(wǎng)頁加載的請(qǐng)求,瀏覽器緩存沒有提供的內(nèi)容(參見上圖)包括:對(duì) Google 分析的 API 的兩個(gè)異步調(diào)用,以及從 CDN 處獲取的初始 HTML 請(qǐng)求。因此,對(duì)于重復(fù)的網(wǎng)頁加載,頁面能夠做到立即加載。
后端性能
對(duì)于后端性能,我們需要同時(shí)考慮延遲和吞吐量。為了實(shí)現(xiàn)低延遲,我們需要將服務(wù)器的處理時(shí)間最小化。為了保持高吞吐量和應(yīng)對(duì)負(fù)載尖峰,我們需要采用一種水平可擴(kuò)展的架構(gòu)。我們不會(huì)談到太多細(xì)節(jié),因?yàn)樵O(shè)計(jì)決策對(duì)性能的影響空間是巨大的,這些是需要去尋找的最重要的組件和屬性:
可擴(kuò)展的后端技術(shù)棧組件:負(fù)載均衡器,無狀態(tài)應(yīng)用服務(wù)器,分布式數(shù)據(jù)庫
首先,你需要負(fù)載均衡(例如 Amazon ELB 或 DNS 負(fù)載均衡)將傳入的請(qǐng)求分配給你的一個(gè)應(yīng)用服務(wù)器。它還應(yīng)該實(shí)現(xiàn)自動(dòng)調(diào)節(jié)功能,在需要時(shí)生成其他應(yīng)用服務(wù)器,以及故障轉(zhuǎn)移功能,以替換損壞的服務(wù)器并將請(qǐng)求重新路由到正常服務(wù)器。
應(yīng)用服務(wù)器應(yīng)將共享狀態(tài)最小化,從而保持協(xié)調(diào)最少,并使用無狀態(tài)會(huì)話處理來啟用自由的負(fù)載均衡。此外,服務(wù)器應(yīng)該有高效的代碼和 IO,使得服務(wù)器處理時(shí)間最小。
數(shù)據(jù)庫需要承受負(fù)載尖峰,并盡可能減少處理時(shí)間。同時(shí),它們需要具有足夠的表達(dá)性,以根據(jù)需要建模和查詢數(shù)據(jù)。有大量的可擴(kuò)展數(shù)據(jù)庫(尤其是 NoSQL),每個(gè)都有自己的 trade-off。詳細(xì)信息請(qǐng)參考我們關(guān)于該主題的調(diào)查和決策指南:
NoSQL 數(shù)據(jù)庫:一份調(diào)查和決策指南
與我們?cè)跐h堡大學(xué)的同事一起,我們是:Felix Gessert, Wolfram Wingerath, Steffen…medium.baqend.com
Thinks?網(wǎng)上商城搭建在?Baqend?上,使用了如下的后端技術(shù)棧:
Baqend的后端技術(shù)棧:MongoDB 作為主數(shù)據(jù)庫,無狀態(tài)應(yīng)用服務(wù)器,HTTP 緩存層次結(jié)構(gòu),REST 和 web 前端的 JS SDK
用于?Thinks?的主數(shù)據(jù)庫是?MongoDB。為了維護(hù)我們將要到期的布隆過濾器(用于瀏覽器緩存),我們使用?Redis?,因?yàn)樗母邔懭胪掏铝俊o狀態(tài)應(yīng)用程服務(wù)器(Orestes Servers)為后端功能提供接口(文件托管,數(shù)據(jù)存儲(chǔ),實(shí)時(shí)查詢,推送通知,訪問控制等),并處理動(dòng)態(tài)數(shù)據(jù)的緩存一致性。它們從?CDN?拿到請(qǐng)求,CDN 也充當(dāng)負(fù)載均衡器。網(wǎng)站前端使用基于?REST API?的?JS SDK?來訪問后端,后端自動(dòng)利用完整的?HTTP 緩存層次結(jié)構(gòu)來讓請(qǐng)求加速并保持緩存數(shù)據(jù)時(shí)刻最新。
負(fù)載測(cè)試
為了在高負(fù)載下測(cè)試?Thinks?網(wǎng)上商城,我們?cè)诜ㄌm克福的 t2.medium AWS 實(shí)例上使用 2 個(gè)應(yīng)用服務(wù)器來進(jìn)行負(fù)載測(cè)試。MongoDB 在兩個(gè) t2.large 實(shí)例上運(yùn)行。使用?JMeter?構(gòu)建負(fù)載測(cè)試并在?IBM soft layer?上的 20 個(gè)機(jī)器上運(yùn)行,以模擬在?15分鐘內(nèi),200,000 個(gè)用戶同時(shí)訪問和瀏覽網(wǎng)站。20% 的用戶(40,000)被配置為執(zhí)行額外的付款流程。
網(wǎng)上商城的負(fù)載測(cè)試設(shè)置
我們?cè)谥Ц秾?shí)現(xiàn)中發(fā)現(xiàn)了一些瓶頸,例如,我們必須從庫存的積極更新(使用?findAndModify實(shí)現(xiàn))切換到 MongoDB 的部分更新操作(inc)。但是在這之后,服務(wù)器處理的負(fù)載只是精細(xì)地達(dá)到了平均請(qǐng)求延遲 5 ms。
JMeter 在負(fù)載測(cè)試期間輸出:在 12 分鐘內(nèi)有 680 萬個(gè)請(qǐng)求,平均延遲 5 ms
所有的負(fù)載測(cè)試組合生成了大約?1000 萬個(gè)請(qǐng)求,傳輸了?460 GB的數(shù)據(jù),伴隨著?99.8%?的 CDN?緩存命中率。
負(fù)載測(cè)試后的儀表板概述
總結(jié)
總之,良好的用戶體驗(yàn)取決于三個(gè)支柱:前端,網(wǎng)絡(luò)和后端的性能。
前端性能是我們認(rèn)為最容易實(shí)現(xiàn)的,因?yàn)橐呀?jīng)有很多工具和一些容易遵循的最佳實(shí)踐。但仍然有很多網(wǎng)站不遵循這些最佳實(shí)踐,完全沒有優(yōu)化過它們的前端。
網(wǎng)絡(luò)性能對(duì)于頁面加載時(shí)間來說,是最重要的因素,也是最難優(yōu)化的。緩存和 CDN 是最有效的優(yōu)化方法,但即使對(duì)于靜態(tài)內(nèi)容也要付出相當(dāng)大的努力。
后端性能取決于單服務(wù)器性能和跨機(jī)器去分發(fā)工作的能力。水平可擴(kuò)展性特別難以實(shí)現(xiàn),必須從一開始就考慮。許多項(xiàng)目將可擴(kuò)展性和性能作為事后處理,然而在它們的業(yè)務(wù)增長時(shí)會(huì)陷入大麻煩。
文獻(xiàn)和工具建議
有很多關(guān)于 web 性能和可擴(kuò)展系統(tǒng)設(shè)計(jì)的書:由 Ilya Grigorik 所寫的?高性能瀏覽器網(wǎng)絡(luò)?包含了幾乎所有你需要了解的網(wǎng)絡(luò)和瀏覽器性能知識(shí),并且目前不斷更新的版本可以免費(fèi)在線閱讀哦!Martin Kleppmann 寫的?設(shè)計(jì)數(shù)據(jù)密集型應(yīng)用?仍處于前期發(fā)布狀態(tài),但已經(jīng)是其領(lǐng)域最好的書之一,它涵蓋了可擴(kuò)展后端系統(tǒng)背后的大部分基礎(chǔ)知識(shí),并擁有相當(dāng)多的細(xì)節(jié)。設(shè)計(jì)性能?由Lara Callender Hogan 寫成,圍繞著構(gòu)建快速的、具有良好的用戶體驗(yàn)的網(wǎng)站,涵蓋了很多最佳實(shí)踐。
還有一些很棒的在線指南、教程和工具可以考慮:從初學(xué)者友好的 Udacity 課程?網(wǎng)站性能優(yōu)化、Google 的?開發(fā)者性能指南?到類似于?Google PageSpeed Insights、GTmetrix?和?WebPageTest?這樣的優(yōu)化工具。
最新的 Web 性能開發(fā)
移動(dòng)頁面加速
Google 正在通過諸如?PageSpeed Insights、開發(fā)人員指南?等網(wǎng)站性能項(xiàng)目來提高大家對(duì)于網(wǎng)站性能的意識(shí),并將網(wǎng)頁速度作為其?網(wǎng)頁排名?的主要因素。
在 Google 搜索中用來提高網(wǎng)頁速度、增強(qiáng)用戶體驗(yàn)的最新概念是?移動(dòng)網(wǎng)頁加速(AMP)。其目的是讓新聞文章、產(chǎn)品頁面和其它搜索內(nèi)容立即從 Google 搜索加載。為此,這些頁面必須構(gòu)建為 AMP。
一個(gè) AMP 頁面的示例
AMP 主要做兩件事:
構(gòu)建為 AMP 的網(wǎng)站使用精簡版本的 HTML,并使用 JS 加載器來快速渲染,并異步加載盡可能多的資源。
Google 將網(wǎng)站緩存在 Google CDN 中,并通過 HTTP/2 分發(fā)。
第一件事從本質(zhì)上意味著 AMP 以一種方式限制了你的 HTML、JS 和 CSS,這種方式構(gòu)建的網(wǎng)頁有一個(gè)優(yōu)化的關(guān)鍵呈現(xiàn)路徑,可以很容易地被 Google 爬取。 AMP 強(qiáng)制?幾個(gè)限制,例如所有 CSS 必須內(nèi)聯(lián),所有 JS 必須是異步的,頁面上的所有內(nèi)容必須具有靜態(tài)大小(以防止重繪)。 雖然你可以通過堅(jiān)持之前的 web 性能最佳實(shí)踐,在沒有這些限制的情況下,實(shí)現(xiàn)相同的結(jié)果,但 AMP 可能是很好的 trade-off ,能夠?yàn)榉浅:唵蔚木W(wǎng)站提供幫助。
第二件事意味著,Google 抓取你的網(wǎng)站,然后將其緩存在 Google CDN 中,以便快速分發(fā)。網(wǎng)站內(nèi)容會(huì)在爬蟲重新索引你的網(wǎng)站后更新。CDN 還遵循服務(wù)器設(shè)置的靜態(tài) TTL,但至少執(zhí)行?微緩存:資源至少在一分鐘內(nèi)被視為最新的,并在用戶請(qǐng)求進(jìn)入時(shí)在后臺(tái)更新。因此 AMP 最適用于內(nèi)容大多是靜態(tài)的用戶案例。這種適用于人為編輯修改的新聞網(wǎng)站或者其他出版物的情況。
漸進(jìn)式 web 應(yīng)用(Progressive Web?Apps)
Google 的另一種做法是?漸進(jìn)式 web 應(yīng)用(PWA)。其想法是在瀏覽器中使用?服務(wù)工作者(service worker)?來緩存網(wǎng)站的靜態(tài)部分。因此,這些部分對(duì)于重復(fù)視圖會(huì)立即加載,并可離線使用。動(dòng)態(tài)部分仍從服務(wù)器端加載。
app shell(單頁應(yīng)用程序邏輯)可以在后臺(tái)重新驗(yàn)證。如果標(biāo)識(shí)了對(duì)應(yīng)用 shell 的更新,則會(huì)提示用戶,要求他更新頁面。例如,Gmail 收件箱?就實(shí)現(xiàn)了這個(gè)。
但是,寫出緩存靜態(tài)資源并進(jìn)行重新驗(yàn)證的服務(wù)工作者(service worker)代碼,對(duì)于每個(gè)網(wǎng)站來說,都需要付出相當(dāng)大的努力。此外,只有 Chrome 和 Firefox 充分地支持了服務(wù)工作者(service worker)。
緩存動(dòng)態(tài)內(nèi)容
所有緩存方法遇到的問題是它們不能處理動(dòng)態(tài)內(nèi)容。這只是由于 HTTP 緩存的工作機(jī)制導(dǎo)致的。有兩種類型的緩存:基于失效的緩存(如轉(zhuǎn)發(fā)代理緩存和 CDN)和基于到期的緩存(如 ISP 緩存、機(jī)構(gòu)代理和瀏覽器緩存)。基于失效的緩存可以從服務(wù)器端主動(dòng)失效,基于到期的高速緩存只能從客戶端重新驗(yàn)證。
使用基于到期的緩存時(shí),棘手的事情是,你必須在首次從服務(wù)器拿到數(shù)據(jù)時(shí)指定緩存生命周期(TTL)。之后,你沒有任何機(jī)會(huì)將緩存數(shù)據(jù)刪除。它將由瀏覽器緩存提供到 TTL 到期的時(shí)刻。對(duì)于靜態(tài)資源,這不是一件復(fù)雜的事情,因?yàn)樗鼈兺ǔV粫?huì)在你部署 web 應(yīng)用程序的新版本時(shí)發(fā)生變化。因此,你可以使用?gulp-rev-all?和?grunt-filerev?等很酷的工具)對(duì) assets 進(jìn)行散列。
但是,但是你該如何處理運(yùn)行時(shí)的應(yīng)用數(shù)據(jù)加載和修改呢?更改用戶個(gè)人資料、更新帖子或添加新評(píng)論似乎不可能與瀏覽器緩存結(jié)合使用,因?yàn)槟銦o法預(yù)估此類更新將來何時(shí)會(huì)發(fā)生。因此,緩存只能被禁用或使用非常小的 TTL。
由另一個(gè)客戶端更新時(shí),緩存動(dòng)態(tài)數(shù)據(jù)如何過時(shí)的示例
Baqend 的 Cache-Sketch 方法
在?Baqend,我們已經(jīng)研究并開發(fā)了一種方法,在實(shí)際獲取之前,檢查客戶端中 URL 的陳舊度。在每個(gè)用戶會(huì)話開始時(shí),我們獲取一個(gè)非常小的數(shù)據(jù)結(jié)構(gòu),稱為布隆過濾器(Bloom Filter),它是所有過時(shí)資源集合的高度壓縮表示。通過查看布隆過濾器,客戶端可以檢查資源是否過時(shí)(包含在布隆過濾器中)或者是否是全新的。對(duì)于潛在的過時(shí)資源,我們繞過瀏覽器緩存并從 CDN 獲取內(nèi)容。在其他的所有情況下,我們直接用瀏覽器緩存提供內(nèi)容。使用瀏覽器緩存可以節(jié)省網(wǎng)絡(luò)流量和帶寬,并且是很快的。
此外,我們確保 CDN(以及其它基于失效的緩存,如 Varnish)始終包含最新的數(shù)據(jù),只要它們過時(shí)就立即清除資源。
Baqend 如何確保緩存動(dòng)態(tài)數(shù)據(jù)的新鮮度示例
布隆過濾器(Bloom filter)?是具有可調(diào)誤報(bào)率的概率數(shù)據(jù)結(jié)構(gòu),這意味著集合可以用來表示對(duì)從未添加的對(duì)象的遏制,但永遠(yuǎn)不會(huì)刪除實(shí)際條目。換句話說,我們可能偶爾會(huì)重新驗(yàn)證新資源,但是我們永遠(yuǎn)不會(huì)提供過期數(shù)據(jù)。注意,誤報(bào)率非常低,這使得我們能夠讓集合非常小。例如,我們只需要 11 Kbyte 來存儲(chǔ) 20,000 個(gè)不同的更新。
Baqend 在服務(wù)器端有很多流處理(查詢匹配檢測(cè))、機(jī)器學(xué)習(xí)(最佳 TTL 估計(jì))和分布式協(xié)調(diào)(可擴(kuò)展的布隆過濾器維護(hù))的工作。如果你對(duì)這些細(xì)節(jié)感興趣,看看這篇?文章?或?這些幻燈片?來深入研究。
性能收益
這一切都?xì)w結(jié)為這一點(diǎn)。
使用 Baqend 的緩存基礎(chǔ)設(shè)施可以使哪種頁面速度得到提高?
為了展示使用 Baqend 的好處,我們?cè)诤蠖思捶?wù)(BaaS)領(lǐng)域中的每個(gè)領(lǐng)先競(jìng)爭(zhēng)對(duì)手上構(gòu)建了一個(gè)非常簡單的新聞應(yīng)用,并觀測(cè)了來自世界各地不同位置的頁面加載時(shí)間。如下所示,Baqend 持續(xù)加載低于 1 秒,比平均速度快 6.8 倍。即使當(dāng)所有客戶端來自服務(wù)器所在的同一位置時(shí),由于有瀏覽器緩存,Baqend 也是 150% 倍速度。
簡單新聞應(yīng)用的平均加載時(shí)間比較
我們將此比較作為一個(gè)?動(dòng)手的 web 應(yīng)用?來比較 BaaS 競(jìng)爭(zhēng)。
動(dòng)手比較?的截圖
但這當(dāng)然是一個(gè)測(cè)試場(chǎng)景,而不是一個(gè)具有真正用戶的 web 應(yīng)用。 所以讓我們回到?Thinks?網(wǎng)上商城來看一個(gè)真實(shí)世界的例子。
Thinks 網(wǎng)上商城——所有的事實(shí)
當(dāng) DHDL("Shark Tank"的德國版)在 9 月 6 日播出時(shí),有 270 萬觀眾,我們坐在電視和我們的 Google 分析屏幕前,為?Thinks?創(chuàng)始人提出他們的產(chǎn)品而激動(dòng)。
從他們開始演示起,網(wǎng)上商的并發(fā)用戶數(shù)量迅速增加到大約 10,000,但真正的巔峰發(fā)生在廣告休息時(shí),當(dāng)時(shí)突然有超過45,000 的并發(fā)用戶來參觀該店購買 Towell+:
Google 分析觀測(cè)在商業(yè)廣告時(shí)間之前開始。
Thinks?在電視播放的 30 分鐘里,我們得到了?340?萬的請(qǐng)求,300,000?位游客,高達(dá)?50,000?位的并發(fā)訪問游客和高達(dá)每秒 20,000 個(gè)請(qǐng)求,所有這一切實(shí)現(xiàn)了在 CDN 級(jí)別的?98.5% 的緩存命中率,和平均為?3% 的服務(wù)器 CPU 負(fù)載
因此,頁面加載時(shí)間為低于 1 秒,整個(gè)時(shí)間實(shí)現(xiàn)了?7.8% 的極大的轉(zhuǎn)化率。
如果我們看看在同一集 DHDL 中展示的其他商城,我們會(huì)看到其中四個(gè)?完全崩潰了,剩下的商城只利用了極少的性能優(yōu)化。
可用性概述和商城的 Google 頁面速度得分,在 DHDL 上,于 9 月 6 日展示。
總結(jié)
我們已經(jīng)看到了在設(shè)計(jì)快速和可擴(kuò)展的網(wǎng)站時(shí)需要克服的瓶頸:我們必須掌握關(guān)鍵呈現(xiàn)路徑,理解網(wǎng)絡(luò)限制、緩存的重要性和具有水平可擴(kuò)展性的后端設(shè)計(jì)。
我們已經(jīng)看到了很多用來解決單個(gè)問題的工具,以及移動(dòng)加速頁面(AMP)和漸進(jìn)式 web 應(yīng)用(PWA),這些采取了更全面的做法。但是,緩存動(dòng)態(tài)數(shù)據(jù)的問題仍然存在。
Baqend?的做法是減少 web 開發(fā),將構(gòu)建主要放在前端,通過 JS SDK 使用 Baqend 完全托管的云服務(wù)上的后端功能,包括數(shù)據(jù)和文件存儲(chǔ)、(實(shí)時(shí))查詢、推送通知、用戶管理和 OAuth 以及訪問控制。該平臺(tái)通過使用完整的 HTTP 緩存層次結(jié)構(gòu)自動(dòng)加速所有請(qǐng)求,并確保可用性和可擴(kuò)展性。
我們對(duì)于 Baqend 的愿景是一個(gè)不需要加載時(shí)間的網(wǎng)站,并且我們想要給你到達(dá)這個(gè)目標(biāo)的工具。
繼續(xù)前往免費(fèi)試用?www.baqend.com.
?
PS:文章不錯(cuò),忍不住轉(zhuǎn)載了,轉(zhuǎn)載鏈接是:https://github.com/xitu/gold-miner/blob/master/TODO/building-a-shop-with-sub-second-page-loads-lessons-learned.md
轉(zhuǎn)載于:https://www.cnblogs.com/Andrew-XinFei/p/6202779.html
總結(jié)
以上是生活随笔為你收集整理的[转载] 全方位提升网站打开速度:前端、后端、新的技术的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微信 小程序组件 循环
- 下一篇: supervisor开机自启动方法