11、使用內(nèi)容分發(fā)網(wǎng)絡(luò)
用戶與你網(wǎng)站服務(wù)器的接近程度會(huì)影響響應(yīng)時(shí)間的長短。把你的網(wǎng)站內(nèi)容分散到多個(gè)、處于不同地域位置的服務(wù)器上可以加快下載速度。但是首先我們應(yīng)該做些什么呢?
按地域布置網(wǎng)站內(nèi)容的第一步并不是要嘗試重新架構(gòu)你的網(wǎng)站讓他們在分發(fā)服務(wù)器上正常運(yùn)行。根據(jù)應(yīng)用的需求來改變網(wǎng)站結(jié)構(gòu),這可能會(huì)包括一些比較復(fù)雜的任務(wù),如在服務(wù)器間同步Session狀態(tài)和合并數(shù)據(jù)庫更新等。要想縮短用戶和內(nèi)容服務(wù)器的距離,這些架構(gòu)步驟可能是不可避免的。
要記住,在終端用戶的響應(yīng)時(shí)間中有80%到90%的響應(yīng)時(shí)間用于下載圖像、樣式表、腳本、Flash等頁面內(nèi)容。這就是網(wǎng)站性能黃金守則。和重新設(shè)計(jì)你的應(yīng)用程序架構(gòu)這樣比較困難的任務(wù)相比,首先來分布靜態(tài)內(nèi)容會(huì)更好一點(diǎn)。這不僅會(huì)縮短響應(yīng)時(shí)間,而且對(duì)于內(nèi)容分發(fā)網(wǎng)絡(luò)來說它更容易實(shí)現(xiàn)。
內(nèi)容分發(fā)網(wǎng)絡(luò)(Content DeliveryNetwork,CDN)是由一系列分散到各個(gè)不同地理位置上的Web服務(wù)器組成的,它提高了網(wǎng)站內(nèi)容的傳輸速度。用于向用戶傳輸內(nèi)容的服務(wù)器主要是根據(jù)和用戶在網(wǎng)絡(luò)上的靠近程度來指定的。例如,擁有最少網(wǎng)絡(luò)跳數(shù)(network hops)和響應(yīng)速度最快的服務(wù)器會(huì)被選定。
一些大型的網(wǎng)絡(luò)公司擁有自己的CDN,但是使用像Akamai Technologies,Mirror Image Internet, 或者Limelight Networks這樣的CDN服務(wù)成本卻非常高。對(duì)于剛剛起步的企業(yè)和個(gè)人網(wǎng)站來說,可能沒有使用CDN的成本預(yù)算,但是隨著目標(biāo)用戶群的不斷擴(kuò)大和更加全球化,CDN就是實(shí)現(xiàn)快速響應(yīng)所必需的了。以Yahoo來說,他們轉(zhuǎn)移到CDN上的網(wǎng)站程序靜態(tài)內(nèi)容節(jié)省了終端用戶20%以上的響應(yīng)時(shí)間。使用CDN是一個(gè)只需要相對(duì)簡單地修改代碼實(shí)現(xiàn)顯著改善網(wǎng)站訪問速度的方法。
12、為文件頭指定Expires或Cache-Control
這條守則包括兩方面的內(nèi)容:
對(duì)于靜態(tài)內(nèi)容:設(shè)置文件頭過期時(shí)間Expires的值為“Never expire”(永不過期)
對(duì)于動(dòng)態(tài)內(nèi)容:使用恰當(dāng)?shù)腃ache-Control文件頭來幫助瀏覽器進(jìn)行有條件的請求
網(wǎng)頁內(nèi)容設(shè)計(jì)現(xiàn)在越來越豐富,這就意味著頁面中要包含更多的腳本、樣式表、圖片和Flash。第一次訪問你頁面的用戶就意味著進(jìn)行多次的HTTP請求,但是通過使用Expires文件頭就可以使這樣內(nèi)容具有緩存性。它避免了接下來的頁面訪問中不必要的HTTP請求。Expires文件頭經(jīng)常用于圖像文件,但是應(yīng)該在所有的內(nèi)容都使用他,包括腳本、樣式表和Flash等。
瀏覽器(和代理)使用緩存來減少HTTP請求的大小和次數(shù)以加快頁面訪問速度。Web服務(wù)器在HTTP響應(yīng)中使用Expires文件頭來告訴客戶端內(nèi)容需要緩存多長時(shí)間。下面這個(gè)例子是一個(gè)較長時(shí)間的Expires文件頭,它告訴瀏覽器這個(gè)響應(yīng)直到2010年4月15日才過期。
Expires: Thu, 15 Apr 2010 20:00:00 GMT
如果你使用的是Apache服務(wù)器,可以使用ExpiresDefault來設(shè)定相對(duì)當(dāng)前日期的過期時(shí)間。下面這個(gè)例子是使用ExpiresDefault來設(shè)定請求時(shí)間后10年過期的文件頭:
ExpiresDefault "access plus 10 years"
要切記,如果使用了Expires文件頭,當(dāng)頁面內(nèi)容改變時(shí)就必須改變內(nèi)容的文件名。依Yahoo!來說我們經(jīng)常使用這樣的步驟:在內(nèi)容的文件名中加上版本號(hào),如yahoo_2.0.6.js。
使用Expires文件頭只有會(huì)在用戶已經(jīng)訪問過你的網(wǎng)站后才會(huì)起作用。當(dāng)用戶首次訪問你的網(wǎng)站時(shí)這對(duì)減少HTTP請求次數(shù)來說是無效的,因?yàn)闉g覽器的緩存是空的。因此這種方法對(duì)于你網(wǎng)站性能的改進(jìn)情況要依據(jù)他們“預(yù)緩存”存在時(shí)對(duì)你頁面的點(diǎn)擊頻率(“預(yù)緩存”中已經(jīng)包含了頁面中的所有內(nèi)容)。Yahoo!建立了一套測量方法,我們發(fā)現(xiàn)所有的頁面瀏覽量中有75~85%都有“預(yù)緩存”。通過使用Expires文件頭,增加了緩存在瀏覽器中內(nèi)容的數(shù)量,并且可以在用戶接下來的請求中再次使用這些內(nèi)容,這甚至都不需要通過用戶發(fā)送一個(gè)字節(jié)的請求。
13、Gzip壓縮文件內(nèi)容
網(wǎng)絡(luò)傳輸中的HTTP請求和應(yīng)答時(shí)間可以通過前端機(jī)制得到顯著改善。的確,終端用戶的帶寬、互聯(lián)網(wǎng)提供者、與對(duì)等交換點(diǎn)的靠近程度等都不是網(wǎng)站開發(fā)者所能決定的。但是還有其他因素影響著響應(yīng)時(shí)間。通過減小HTTP響應(yīng)的大小可以節(jié)省HTTP響應(yīng)時(shí)間。
從HTTP/1.1開始,web客戶端都默認(rèn)支持HTTP請求中有Accept-Encoding文件頭的壓縮格式:
Accept-Encoding: gzip, deflate
如果web服務(wù)器在請求的文件頭中檢測到上面的代碼,就會(huì)以客戶端列出的方式壓縮響應(yīng)內(nèi)容。Web服務(wù)器把壓縮方式通過響應(yīng)文件頭中的Content-Encoding來返回給瀏覽器。
Content-Encoding: gzip
Gzip是目前最流行也是最有效的壓縮方式。這是由GNU項(xiàng)目開發(fā)并通過RFC 1952來標(biāo)準(zhǔn)化的。另外僅有的一個(gè)壓縮格式是deflate,但是它的使用范圍有限效果也稍稍遜色。
Gzip大概可以減少70%的響應(yīng)規(guī)模。目前大約有90%通過瀏覽器傳輸?shù)幕ヂ?lián)網(wǎng)交換支持gzip格式。如果你使用的是Apache,gzip模塊配置和你的版本有關(guān):Apache 1.3使用mod_zip,而Apache 2.x使用moflate。
瀏覽器和代理都會(huì)存在這樣的問題:瀏覽器期望收到的和實(shí)際接收到的內(nèi)容會(huì)存在不匹配的現(xiàn)象。幸好,這種特殊情況隨著舊式瀏覽器使用量的減少在減少。Apache模塊會(huì)通過自動(dòng)添加適當(dāng)?shù)腣ary響應(yīng)文件頭來避免這種狀況的出現(xiàn)。
服務(wù)器根據(jù)文件類型來選擇需要進(jìn)行g(shù)zip壓縮的文件,但是這過于限制了可壓縮的文件。大多數(shù)web服務(wù)器會(huì)壓縮HTML文檔。對(duì)腳本和樣式表進(jìn)行壓縮同樣也是值得做的事情,但是很多web服務(wù)器都沒有這個(gè)功能。實(shí)際上,壓縮任何一個(gè)文本類型的響應(yīng),包括XML和JSON,都值得的。圖像和PDF文件由于已經(jīng)壓縮過了所以不能再進(jìn)行g(shù)zip壓縮。如果試圖gizp壓縮這些文件的話不但會(huì)浪費(fèi)CPU資源還會(huì)增加文件的大小。
Gzip壓縮所有可能的文件類型是減少文件體積增加用戶體驗(yàn)的簡單方法。
14、配置ETag
Entitytags(ETags)(實(shí)體標(biāo)簽)是web服務(wù)器和瀏覽器用于判斷瀏覽器緩存中的內(nèi)容和服務(wù)器中的原始內(nèi)容是否匹配的一種機(jī)制(“實(shí)體”就是所說的“內(nèi)容”,包括圖片、腳本、樣式表等)。增加ETag為實(shí)體的驗(yàn)證提供了一個(gè)比使用“last-modifieddate(上次編輯時(shí)間)”更加靈活的機(jī)制。Etag是一個(gè)識(shí)別內(nèi)容版本號(hào)的唯一字符串。唯一的格式限制就是它必須包含在雙引號(hào)內(nèi)。原始服務(wù)器通過含有ETag文件頭的響應(yīng)指定頁面內(nèi)容的ETag。
HTTP/1.1 200 OK
Last-Modified: Tue, 12 Dec 2006 03:03:59 GMT
ETag: "10c24bc-4ab-457e1c1f"
Content-Length: 12195
稍后,如果瀏覽器要驗(yàn)證一個(gè)文件,它會(huì)使用If-None-Match文件頭來把ETag傳回給原始服務(wù)器。在這個(gè)例子中,如果ETag匹配,就會(huì)返回一個(gè)304狀態(tài)碼,這就節(jié)省了12195字節(jié)的響應(yīng)。 GET /i/yahoo.gif HTTP/1.1
Host: us.yimg.com
If-Modified-Since: Tue, 12 Dec 2006 03:03:59 GMT
If-None-Match: "10c24bc-4ab-457e1c1f"
HTTP/1.1 304 Not Modified
ETag的問題在于,它是根據(jù)可以辨別網(wǎng)站所在的服務(wù)器的具有唯一性的屬性來生成的。當(dāng)瀏覽器從一臺(tái)服務(wù)器上獲得頁面內(nèi)容后到另外一臺(tái)服務(wù)器上進(jìn)行驗(yàn)證時(shí)ETag就會(huì)不匹配,這種情況對(duì)于使用服務(wù)器組和處理請求的網(wǎng)站來說是非常常見的。默認(rèn)情況下,Apache和IIS都會(huì)把數(shù)據(jù)嵌入ETag中,這會(huì)顯著減少多服務(wù)器間的文件驗(yàn)證沖突。
Apache 1.3和2.x中的ETag格式為inode-size-timestamp。即使某個(gè)文件在不同的服務(wù)器上會(huì)處于相同的目錄下,文件大小、權(quán)限、時(shí)間戳等都完全相同,但是在不同服務(wù)器上他們的內(nèi)碼也是不同的。
IIS 5.0和IIS6.0處理ETag的機(jī)制相似。IIS中的ETag格式為Filetimestamp:ChangeNumber。用ChangeNumber來跟蹤IIS配置的改變。網(wǎng)站所用的不同IIS服務(wù)器間ChangeNumber也不相同。不同的服務(wù)器上的Apache和IIS即使對(duì)于完全相同的內(nèi)容產(chǎn)生的ETag在也不相同,用戶并不會(huì)接收到一個(gè)小而快的304響應(yīng);相反他們會(huì)接收一個(gè)正常的200響應(yīng)并下載全部內(nèi)容。如果你的網(wǎng)站只放在一臺(tái)服務(wù)器上,就不會(huì)存在這個(gè)問題。但是如果你的網(wǎng)站是架設(shè)在多個(gè)服務(wù)器上,并且使用Apache和IIS產(chǎn)生默認(rèn)的ETag配置,你的用戶獲得頁面就會(huì)相對(duì)慢一點(diǎn),服務(wù)器會(huì)傳輸更多的內(nèi)容,占用更多的帶寬,代理也不會(huì)有效地緩存你的網(wǎng)站內(nèi)容。即使你的內(nèi)容擁有Expires文件頭,無論用戶什么時(shí)候點(diǎn)擊“刷新”或者“重載”按鈕都會(huì)發(fā)送相應(yīng)的GET請求。
如果你沒有使用ETag提供的靈活的驗(yàn)證模式,那么干脆把所有的ETag都去掉會(huì)更好。Last-Modified文件頭驗(yàn)證是基于內(nèi)容的時(shí)間戳的。去掉ETag文件頭會(huì)減少響應(yīng)和下次請求中文件的大小。微軟的這篇支持文稿講述了如何去掉ETag。在Apache中,只需要在配置文件中簡單添加下面一行代碼就可以了:
FileETag none
15、盡早刷新輸出緩沖
當(dāng)用戶請求一個(gè)頁面時(shí),無論如何都會(huì)花費(fèi)200到500毫秒用于后臺(tái)組織HTML文件。在這期間,瀏覽器會(huì)一直空閑等待數(shù)據(jù)返回。在PHP中,你可以使用flush()方法,它允許你把已經(jīng)編譯的好的部分HTML響應(yīng)文件先發(fā)送給瀏覽器,這時(shí)瀏覽器就會(huì)可以下載文件中的內(nèi)容(腳本等)而后臺(tái)同時(shí)處理剩余的HTML頁面。這樣做的效果會(huì)在后臺(tái)煩惱或者前臺(tái)較空閑時(shí)更加明顯。
輸出緩沖應(yīng)用最好的一個(gè)地方就是緊跟在<head />之后,因?yàn)镠TML的頭部分容易生成而且頭部往往包含CSS和JavaScript文件,這樣瀏覽器就可以在后臺(tái)編譯剩余HTML的同時(shí)并行下載它們。 例子:
... <!-- css, js -->
</head>
<?php flush(); ?>
<body>
... <!-- content -->
為了證明使用這項(xiàng)技術(shù)的好處,Yahoo!搜索率先研究并完成了用戶測試。
16、使用GET來完成AJAX請求
Yahoo!Mail團(tuán)隊(duì)發(fā)現(xiàn),當(dāng)使用XMLHttpRequest時(shí),瀏覽器中的POST方法是一個(gè)“兩步走”的過程:首先發(fā)送文件頭,然后才發(fā)送數(shù)據(jù)。因此使用GET最為恰當(dāng),因?yàn)樗恍璋l(fā)送一個(gè)TCP包(除非你有很多cookie)。IE中URL的最大長度為2K,因此如果你要發(fā)送一個(gè)超過2K的數(shù)據(jù)時(shí)就不能使用GET了。
一個(gè)有趣的不同就是POST并不像GET那樣實(shí)際發(fā)送數(shù)據(jù)。根據(jù)HTTP規(guī)范,GET意味著“獲取”數(shù)據(jù),因此當(dāng)你僅僅獲取數(shù)據(jù)時(shí)使用GET更加有意義(從語意上講也是如此),相反,發(fā)送并在服務(wù)端保存數(shù)據(jù)時(shí)使用POST。
聯(lián)系客服