從減少http請求數說起

前一陣,給我一個學生做培訓,講到一點點性能優化,然後我很後悔我誤導了她.我給她講減少http請求是多麼重要,如何重要,爲什麼重要,還舉了例子來說明這對於大型網站來說是多麼重要,講的頭頭是道,有理有據,最後把她說的服服帖帖,一切看起來理所當然.但是….

事情沒有那麼簡單,就像做技術一樣,其實去了解一個技術很簡單,但是要懂得如何運用這個技術就不是每個人都可以做到的了.

1.理所當然我們是這樣想的

關於減少http請求數,是前端開發性能優化的一個非常重要方面,所以在基本所有的優化原則裏,都有這一條原則:減少http請求數.

先不考慮其他的,我們先考慮爲什麼減少http請求可以優化性能.

減少http請求有這樣幾個優點:

(1)   減少DNS請求所耗費的時間.

且不說對錯,因爲從基本來說,減少http請求數的確可以減少DNS請求和解析耗費的時間.

(2)   減少服務器壓力.

這個通常是被考慮最多的,也是我用來講解給別人聽的最大理由,因爲每個http請求都會耗費服務器資源,特別是一些需要計算合併等操作的服務器,耗費服務器的cpu資源可不是開玩笑的事情,硬盤可以用錢買來,cpu資源可就沒那麼廉價了.

(3)   減少http請求頭.

當我們對服務器發起一個請求的時候,我們會攜帶着這個域名下的cookie和一些其他的信息在http頭部裏,然後服務器響應請求的時候也會帶回一些cookie之類的頭部信息.這些信息有的時候會很大,在這種請求和響應的時候會影響帶寬性能.

2.讓我們來一一道來

(1) 什麼是DNS請求和解析呢?

簡單來說,例如:www.taobao.com這樣一個url,其中www部分被稱爲主機名(hostname),taobao這部分則是二級域,com則是一級域,如果是這樣一個網址:www.ali.taobao.com.那麼ali就是三級域.

當我們去請求一個url的時候,首先會到本地服務器裏去尋找緩存中是否有解析結果,如果沒有解析結果,就去根域名服務器請求,根域名服務器返回給本 地域名服務器一個所查詢的域的主域名服務器的ip地址,然後我們再去請求剛纔返回的ip地址的域名服務器,然後返回下一級域名的ip地址,直到我們找到域 名中所指的服務器ip,然後將結果緩存起來供下次使用,並返回此結果.

一個第一次請求的url的DNS解析過程可能耗費是很高的.但是解析一次之後,結果就會被緩存起來,之後再請求的時候就不用走上面這一套複雜的解析過程了.

關於一個正常的DNS請求到底會耗費多少時間,這個沒有定論,要看網速狀況和地域,但是考慮一個dns解析解析過後會被緩存起來,像淘寶這樣的大網站,來的都是回頭客,我們是否可以忽略DNS解析花費的時間呢?

在前端優化裏還有一個優化方法,那就是增加hostname,例如,淘寶圖片服務器,分爲img01,img02,img03等主機名,這樣做是因 爲考慮到瀏覽器對同一個域名下同時進行的http連接數的限制,具體可以見下表: .然後我們在一個頁面裏的圖片放在不同的hostname下,這樣就可以同時下載多個圖片了,瀏覽器http連接數的限制可以被緩解一下,但是這樣做的後 果就是yslow評分會下降,因爲yslow將DNS請求看的比較重要.

Browser   HTTP/1.1       HTTP/1.0
IE 6,7           2                     4
IE 8               6                    6
Firefox 2      2                     8
Firefox 3      6                     6
Safari 3,4     4                     4
Opera 9.61   8                     2

在此,就要引出我們想討論的東西,爲什麼yslow評分在合理的情況下分數反而會低,因爲yslow只是一個機器程序,它並不知道 我們的網站是什麼類型的,是何種規模的,是內容型還是應用型,所以我們可以用異步加載的方式來欺騙yslow對於dom節點的評分,但是異步加載真的適合 我們的網站麼?同樣,別人寫了一篇文章,出了一個原則,一個最佳實踐,但是你確定他說的情況適合你的情況麼?網站有大有小,大小不同,需要考慮的東西也就 不同.

爲什麼對於淘寶的圖片來說,使用不同的hostname是個更優的方案呢?

首先,因爲淘寶網的特殊性,淘寶網大多數訪問者都是回頭客,他們電腦裏大多緩存着dns記錄.這種情況,如果是小網站或者新興網站可能要考慮,因爲新用戶比較多,可能dns請求的消耗更大一些,而且第一印象對於這些網站來說更爲重要.

再者,淘寶裏的圖片很多,一個頁面裏通常會用到幾十張甚至上百張圖片,在這種情況下,我們更需要突破瀏覽器的http連接數的限制,以便加快加載速 度,這時候加載速度的考慮優先級遠遠高於DNS的影響,而yslow中對於DNS的着重考慮可能更偏向中小網站,圖片比較少的網站.

對於DNS請求或者tcp(tcp握手之類的也會消耗請求時間)請求之類的分配和解析的消耗,還有一個辦法是keeplive,讓你的鏈接保持keeplive,這樣可以只建立一次鏈接,然後傳輸多個文件,可以有效減少建立連接的時間.

(2) 減少服務器壓力

過多的http請求對於服務器來說是很危險的,如果你的服務器不是很強,請把這一條考慮放在第一位,其他的優化策略都只是優化,而這裏涉及到的是服務器,你要保證你的服務器能正常運轉.

