摘自《高性能網(wǎng)站建設(shè)》
一、減少HTTP請(qǐng)求
通過減少組件的數(shù)量來減少HTTP請(qǐng)求的數(shù)量
1、圖片地圖
它允許在一個(gè)圖片上關(guān)聯(lián)多個(gè)URL,目標(biāo)URL的選擇取決于用戶單擊了圖片上的哪個(gè)位置。
當(dāng)使用N個(gè)分開的圖片,每個(gè)圖片對(duì)應(yīng)一個(gè)超鏈接,這樣就會(huì)產(chǎn)生N個(gè)HTTP請(qǐng)求,當(dāng)把N張圖片合并為一張的時(shí)候,然后以位置信息定位超鏈接,這樣就只剩下一個(gè)HTTP請(qǐng)求,同時(shí)保證功能的準(zhǔn)確實(shí)現(xiàn)。例如:
簡單的來講,就是通過使用合并圖片,用css中的background-image和background-position來顯示元素。
在background-position中,background-position:x y;x和y可以為負(fù)可以為正。圖片的左上方為(0,0),以(0,0)坐標(biāo)向右是為負(fù)數(shù)的x軸,以(0,0)坐標(biāo)向下是為負(fù)數(shù)的y軸。正值的情況則以圖片左下方為(0,0),向右是為正數(shù)的x軸,向上是為正數(shù)的y軸。
例如:
綜上兩個(gè):圖片地圖依賴于html實(shí)現(xiàn),css sprite依賴css實(shí)現(xiàn)。
3、合并腳本和樣式表
把js合并為一個(gè)文件,把css也合并為一個(gè)樣式表
二、使用內(nèi)容分發(fā)網(wǎng)絡(luò)
服務(wù)器離用戶越近,HTTP請(qǐng)求的響應(yīng)時(shí)間就會(huì)更短。
CNAME:別名記錄,當(dāng)多個(gè)域名需要指向同一服務(wù)器IP,可以使用一個(gè)域名做A記錄指向該服務(wù)器IP,然后讓多個(gè)域名指向該A記錄。
ICP:Internet Content Providor
DNS:Domain Name System
內(nèi)容分發(fā)網(wǎng)絡(luò)CDN:CDN是一組分布在多個(gè)不同地理位置的web服務(wù)器,通過將網(wǎng)站的資源發(fā)布到最接近用戶的網(wǎng)絡(luò)“邊緣”,供用戶就近取得所需內(nèi)容。CDN可以看做是一種緩存代理,主要用于對(duì)靜態(tài)資源(如image,css,js等)的緩存。
CDN網(wǎng)絡(luò)架構(gòu):
CDN的網(wǎng)絡(luò)架構(gòu)主要分為中心和邊緣兩個(gè)部分,中心服務(wù)器主要負(fù)責(zé)DNS解析和全局負(fù)載均衡;而邊緣服務(wù)器指異地節(jié)點(diǎn),作為CDN分發(fā)的載體,包括負(fù)載均衡和高速緩存。邊緣服務(wù)器的負(fù)載均衡負(fù)責(zé)緩存內(nèi)容的負(fù)載均衡,保證節(jié)點(diǎn)的工作效率,同時(shí)還負(fù)責(zé)與中心服務(wù)器通信,實(shí)現(xiàn)整個(gè)系統(tǒng)的負(fù)載均衡。邊緣服務(wù)器的高速緩存負(fù)責(zé)存儲(chǔ)從客戶源服務(wù)器獲取的資源,并提供給本地用戶訪問。
CDN的工作原理:
除了一些大型互聯(lián)網(wǎng)公司擁有自己的CDN,其他公司基本都會(huì)選擇CDN運(yùn)營商合作。
所以作為ICP,需要把域名解釋權(quán)交給CDN運(yùn)營商,操作時(shí)ICP修改自己的域名解析部分,一般用CNAME的方式,將自己的靜態(tài)資源域名指向一個(gè)CDN提供的CNAME。
而作為CDN運(yùn)營商,需要對(duì)CNAME提供專用DNS解析,同時(shí)需要維護(hù)客戶服務(wù)器的域名和IP地址映射列表。
CDN工作流程:
1、瀏覽器獲得需要訪問的資源的域名;
2、通過域名解析得到該域名指向CDN的一個(gè)CNAME;
3、為了獲得IP地址,需要對(duì)CNAME進(jìn)行域名解析,這時(shí)請(qǐng)求就會(huì)被發(fā)送到CDN的中心服務(wù)器,全局負(fù)載均衡通過預(yù)先設(shè)定的規(guī)則,同時(shí)根據(jù)用戶訪問的地理位置,把最合適的邊緣服務(wù)器IP地址返回;
4、瀏覽器獲得IP地址后,就向邊緣服務(wù)器發(fā)出請(qǐng)求;
5、邊緣服務(wù)器根據(jù)訪問域名,首先搜索緩存,查看資源是否存在,存在則直接返回資源給瀏覽器,直接完成整個(gè)資源請(qǐng)求過程,否則就根據(jù)緩存內(nèi)部的DNS解析得到資源實(shí)際IP地址(即客戶的服務(wù)器IP地址),向該IP地址發(fā)起資源請(qǐng)求;
6、邊緣服務(wù)器向客戶服務(wù)器請(qǐng)求資源成功后,就把該資源加入本身的高速緩存中,并把資源發(fā)送給用戶。
CDN的簡單應(yīng)用
其實(shí)CDN的使用并沒有和我們想象中那么遙遠(yuǎn),JQuery應(yīng)該是當(dāng)今Web開發(fā)領(lǐng)域使用最為廣泛的js框架之一,很多時(shí)候我們的網(wǎng)站都需要引用一個(gè)jquery.min.js的引用,我們可以將這個(gè)js文件存儲(chǔ)在自己的服務(wù)器,或者更好的選擇:使用大公司的CDN服務(wù)提供的jquery.min.js. 微軟和google都提供了jquery的CDN免費(fèi)服務(wù),你只需做的事情就是在項(xiàng)目中引用它們,就能享受CDN帶來的便利。
延伸:http://www.chinaz.com/web/2015/0309/388408.shtml
http://www.chinaz.com/web/2015/0414/398330.shtml
http://www.chinaz.com/web/2014/1112/373825.shtml
三、添加Expires頭
什么是Expires頭?
Expires存儲(chǔ)的是一個(gè)用來控制緩存失效的日期。當(dāng)瀏覽器看到響應(yīng)中有一個(gè)Expires頭時(shí),它會(huì)和相應(yīng)的組件一起保存到其緩存中,只要組件沒有過期,瀏覽器就會(huì)使用緩存版本而不會(huì)進(jìn)行任何的HTTP請(qǐng)求。Expires設(shè)置的日期格式必須為GMT。
HTTP1.1協(xié)議中緩存的另一種選擇
Expires存在著明顯的不足。
首先,Expires頭使用的是一個(gè)特定的時(shí)間,要求客戶端和服務(wù)器端的時(shí)鐘嚴(yán)格同步。何為嚴(yán)格同步?我們知道客戶端的時(shí)間是可以修改的,如果服務(wù)器和客戶端的時(shí)間不統(tǒng)一,這就導(dǎo)致有可能出現(xiàn)緩存提前失效的情況,存在不穩(wěn)定性。其次,假如Expires的日期到來了,那么還需要在服務(wù)器配置中提供一個(gè)新的日期。
面對(duì)這種情況,HTTP1.1引入了Cache-Control頭來克服Expires頭的限制。Cache-Control使用max-age制定組件被緩存多久,使用秒為單位,例如Cache-Control:max-age=3600;表示組件將被緩存60分鐘。如果max-age和Expires同時(shí)出現(xiàn),則max-age有更高的優(yōu)先級(jí),瀏覽器會(huì)根據(jù)max-age的時(shí)間來確認(rèn)緩存過期時(shí)間。
Cache-Control除了可以設(shè)置max-age之外,還可以同時(shí)設(shè)置其他標(biāo)簽。如下圖所示常用標(biāo)簽:
no-cache:實(shí)際上是可以存儲(chǔ)在本地緩存中,只是在與服務(wù)器進(jìn)行新鮮度再驗(yàn)證之前,不能提供緩存給客戶端使用
no-store:表示資源既不能被放入緩存,也不能被放入磁盤中,比no-chche指令更加嚴(yán)格
private:默認(rèn)值,表示代理服務(wù)器將不能緩存資源,只有客戶端能緩存
public:表示資源任何服務(wù)器都可以緩存
max-age:確定資源的緩存時(shí)間
如何配置過期緩存?
在ASP.NET下,可以通過web.config文件來配置緩存。
gzip編碼:gzip是GUNzip的縮寫,是使用無損壓縮算法的一種,最早是用于Unix系統(tǒng)的文件壓縮,憑借著良好的壓縮效率,現(xiàn)在已經(jīng)成為Web上使用最為普遍的數(shù)據(jù)壓縮格式。
壓縮是如何工作的?
客戶端請(qǐng)求報(bào)文中包含Accept-Encoding表示客戶端能識(shí)別的壓縮方法,如果客戶端請(qǐng)求報(bào)文沒有包含Accept-Encoding首部,服務(wù)器就會(huì)假設(shè)客戶端能夠接受任何編碼格式;服務(wù)器響應(yīng)報(bào)文中包含Content-Encoding表示采用的壓縮方法。(然而,一個(gè)統(tǒng)計(jì)表明,大約有15%的客戶端請(qǐng)求是沒有Accept-Encoding請(qǐng)求的,因?yàn)榭蛻舳说囊恍﹚eb代理和PC安全軟件會(huì)移除瀏覽器發(fā)出的Accept-Encoding,因?yàn)楸O(jiān)聽未經(jīng)壓縮的響應(yīng)會(huì)占用更少的CPU資源,但卻無疑增加了網(wǎng)絡(luò)傳輸?shù)臅r(shí)間。)
應(yīng)該對(duì)什么資源使用壓縮?
基于文本的資源如html,js,css,xml都適用于壓縮。然而對(duì)于圖片而言,卻不應(yīng)該對(duì)圖片進(jìn)行壓縮,因?yàn)閳D片本身是已經(jīng)被壓縮過了,如果再進(jìn)行g(shù)zip壓縮,有可能得到的結(jié)果是和圖片本身大小相差不大或更大,這樣就浪費(fèi)了服務(wù)器的CPU資源來做無用功了。
壓縮的優(yōu)缺點(diǎn)
優(yōu)點(diǎn):壓縮組件可以減少HTTP響應(yīng)時(shí)間,提升傳輸效率。
缺點(diǎn):服務(wù)器要通過花費(fèi)額外的CPU周期來完成壓縮,客戶端要對(duì)壓縮文件進(jìn)行解壓縮。
總體來說,使用壓縮還是利大于弊的,不過需要合理地使用壓縮,通過選擇對(duì)一定范圍大小的組件進(jìn)行壓縮和選擇要壓縮組件的類型,能使得收益最大化。
考慮代理緩存的情況
代理緩存服務(wù)器是一個(gè)中間層,位于客戶端和服務(wù)器之間。使用代理緩存的情況下,瀏覽器將不直接與服務(wù)器通信,而是通過代理發(fā)送請(qǐng)求。這種情況下,壓縮就要考慮額外的東西了。
首先,假設(shè)到達(dá)代理的是一個(gè)來自不支持gzip的瀏覽器的請(qǐng)求,代理會(huì)將請(qǐng)求轉(zhuǎn)發(fā)到web服務(wù)器,此時(shí)web服務(wù)器的響應(yīng)是未經(jīng)過壓縮的,這個(gè)響應(yīng)會(huì)把代理服務(wù)器緩存起來并發(fā)給瀏覽器?,F(xiàn)在,假設(shè)到達(dá)代理的第二個(gè)請(qǐng)求來自一個(gè)支持gzip瀏覽器,請(qǐng)求的是與之前相同的URL,代理會(huì)直接使用未經(jīng)壓縮的緩存響應(yīng),那么久失去了進(jìn)行壓縮的機(jī)會(huì)了??紤]更糟糕的情況,第一個(gè)請(qǐng)求來自支持gzip的瀏覽器,第二個(gè)請(qǐng)求來自不支持gzip的瀏覽器,這樣第二個(gè)請(qǐng)求得到的緩存響應(yīng)將無法被解碼,導(dǎo)致出錯(cuò)。
解決這一問題的方法就是在Web服務(wù)器的響應(yīng)中添加Vary頭,Vary:Accept-Encoding,表示web服務(wù)器告訴緩存服務(wù)器分別為每一個(gè)Accpet-Encoding請(qǐng)求頭緩存。在前面的例子中,代理通過識(shí)別Vary頭,對(duì)響應(yīng)緩存不同的版本,避免出錯(cuò)。
五、網(wǎng)站樣式和腳本
1、將樣式表放在頭部
可視性回饋的重要性
進(jìn)度指示器有三個(gè)主要優(yōu)勢(shì)——它們讓用戶知道系統(tǒng)沒有崩潰,只是正在為他或她解決問題;它們指出了用戶大概還需要等多久,以便用戶能夠在漫長的等待中做些其他事情;最后,它們能給用戶提供一些可以看的東西,使得等待不再是那么無聊。最后一點(diǎn)優(yōu)勢(shì)不可低估,這也是為什么推薦使用圖形進(jìn)度條而不是僅僅以數(shù)字形式顯示預(yù)期的剩余時(shí)間。在Web的世界里,Html頁面的逐步呈現(xiàn)就是很好的進(jìn)度指示器。
將沒有立即使用的css放在底部是錯(cuò)誤的做法
通常組件的下載是按照文檔中出現(xiàn)的順序下載的,所以將不需要立即使用到的組件css(比如需要用戶點(diǎn)擊登錄彈出框需要用到的樣式)放在底部,可以得到一個(gè)加載很快的頁面。然而這個(gè)推論其實(shí)是錯(cuò)誤的,IE8以下(包括IE8)的工作方式是如果css表仍在加載,構(gòu)建呈現(xiàn)樹就是一種浪費(fèi),因?yàn)樵谒袠邮奖砑虞d并解析完畢之前無需繪制任何東西,這時(shí)整個(gè)瀏覽器顯示都是空白,直到css加載完畢,這就失去了提供可視化回饋的機(jī)會(huì),讓用戶感覺到緩慢。
不過,更高級(jí)版本的IE和其他瀏覽器已經(jīng)克服了“白屏”問題,所以這種情況已經(jīng)不復(fù)存在。
無樣式內(nèi)容的閃爍
這里將討論另外一種出現(xiàn)的情況,當(dāng)我們將css放在底部,頁面可以正常逐步呈現(xiàn),但在css下載并解析完畢之后,已經(jīng)呈現(xiàn)的文字和圖片就要用新的樣式重繪了,這就是“無樣式內(nèi)容的閃爍”,這將是一種不好的用戶體驗(yàn)。
CSS的最佳擺放位置
使用LINK標(biāo)簽將樣式表放在文檔HEAD中。
二、將腳本放在底部
并行下載
瀏覽器下載組件的時(shí)候并不是每次只下載一個(gè)組件,而是實(shí)現(xiàn)了并行下載的機(jī)制。HTTP規(guī)范1.1建議瀏覽器從每個(gè)主機(jī)名并行地下載兩個(gè)組件。既假如頁面的所有組件都來自于一個(gè)主機(jī)名,則每次只能同時(shí)下載兩個(gè)組件。如果組件使用了兩個(gè)主機(jī)名,而且組件的主機(jī)名分配均勻,則每次并行下載的數(shù)量變成了2*2=4。不過,當(dāng)代的瀏覽器普遍實(shí)現(xiàn)都超過了2個(gè)并行下載,不同的瀏覽器設(shè)置都有所不同。
腳本阻塞下載
并行下載組件能加快頁面的加載速度,然而,在下載腳本的時(shí)候并行下載實(shí)際上是被禁用的,即使其他組件使用了不同的主機(jī)名,瀏覽器也不會(huì)啟動(dòng)其他的下載。原因如下:1. 腳本可能使用了document.write來修改頁面內(nèi)容,因此瀏覽器會(huì)等待,以確保能夠恰當(dāng)?shù)夭季郑?. 為了保證腳本能夠按照正確的順序執(zhí)行,如果并行下載多個(gè)組件,就無法保證響應(yīng)是按照特定順序到達(dá)瀏覽器的。
所以,腳本放在越靠近頂部的地方將越延遲用戶的可視化反饋,這不是一種良好的用戶體驗(yàn),會(huì)讓用戶感覺到緩慢。
最佳做法
放置腳本的最好地方是頁面的底部,這不會(huì)阻止頁面內(nèi)容的呈現(xiàn),而且頁面的可視化組件可以盡早下載。以博客園為例,博客園就把google流量分析的js放在底部,同時(shí)把下載Blog新聞和Blog側(cè)邊欄的js執(zhí)行函數(shù)放在了底部。
3、使用外部javascript和css
基礎(chǔ)知識(shí)
頁面瀏覽量(PV):用戶對(duì)頁面請(qǐng)求訪問次數(shù)總和。
內(nèi)聯(lián) VS 外置
對(duì)于兩個(gè)相同大小的頁面,一個(gè)使用了內(nèi)聯(lián),只有html需要下載,一個(gè)使用了外置,包括一個(gè)js和一個(gè)css,在用戶不帶緩存訪問頁面的時(shí)候,內(nèi)聯(lián)所有的js和css的效率更快,原因是外置js和css帶來額外的http請(qǐng)求開銷,1個(gè)http請(qǐng)求相對(duì)于3個(gè)http請(qǐng)求要更快一些。盡管如此,現(xiàn)實(shí)中還是使用外部文件會(huì)產(chǎn)生較快的訪問速度,這是由于外部js和css有機(jī)會(huì)被瀏覽器緩存起來,當(dāng)再次請(qǐng)求相同的js或css的時(shí)候,瀏覽器將不會(huì)發(fā)出http請(qǐng)求,而是使用緩存的組件,減少了總體需要下載文件的大小。
綜合來講,我們一般推薦使用外置的js和css,不過這也要根據(jù)自身web的訪問場(chǎng)景以及PV做出最優(yōu)選擇。
如何劃分組件?
當(dāng)我們決定使用外置js和css的時(shí)候,這時(shí)怎樣劃分js和css并打包到外部文件中成為一個(gè)首要考慮的問題。在典型情況下,頁面之間的js和css的重用既不可能100%重疊,也不可能100%無關(guān)。
一種極端的做法是創(chuàng)建一個(gè)單獨(dú)的,聯(lián)合了所有js的文件,再創(chuàng)建一個(gè)包含了所有css的文件。這只要求用戶生成一個(gè)Http請(qǐng)求,但它增加了用戶不帶緩存訪問的情況下的數(shù)據(jù)量,同時(shí)我們必須清楚:緩存有時(shí)會(huì)失效,這將帶來更多額外的開銷。而且,在任何一塊獨(dú)立的js或css改變后,都需要更新文件,并發(fā)布新的版本號(hào),這將使所有客戶端的舊版本緩存失效。
另一種極端的做法是為每個(gè)頁面提供一組分離的外部文件,這種方式真正做到按需下載,但缺點(diǎn)在于每個(gè)頁面都產(chǎn)生令響應(yīng)時(shí)間變慢的HTTP請(qǐng)求。
對(duì)于大多數(shù)web應(yīng)用來說,我們需要一種折中的方案!將頁面劃分為幾種頁面類型,然后為每種類型創(chuàng)建單獨(dú)的js和css。以css為例,我們可以創(chuàng)建一個(gè)所有頁面都通用的global.css,再針對(duì)不同類型的頁面,創(chuàng)建對(duì)應(yīng)的css。
六、減少DNS查找、避免重定向
1、減少DNS查找
基礎(chǔ)知識(shí)
DNS(Domain Name System): 負(fù)責(zé)將域名URL轉(zhuǎn)化為服務(wù)器主機(jī)IP。
DNS查找流程:首先查看瀏覽器緩存是否存在,不存在則訪問本機(jī)DNS緩存,再不存在則訪問本地DNS服務(wù)器。所以DNS也是開銷,通常瀏覽器查找一個(gè)給定URL的IP地址要花費(fèi)20-120ms,在DNS查找完成前,瀏覽器不能從host那里下載任何東西。
TTL(Time To Live):表示查找返回的DNS記錄包含的一個(gè)存活時(shí)間,過期則這個(gè)DNS記錄將被拋棄。
影響DNS緩存的因素
(1). 服務(wù)器可以設(shè)置TTL值表示DNS記錄的存活時(shí)間。本機(jī)DNS緩存將根據(jù)這個(gè)TTL值判斷DNS記錄什么時(shí)候被拋棄,這個(gè)TTL值一般都不會(huì)設(shè)置很大,主要是考慮到快速故障轉(zhuǎn)移的問題。
(2).瀏覽器DNS緩存也有自己的過期時(shí)間,這個(gè)時(shí)間是獨(dú)立于本機(jī)DNS緩存的,相對(duì)也比較短,例如chrome只有1分鐘左右。
(3). 瀏覽器DNS記錄的數(shù)量也有限制,如果短時(shí)間內(nèi)訪問了大量不同域名的網(wǎng)站,則較早的DNS記錄將被拋棄,必須重新查找。不過即使瀏覽器丟棄了DNS記錄,操作系統(tǒng)的DNS緩存也有很大機(jī)率保留著該記錄,這樣可以避免通過網(wǎng)絡(luò)查詢而帶來的延遲。
最佳實(shí)踐
當(dāng)客戶端的DNS緩存為空時(shí),DNS查找的數(shù)量與Web頁面中唯一主機(jī)名的數(shù)量相等。所以減少唯一主機(jī)名的數(shù)量就可以減少DNS查找的數(shù)量。
然而減少唯一主機(jī)名的數(shù)量會(huì)潛在地減少頁面中并行下載的數(shù)量,避免DNS查找降低了響應(yīng)時(shí)間,但減少并行下載可能會(huì)增加響應(yīng)時(shí)間。當(dāng)頁面的組件量比較多的時(shí)候,可以考慮將組件分別放到至少2-4個(gè)主機(jī)名,已獲得最大收益。
延伸:
http://www.chinaz.com/web/2015/0318/390930.shtml
http://www.chinaz.com/web/2015/0316/390234.shtml
http://www.chinaz.com/web/2015/0122/380042.shtml
http://www.chinaz.com/web/2015/0122/380039.shtml
2、避免重定向
什么是重定向?
重定向用于將用戶從一個(gè)URL重新路由到另一個(gè)URL。
常用重定向的類型
301:永久重定向,主要用于當(dāng)網(wǎng)站的域名發(fā)生變更之后,告訴搜索引擎域名已經(jīng)變更了,應(yīng)該把舊域名的的數(shù)據(jù)和鏈接數(shù)轉(zhuǎn)移到新域名下,從而不會(huì)讓網(wǎng)站的排名因域名變更而受到影響。
302:臨時(shí)重定向,主要實(shí)現(xiàn)post請(qǐng)求后告知瀏覽器轉(zhuǎn)移到新的URL。
304:Not Modified,主要用于當(dāng)瀏覽器在其緩存中保留了組件的一個(gè)副本,同時(shí)組件已經(jīng)過期了,這是瀏覽器就會(huì)生成一個(gè)條件GET請(qǐng)求,如果服務(wù)器的組件并沒有修改過,則會(huì)返回304狀態(tài)碼,同時(shí)不攜帶主體,告知瀏覽器可以重用這個(gè)副本,減少響應(yīng)大小。
重定向如何損傷性能?
當(dāng)頁面發(fā)生了重定向,就會(huì)延遲整個(gè)HTML文檔的傳輸。在HTML文檔到達(dá)之前,頁面中不會(huì)呈現(xiàn)任何東西,也沒有任何組件會(huì)被下載。
來看一個(gè)實(shí)際例子:對(duì)于ASP.NET webform開發(fā)來說,對(duì)于新手很容易犯一個(gè)錯(cuò)誤,就是把頁面的連接寫成服務(wù)器控件后臺(tái)代碼里,例如用一個(gè)Button控件,在它的后臺(tái)click事件中寫上:Response.Redirect("");然而這個(gè)Button的作用只是轉(zhuǎn)移URL,這是非常低效的做法,因?yàn)辄c(diǎn)擊Button后,先發(fā)送一個(gè)Post請(qǐng)求給服務(wù)器,服務(wù)器處理Response.Redirect("")后就發(fā)送一個(gè)302響應(yīng)給瀏覽器,瀏覽器再根據(jù)響應(yīng)的URL發(fā)送GET請(qǐng)求。正確的做法應(yīng)該是在html頁面直接使用a標(biāo)簽做鏈接,這樣就避免了多余的post和重定向。
重定向的應(yīng)用場(chǎng)景
(1). 跟蹤內(nèi)部流量
當(dāng)擁有一個(gè)門戶主頁的時(shí)候,同時(shí)想對(duì)用戶離開主頁后的流量進(jìn)行跟蹤,這時(shí)可以使用重定向。以yahoo.com為例,主頁新聞的鏈接主機(jī)名是http://hsrd.yahoo.com/,后面跟著識(shí)別的參數(shù),點(diǎn)擊后再產(chǎn)生一個(gè)301重定向,這樣就記錄了離開門戶主頁后的流量去向?! ?br>我們知道重定向是如何損傷性能的,為了實(shí)現(xiàn)更好的效率,可以使用Referer日志來跟蹤內(nèi)部流量去向。每個(gè)HTTP請(qǐng)求都有一個(gè)Referer表示原始請(qǐng)求頁(除了從書簽打開或直接鍵入U(xiǎn)RL等操作),記錄下每個(gè)請(qǐng)求的Referer,就避免了向用戶發(fā)送重定向,從而改善了響應(yīng)時(shí)間。
(2). 跟蹤出站流量
有時(shí)鏈接可能將用戶帶離你的網(wǎng)站,在這種情況下,使用Referer就不太現(xiàn)實(shí)了。
同樣也可以使用重定向來解決跟蹤出站流量問題。以百度搜索為例,百度通過將每個(gè)鏈接包裝到一個(gè)302重定向來解決跟蹤的問題,例如搜索關(guān)鍵字“跟蹤出站流量”,搜索結(jié)果的第一個(gè)URL為http://www.baidu.com/link?url=后面跟著一連串字符,即使搜索結(jié)果并沒有變,但這個(gè)字符串是動(dòng)態(tài)改變的,我認(rèn)為這里的搜索連接URL好像沒有改變的需要,不知道這里起到怎樣的作用?
除了重定向外,我們還可以選擇使用信標(biāo)(beacon)——一個(gè)HTTP請(qǐng)求,其URL中包含有跟蹤信息。跟蹤信息可以從信標(biāo)Web服務(wù)器的訪問日記中提取出來,信標(biāo)通常是一個(gè)1px*1px的透明圖片,不過204響應(yīng)更優(yōu)秀,因?yàn)樗。瑥膩聿槐痪彺?,而且絕不會(huì)改變?yōu)g覽器的狀態(tài)。
延伸:http://www.chinaz.com/web/2014/1029/372287.shtml
http://www.chinaz.com/web/2013/1212/330808.shtml
http://www.chinaz.com/web/2015/0409/397350.shtml
七、精簡js移除重復(fù)腳本
基礎(chǔ)知識(shí)
精簡:從javascript代碼中移除所有的注釋以及不必要的空白字符(空格,換行和制表符),減少javascript文件的大小。
混淆:和精簡一樣,會(huì)從javascript代碼中移除注釋和空白,另外也會(huì)改寫代碼。作為改寫的一部分,函數(shù)和變量的名字將被轉(zhuǎn)換為更短的字符串,所以進(jìn)一步減少了javascript文件的大小。
混淆的缺點(diǎn):
1. 缺陷:混淆過程本身很有可能引入錯(cuò)誤。
2. 維護(hù):由于混淆會(huì)改變javascript符號(hào),因此需要對(duì)任何不能改變的符號(hào)進(jìn)行標(biāo)記,防止混淆器修改它們。
3. 調(diào)試:經(jīng)過混淆的代碼很難閱讀,這使得在產(chǎn)品環(huán)境中更加難以調(diào)試。
相對(duì)而言,精簡出錯(cuò)的概率會(huì)少很多。
一個(gè)精簡和混淆的示例
使用JSMin進(jìn)行精簡,使用yuicompressor進(jìn)行混淆,原始js如下:
我們知道啟用gzip壓縮能減少組件的傳送大小,壓縮后精簡和混淆的差別會(huì)進(jìn)一步減少,綜合考慮混淆可能帶來的額外的風(fēng)險(xiǎn),所以優(yōu)先考慮使用精簡。不過,如果對(duì)于性能的極致追求,可以使用混淆,但要做足測(cè)試,確?;煜粫?huì)帶來其他的問題。
JQuery作為非常流行的前端框架,除了有開發(fā)版外,也提供了一個(gè)min版本,供實(shí)際部署web使用,這個(gè)min版本就使用了混淆,最大化地減少代碼總量。
2、移除重復(fù)腳本
出現(xiàn)重復(fù)腳本的原因
導(dǎo)致一個(gè)腳本的重復(fù)又兩個(gè)主要因素:團(tuán)隊(duì)大小和腳本數(shù)量。開發(fā)一個(gè)網(wǎng)站需要極大數(shù)量的資源,不同的團(tuán)隊(duì)需要構(gòu)建一個(gè)大型web的不同部分,當(dāng)團(tuán)隊(duì)整合和溝通工作沒有做足,則容易出現(xiàn)重復(fù)腳本的情況。當(dāng)然腳本數(shù)量也是重要的一環(huán),腳本數(shù)量越多越容易出現(xiàn)重復(fù)腳本的情況。
重復(fù)腳本如何損傷性能
在沒有緩存的情況下,如果在html中重復(fù)鏈接了相同的腳本,IE7以下(包括IE7)將會(huì)產(chǎn)生兩次HTTP請(qǐng)求,IE8以上則不會(huì)。
除了產(chǎn)生不必要的HTTP請(qǐng)求外,對(duì)腳本進(jìn)行重復(fù)執(zhí)行也會(huì)浪費(fèi)時(shí)間,腳本的重復(fù)執(zhí)行在瀏覽器中都存在。
如何避免重復(fù)腳本
(1). 形成良好的腳本組織。重復(fù)腳本有可能出現(xiàn)在不同的腳本包含同一段腳本的情況,有些是必要的,但有些卻不是必要的,所以需要對(duì)腳本進(jìn)行一個(gè)良好的組織。
(2). 實(shí)現(xiàn)腳本管理器函數(shù)。
八、配置ETag
什么是ETag?
實(shí)體標(biāo)簽(EntityTag)是唯一標(biāo)識(shí)了一個(gè)組件的一個(gè)特定版本的字符串,是web服務(wù)器用于確認(rèn)緩存組件的有效性的一種機(jī)制,通常可以使用組件的某些屬性來構(gòu)造它。
條件GET請(qǐng)求
瀏覽器下載組件的時(shí)候,會(huì)將它們存儲(chǔ)到瀏覽器緩存中。如果需要再次獲取相同的組件,瀏覽器將檢查組件的緩存時(shí)間,假如已經(jīng)過期,那么瀏覽器將發(fā)送一個(gè)條件GET請(qǐng)求到服務(wù)器,服務(wù)器判斷緩存還有效,則發(fā)送一個(gè)304響應(yīng),告訴瀏覽器可以重用緩存組件。
那么服務(wù)器是根據(jù)什么判斷緩存是否還有效呢?答案有兩種方式,一種是前面提到的ETag,另一種是根據(jù)最新修改時(shí)間。先來看看最新修改時(shí)間。
最新修改時(shí)間
原始服務(wù)器通過Last-Modified響應(yīng)頭來返回組件的最新修改時(shí)間。
以一個(gè)實(shí)際例子來說明,當(dāng)我們不帶緩存訪問www.google.com.hk的時(shí)候,我們需要下載google的logo,這時(shí)會(huì)發(fā)送這樣一個(gè)HTTP請(qǐng)求:
Request:
GET /logo.png HTTP 1.1
Host: www.google.com.hk
Response:
HTTP 1.1 200 OK
Last-Modified:Wed, 09 Oct 2013 01:35:39 GMT
當(dāng)需要再次訪問相同組件的時(shí)候,同時(shí)緩存已經(jīng)過期,瀏覽器會(huì)發(fā)送如下條件GET請(qǐng)求:
REQUEST:
GET /logo.png HTTP 1.1
If-Modified-Since:Wed, 09 Oct 2013 01:35:39 GMT
Host: www.google.com.hk
Response:
HTTP 1.1 304 Not Modified
實(shí)體標(biāo)簽
ETag提供了另外一種方式,用于檢測(cè)瀏覽器緩存中的組件與原始服務(wù)器上的組件是否匹配。
不帶緩存的請(qǐng)求:
Request:
GET /i/yahoo/gif HTTP 1.1
Host: us.yimg.com
Response:
HTTP 1.1 200 OK
Last-Modified:Tue,12 Dec 200603:03:59 GMT
ETag:”10c24bc-4ab-457elc1f“
再次請(qǐng)求相同組件:
Request:
GET /i/yahoo/gif HTTP 1.1
Host: us.yimg.com
If-Modified-Since:Tue,12 Dec 200603:03:59 GMT
If-None-Match:”10c24bc-4ab-457elc1f“
Response:
HTTP 1.1 304 Not Midified
當(dāng)ETag和Modified-Time都出現(xiàn)了,則原始服務(wù)器禁止返回304除非請(qǐng)求中的條件頭字段全部一致。
為什么要引入ETag?
ETag主要是為了解決Last-Modified無法解決的一些問題:
1. 一些文件也許會(huì)周期性的更改,但是他的內(nèi)容并不改變(僅僅改變的修改時(shí)間),這個(gè)時(shí)候我們并不希望客戶端認(rèn)為這個(gè)文件被修改了,而重新GET;
2. 某些文件修改非常頻繁,比如在秒以下的時(shí)間內(nèi)進(jìn)行修改,(比方說1s內(nèi)修改了N次),If-Modified-Since能檢查到的粒度是s級(jí)的,這種修改無法判斷(或者說UNIX記
錄MTIME只能精確到秒);
3. 某些服務(wù)器不能精確的得到文件的最后修改時(shí)間。
ETag帶來的問題
ETag的問題在于通常使用某些屬性來構(gòu)造它,有些屬性對(duì)于特定的部署了網(wǎng)站的服務(wù)器來說是唯一的。當(dāng)使用集群服務(wù)器的時(shí)候,瀏覽器從一臺(tái)服務(wù)器上獲取了原始
組件,之后又向另外一臺(tái)不同的服務(wù)器發(fā)起條件GET請(qǐng)求,ETag就會(huì)出現(xiàn)不匹配的狀況。
最佳實(shí)踐
1. 如果使用Last-Modified不會(huì)出現(xiàn)任何問題,可以直接移除ETag,google的搜索首頁則沒有使用ETag。
2. 確定要使用ETag,在配置ETag的值的時(shí)候,移除可能影響到組件集群服務(wù)器驗(yàn)證的屬性,例如只包含組件大小和時(shí)間戳。
九、圖像和Cookie優(yōu)化
1、 圖像優(yōu)化
圖像基礎(chǔ)知識(shí)
gif: 適用于動(dòng)畫效果,例如提示的滾動(dòng)條圖案 Web前端性能優(yōu)化教程 Web前端性能優(yōu)化 Web優(yōu)化 圖像優(yōu)化
jpg: 是一種使用有損壓縮的圖片格式,它將圖片的每個(gè)像素分解成8*8的柵格,然后對(duì)每個(gè)柵格的數(shù)據(jù)進(jìn)行壓縮處理,通過特殊的算法用附近的顏色填充柵格,隱藏細(xì)
節(jié)。用戶可以設(shè)置質(zhì)量級(jí)別,從0到100,數(shù)字越少圖片質(zhì)量就越差。
png:是一種使用無損壓縮的圖片格式,它將圖片上出現(xiàn)的顏色進(jìn)行索引,保留在“調(diào)色板”上,PNG在顯示圖像的時(shí)候就會(huì)調(diào)用調(diào)色板的顏色去填充相應(yīng)的位置。png
又分為png8,png24和png32;png8表示支持2^8個(gè)種顏色,通常情況下png8是最通用的web圖片格式。
選擇jpg還是png
對(duì)比jpg和png的特點(diǎn),不同的圖像使用不同的格式能得到最佳壓縮效果。對(duì)于層次豐富顏色較多的圖像,使用jpg更好,因?yàn)闉榱撕芎玫娘@示這種圖像,png將使用調(diào)
色板顏色更為豐富的png24,這樣圖片大小會(huì)比jpg大。而對(duì)于顏色簡單對(duì)比強(qiáng)烈的圖像,使用png更好,因?yàn)閜ng使用較少的調(diào)色板顏色就可以滿足顯示效果,而且得
到的圖片相對(duì)也比較小,而jpg是有損的,在清晰的顏色過渡周圍會(huì)有大色塊,影響顯示效果。
將png24|32轉(zhuǎn)化為png8
png圖片的優(yōu)化的很重要的一步:有些png24|32圖片本身顏色較為簡單,將其轉(zhuǎn)變?yōu)閜ng8得到的顯示效果很類似,但卻能極大地減少圖片的大小。這一步可以通過使
用工具pngGo來完成,這是一個(gè)完全免費(fèi)的工具,而且可以根據(jù)需要設(shè)置png所需要的調(diào)色板顏色數(shù),得到最大的壓縮效果。
使用smushit.it在線無損化壓縮
png格式將圖像信息保存在“塊”中,對(duì)于web顯示來說,大部分的“塊”都并非必要,所以優(yōu)化策略可以將它們安全地刪除。雅虎的YSlow提供了一個(gè)在線的無損化壓縮
工具smushit.it,不過基本上假如已經(jīng)將圖片轉(zhuǎn)變?yōu)閜ng8,使用smushit.it能壓縮的空間已經(jīng)很小了,不過對(duì)于追求極致性能的web來說,還是值得一試的。
2、優(yōu)化Cookie
什么是Cookie
Cookie是存儲(chǔ)在客戶端的一小段文本信息,伴隨著用戶請(qǐng)求在瀏覽器和服務(wù)器之間傳遞。Cookie除了核心對(duì)象key-value外,還有max-age,path,domain和httponly
屬性。httponly屬性標(biāo)識(shí)一個(gè)客戶端javascript能否操作這個(gè)Cookie;max-age表示緩存時(shí)間,單位為秒;domain代表域名,例如設(shè)置為.cnblog.com,則
i.cnblogs.com也可以訪問這個(gè)Cookie,如果設(shè)置為i.cnblogs.com,則image.cnblogs.com這個(gè)域名下的資源將不能訪問這個(gè)Cookie;path代表文件路徑,默認(rèn)為/,表
示可以該domain下的所有資源可以訪問這個(gè)Cookie。瀏覽器對(duì)單個(gè)Cookie大小限制不超過4KB;對(duì)于同一域名下Cookie的數(shù)量也有限制,一般不允許超過50個(gè)。
非持久Cookie和持久Cookie
假如Http請(qǐng)求響應(yīng)頭部Set-Cookie的時(shí)候沒有給Cookie添加一個(gè)過期時(shí)間,則它的默認(rèn)過期時(shí)間為當(dāng)前瀏覽會(huì)話結(jié)束,既退出瀏覽器這個(gè)Cookie就無效了,這個(gè)
Cookie就叫做非持久Cookie,因?yàn)槭谴鎯?chǔ)在瀏覽器進(jìn)程的內(nèi)存中的。
而如果給Cookie添加了一個(gè)過期時(shí)間,則Cookie信息將存儲(chǔ)到硬盤上,即使瀏覽器退出這個(gè)Cookie還是存在的。只要Cookie未被清除且還在過期時(shí)間以內(nèi),這個(gè)
Cookie就會(huì)在訪問對(duì)應(yīng)域名的時(shí)候發(fā)送給服務(wù)器。
減少Cookie的體積
由于Cookie在訪問對(duì)應(yīng)域名下的資源的時(shí)候都會(huì)通過Http請(qǐng)求發(fā)送到服務(wù)器,所以通過合理地設(shè)計(jì)Cookie,減少Cookie的體積,能夠減少Http請(qǐng)求報(bào)文的大小,提高
響應(yīng)速度。
通過使用不同的主機(jī)減少Cookie的使用
Cookie在訪問對(duì)應(yīng)域名下的資源的時(shí)候都會(huì)通過Http請(qǐng)求發(fā)送到服務(wù)器,但是在訪問一些資源(例如js腳本,css和圖片)的時(shí)候,大多數(shù)情況下這些Cookie是多余
的,所以我們可以通過使用不同的主機(jī)來存儲(chǔ)一些靜態(tài)資源,例如用專門的主機(jī)來存儲(chǔ)圖片,這樣訪問這些資源的時(shí)候就不會(huì)發(fā)送多余的Cookie,從而提高響應(yīng)速
度。
聯(lián)系客服