當然如果你是在淘寶的話,你就可以安心坐下來跟一羣牛人談論爲什麼要忽略http對服務器的影響,因爲我們要記住:我們是前端開發工程師,我們是在 做前端優化,後臺和我們無關,因爲我們有足夠強大的技術支持和硬件支持,當網站的技術發展到一定程度的時候,我們的關注點應該向用戶那裏偏重,因爲用戶看 到的纔是我們最終要展示的,用戶感受到的體驗和速度纔是我們要達到的速度,後臺我們做的再快,前臺呈現慢了,我們的服務器消耗少了,省錢了,但是用戶卻因 此拋棄了我們,一切都是白費.所以,當後臺足夠支撐你不用你去考慮後臺壓力的時候,那就安心考慮如何做好前臺的工作吧.

Yslow真的是一個誤導人的工具,只要我們按照它的原則對網站進行優化,肯定最後可以拿到高分來欺騙老闆,但是對於有些場景,這些優化往往是一種 對性能的破壞,例如淘寶網的商城首頁,爲了提高Yslow評分,所有的圖片都採用了一個hostname,分數提高了,但是並行加載少了,不過商城首頁都 是異步渲染和異步加載的,所以這種影響看起來並不明顯.

商城首頁有很多針對yslow的優化點,當然大多數優化是正確的,例如:導航那裏,本來是全部寫在頁面裏的,不要小看那個導航,裏面有N個鏈接節 點,以至於從瀏覽器裏複製源代碼的時候瀏覽器會卡死,因爲字節數太多了,這裏yslow肯定不會饒過的,後來我們把導航做成了異步加載的,評分理所當然上 去了.但是這是淘寶網,我們有足夠的速度來提供足夠的用戶體驗.如果你的服務器提供不了這種速度,也承受不了這種頻繁的異步請求的話,這種優化就要慎重 了,延遲可能造成導航不可用.這也是針對場景來協調的.

淘寶現在在廣泛部署CDN,CDN可以給我們提供足夠的後臺資源保障,在CDN和後臺環境不斷萬善的情況下,考慮重點應該更加專注於前臺傳輸速度和展現解析速度的提升.

(3)   合併腳本和樣式?

其實在前一篇文章裏的那段討論也是對於不同應用場景的不同考慮,

減少http請求數的一個方法,對於前端來說,那就是合併腳本和樣式文件,稱爲combo,通過將多個文件合併成一個文件,然後一次性傳輸到客戶 端,這樣可以減少http請求,的確是個有效的方法,甚至對於一些特殊的頁面,例如首頁,我們把樣式和腳本都寫在了頁面裏,根本沒有分離出來,他們不會產 生http請求,當然,也不會被緩存,這是被犧牲的代價.

爲什麼我們要這麼做,因爲首頁的訪問量很大?這樣可以有效減少http請求數?恩,這只是一部分原因,的確這樣做有這樣的好處,而且對於assets服務器不夠強大的網站來說,在併發量大的首頁上實行這一套是很有效的.

但是,淘寶訪問量最大的頁面並不是首頁,而是detail頁面,也就是商品詳情頁!

這纔是我們討論的重點,爲什麼首頁採用combo甚至寫在頁面裏,而detail則按照正常的樣式和腳本來引用.首頁是類似靜態的頁面,detail則是應用型的.首頁沒有腳本,依然可以起到導向的作用,但是detail頁腳本沒有運行起來的話,甚至無法購買商品.

其實在這裏這樣討論並不能明顯看出問題所在,因爲淘寶在這些方面也不是很成熟,detail頁引用了大量腳本和樣式,很多內容是多餘的過期的.

這從本質上來說代表兩種網頁類型,一種是內容型,一種則是應用型.對於內容型的網站,腳本並不是很重要(甚至樣式),因爲沒有腳本,用戶仍然可以瀏 覽頁面,只是可能有些效果看不到而已,所以我們可以把腳本合併起來,一起放在body底部,在頁面內容都加載完後,再一次性加載進來.而對於應用型的網 頁,讓應用跑起來纔是最重要的,因爲沒有應用這個網頁就變得沒有意義了,這時候,按需加載腳本是一種趨勢,我們需要先把應用的基本框架和功能按需加載進 來,讓它們分別運行起來,而不是一起等腳本加載完再一起初始化,我們需要應用能夠快速響應用戶,

而且還是說到CDN,當CDN變得足夠強的時候,連接數已經不是瓶頸,我們應該更多考慮怎麼讓網頁更快的展現給用戶,對於無需腳本也可以提供服務的 內容型的網頁,將腳本放在頁面底部,合併起來(減少連接數,我們仍然需要減少連接數,在不需要太快的使用腳本的情況下),而對於應用型的網頁,我們需要盡 快讓功能運轉,甚至讓他們一部分一部分按優先級初始化,這時候就要將腳本分開,按需加載.

(4)   減少http請求頭

http頭是個龐大的傢伙,你打開taobao.com的首頁,alert一下document.cookie,會發現淘寶網的cookie是如此 龐大,甚至比小型網頁都大,每次你請求淘寶的服務器都會往返一次這些數據,還有一些其他的頭部信息,佔用的空間也不小,可想而知這種消耗有多大.

然後其實自從用了CDN,這一切都無需考慮太多,因爲CDN和淘寶主站不在一個域名下,cookie不會互相污染,而CDN的域名下基本是沒有 cookie和頭部信息的,所以每次請求靜態資源的時候,不會帶着主站的cookie到處跑,而只是傳輸資源的主題內容,所以這對於性能的影響在使用 cdn之後會變得很小.但是如果你的靜態資源服務器和主服務器在一個域名下,那就要控制好cookie和其他頭部信息的大小了,因爲每次傳送都會傳送他 們.

最後

總之,優化原則不是絕對的,對於不同的場景應該考慮不同的側重點,別人的解決方案對於你來說不一定是最優的,應該針對自己的網站規模和類型進行適度的優化,不能盲目追求標準和最佳實踐.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章