開發(fā)出高性能的網(wǎng)站,第三部分:壓縮和其他服務器端的技術 - 2005-05-01
作者 Thomas A. Powell 和 Joe Lima
在第一部分 , 我們講了代碼優(yōu)化的20個技巧,這些代碼優(yōu)化都是針對開發(fā)者源代碼的;在第二部分 , 我們談了緩沖控制。我們在此第三部分中,將來和大家一起看看其他的服務器端的技術,來提升網(wǎng)站的速度,我們先來看看HTTP壓縮。
什么是HTTP壓縮?
HTTP 壓縮(或叫HTTP內(nèi)容編碼)作為一種網(wǎng)站和網(wǎng)頁相關的標準,存在已久了,只是最近幾年才引起大家的注意。HTTP壓縮的基本概念就是采用標準的gzip 壓縮或者deflate編碼方法,來處理HTTP響應,在網(wǎng)頁內(nèi)容發(fā)送到網(wǎng)絡上之前對源數(shù)據(jù)進行壓縮。有趣的是,在版本4的IE和NetScape中就早 已支持這個技術,但是很少有網(wǎng)站真正使用它。Port80軟件公司做的一項調(diào)查顯示,財富1000強中少于5%的企業(yè)網(wǎng)站在服務器端采用了HTTP壓縮技 術。不過,在具有領導地位的網(wǎng)站,如Google、Amazon、和Yahoo!等,HTTP內(nèi)容編碼技術卻是普遍被使用的。考慮到這種技術會給大型的網(wǎng) 站們帶來帶寬上的極大節(jié)省,用于突破傳統(tǒng)的系統(tǒng)管理員都會積極探索并家以使用HTTP壓縮技術。
我們可以在瀏覽器發(fā)出的Accept
請求的頭部看到HTTP內(nèi)容編碼的鍵值。我們來看看Mozilla Firefox瀏覽器的這個請求,如下,我們特別注意一下Accept
,Accept-Language
,Accept-Encoding
,和 Accept-Charset
的頭(header):
GET / HTTP/1.1
Host: www.port80software.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040206 Firefox/0.8
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,
text/plain;q=0.8,video/x-mng,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
這些個"Accept"
值
會被服務器用到,進而決定將適當?shù)膬?nèi)容通過內(nèi)容協(xié)商(Content
Negotiation)發(fā)回來—這是非常有用的功能,它可以讓網(wǎng)站服務器返回不同的語言、字符集、甚至還可以根據(jù)使用者的習慣返回不同的技術。關于內(nèi)容
協(xié)商的討論很多,我們這就不再多講。我們主要來看看和服務器端壓縮有關的一些東西。Accept-Encoding
表明了瀏覽器可接受的除了純文本之外的內(nèi)容編碼的類型,比如gzip壓縮還是deflate壓縮內(nèi)容。
我們下面來看看IE發(fā)出的請求headers,我們可以看到類似的Accept-Encoding
值:
GET / HTTP/1.1
Host: www.google.com
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)
Accept: image/gif,image/x-xbitmap,image/jpeg,image/pjpeg,
application/vnd.ms-excel,application/vnd.ms-powerpoint,application/msword,
application/x-shockwave-flash,*/*
Accept-Encoding: gzip,deflate
Accept-Language: en-us
Connection: keep-alive
假設當今主流的每種瀏覽器都支持gzip和deflate編碼(那些不支持的也不會發(fā)出Accept-Encoding
),我們可以簡單的修改一下網(wǎng)站服務器,從而返回壓縮內(nèi)容到這些瀏覽器上,并返回標準(也就是沒有壓縮的)內(nèi)容到其他的瀏覽器上。在下例中,如果我們的瀏覽器告訴Google它不接受內(nèi)容編碼,我們會取回3,358字節(jié)的數(shù)據(jù);如果我們發(fā)出Accept-Encoding
,再加上應答header告訴我們Content-Encoding: gzip
,我們則會取回僅僅1,213字節(jié) 。用瀏覽器的查看源代碼功能來看源代碼,我們看不出什么差異,但如果使用網(wǎng)絡跟蹤的話,我們就會發(fā)現(xiàn)其響應是不同的。
圖一: Google壓縮 / 非壓縮對比
上例中,雖然文件不大,但是效果依然很明顯—壓縮后比原來小了74%。再加上我們前面兩部分談到的HTML、CSS、和JavaScript代碼優(yōu)化,Google在提升網(wǎng)站性能上的成果非常驚人—它的一個網(wǎng)頁居然可以放在一個TCP響應包里。
雖 然Google在帶寬上的考慮也遠遠超出其他一般的網(wǎng)站,HTTP內(nèi)容編碼進一步讓HTML、CSS、和JavaScript等瘦身50%甚至更多。不好 的地方是,HTTP內(nèi)容編碼(詞語‘壓縮’和‘內(nèi)容編碼’在本文中基本上是一個意思) 基本上針對文本內(nèi)容很有效,對于圖像和其他二進制文件的壓縮效果就一般了,有時可能根本沒有效果,但總的來說,即使有很多二進制文件的時候,整體上可以瘦 身15%到30%那么多。
HTTP內(nèi)容編碼的服務器端支持
如果你現(xiàn)在認同HTTP壓縮的 價值,下一個大問題是:你如何來實施?在Apache網(wǎng)站服務器上,可以使用mod_deflate來進行HTTP內(nèi)容的編碼。在微軟的IIS上,就有些 麻煩了。雖然IIS 5可以支持gzip的編碼壓縮,但實施起來還是超級麻煩,尤其考慮到因為各種瀏覽器中細微差異來進行各種細致參數(shù)調(diào)整的時候。所以在IIS 5上,還是要考慮第三方的采用ISAPI過濾器的壓縮插件,比如httpZip 就是最好的一種。IIS 6上集成了壓縮功能,也更快更靈活,但是還是配置起來比較復雜。ZipEnable 帶給我們第一個專為IIS 6集成壓縮細致管理的工具—并且還有瀏覽器兼容情況監(jiān)測功能。
服務器內(nèi)容編碼的實質(zhì)
當 實施HTTP壓縮時,要平衡考慮一些因素;如果將服務器配置成‘輸出’的內(nèi)容壓縮方式,雖然可以降低帶寬的使用,但同時卻增加了CPU的開銷。多數(shù)情況 下,這不是什么大問題,尤其當網(wǎng)站服務器所作工作很少的時候。不過,在網(wǎng)絡瀏覽很繁重的網(wǎng)站服務器上,運行相當多的動態(tài)內(nèi)容就可能會達到CPU工作的極 限,這時再進而進行壓縮的話,CPU可能會超負荷運行了。通過添加而外的服務器硬件資源,當然可能會減輕這種問題,并讓我們享受通過壓縮而節(jié)省下來的帶 寬, 但最后帶寬和CPU的問題還是要看哪個成本更高。
說到底,系統(tǒng)管理員和網(wǎng)站開發(fā)者是否對HTTP的壓縮有興趣,還是要看最 后的效果如何。當我們明顯的發(fā)現(xiàn)帶寬的負載下來了,那么訪問者也可能會明顯感覺轉載網(wǎng)頁的速度慢了。因為,壓縮產(chǎn)生和解壓縮會帶來的CPU負載, TTFB (time to first byte)也通常會增加,這樣瀏覽器渲染網(wǎng)頁的速度也會降下來,但這還算是很好的平衡,因為數(shù)據(jù)壓縮后傳輸?shù)陌冃×恕⒆兩倭耍峤坏乃俣葧兛欤@個快 速回補償網(wǎng)頁渲染的慢速。然而,對于寬帶用戶來說,這樣的改善可能就不明顯了。不過,這兩種情況下,對于網(wǎng)站建設者來說,都可以節(jié)省一些網(wǎng)絡上的投資。當 然,如果可感知的反應時間對某網(wǎng)站來說是主要目標,并且網(wǎng)站的訪問者很多都還使用撥號上網(wǎng),那么本文的第二部分鐘所講的緩沖控制就是比較好的性能提高策 略。
最后,HTTP內(nèi)容編碼的另一個潛在問題是和由腳本產(chǎn)生的網(wǎng)頁帶來的服務器負載有關的,比如PHP和ASP。在此種情況下, 主要的問題是,網(wǎng)頁內(nèi)容每次請求可能會被再壓縮,這樣就會給服務器增加更多的負載(相對壓縮靜態(tài)內(nèi)容來說)。如果,網(wǎng)站中所有的網(wǎng)頁都是在請求時生成的 話,那么使用HTTP內(nèi)容編碼就得格外小心了。還好,很多商業(yè)上使用的壓縮插件,直到如何對內(nèi)容進行緩沖,但業(yè)余(較便宜的)的壓縮工具可能就沒有這些特 性了。
動態(tài)網(wǎng)頁:立即生成,還是稍后生成?
有趣的是,很多的開發(fā)者都是在網(wǎng)站被訪問時開 始動態(tài)的生成很多甚至全部他們網(wǎng)站的網(wǎng)頁。比如,http://www.domain.com/article.php?id=5就是一個通用的URL, 它暗示了某個網(wǎng)頁是由數(shù)據(jù)庫查詢時或填充模版生成的。這種常用方法的問題是,在很多情況下,在請求時間生成一個網(wǎng)頁是pointless的,因為很多時候 這個主要的靜態(tài)的(所謂的靜態(tài)的動態(tài)網(wǎng)頁、或腳本網(wǎng)頁),其內(nèi)容很長時間也不變化,這顯然對于提高網(wǎng)頁裝載速度沒有什么幫助。實際上,在一個高負荷的網(wǎng)站 這種方式會嚴重的降低服務期的性能。
要避免不必要的動態(tài)網(wǎng)頁的生成,有一個方法是,每次有變化時,則預先生成有內(nèi)容的靜態(tài). html網(wǎng)頁。如果這些生成的.html網(wǎng)頁,還是經(jīng)過了代碼優(yōu)化(在本文第一部分中過這些描述方法),則更好。這不僅會讓服務器交付這些網(wǎng)頁更快變得更 容易,而且這些技術還會使搜索引擎更友好。
不幸的是,在很多情況下,簡單的生成動態(tài)的HTML網(wǎng)頁并不太容易,也為很多網(wǎng)頁只有 在網(wǎng)頁被訪問時才能夠正確的生成動態(tài)內(nèi)容。在這種情況下,你最好是對網(wǎng)頁進行‘烘焙’生成快速執(zhí)行的形式。在ASP .NET的情況下,這種形式則是二進制代碼,在服務器端執(zhí)行的特別快。不好的地方是,在用戶訪問之前,服務器需要先執(zhí)行這些網(wǎng)頁強制執(zhí)行這些字節(jié)代碼。還 好,在ASP .NET 2.0中,這些問題將得到改善。在PHP中,一些諸如Zend等的優(yōu)化軟件是不錯的投資。
對于提交靜態(tài) 和動態(tài)網(wǎng)頁、或者HTML和圖像的不同需要來說,考慮一下針對物理服務器或其他的硬件上的加速可能,也是比較明智的選擇。為了網(wǎng)頁加速而加強硬件方面的投 入的另一個方法是專業(yè)化—不同的部件進行不同的工作,這樣產(chǎn)生出最大的效率。雖然,本文是從代碼和網(wǎng)站服務器校對來說明如何提高網(wǎng)站的性能的,我們也不妨 討論討論其他相關的元素。
對網(wǎng)站服務器進行渦輪增壓
加速網(wǎng)站要考慮的一個重點是服務器軟 件和服務器硬件。先談軟件,網(wǎng)站系統(tǒng)管理員不太可能來回因為易用性問題、性能問題、安全問題等在Apache和IIS之間切換來切換去。簡言之,網(wǎng)站服務 器和其底層的操作系統(tǒng)之間的關系錯綜復雜、互相影響,再進行系統(tǒng)或服務遷移則更是繁重且有風險的工作。所以,你如果真的考慮放棄一種網(wǎng)站服務器而使用另一 種的話,你必須嚴肅認真的好好考慮這個問題;而如果速度是考慮的第一要素的話,建議你考慮一下Zeus。
再談硬件,如果要考慮升 級硬件,則先仔細分析一下服務器上的主要任務。在靜態(tài)網(wǎng)站上,主要的工作是調(diào)整網(wǎng)絡連接和把文件從磁盤拷貝到網(wǎng)絡上。要加速這樣類型的網(wǎng)站,你得把注意力 放在高速硬盤子系統(tǒng)和高速網(wǎng)絡子系統(tǒng)上,另外還得有足夠多的內(nèi)存來處理并發(fā)請求。實際上,你可能得給服務器添加大量的內(nèi)存,從而為經(jīng)常使用的對象盡可能的 增加內(nèi)存緩沖來減輕磁盤的存取。有趣的是,CPU的速度在這里卻不是十分關鍵。雖然不能否認CPU對網(wǎng)站的整體性能有影響,但瓶頸主要發(fā)生在磁盤上。但 是,當網(wǎng)站處理動態(tài)網(wǎng)頁和靜態(tài)網(wǎng)頁差不多一樣多的時候,處理器就顯得很關鍵了,但即便如此高速磁盤或雙網(wǎng)卡還是更有效一些。另一種情況下,除了要處理動態(tài) 網(wǎng)頁,還要處理其他占用CPU的操作(比如SSL和HTTP壓縮等)的時候,CPU就顯得十分關鍵了。換句話說,要加速網(wǎng)站服務時,服務器具體所作的工作 決定著什么類型的硬件資源更需要增強。
當你沒有那么多增加服務器硬件或軟件的預算時,還有一些物美價廉的解決方法。比如,你可以 對服務器的TCP/IP設置進行優(yōu)化,這樣依賴TCP/IP網(wǎng)絡的HTTP便可以最優(yōu)運行。TCP/IP的設置優(yōu)化里,有一項是TCP的接受窗口,可以把 它調(diào)整成最適合應用或者最適合網(wǎng)絡連接的,或者是針對確保TCP連接的一些參數(shù)(如ACK或TCP_NODELAY等)進行調(diào)整,根據(jù)具體情況設置成使用 或不使用。還有一些參數(shù),比如TIME_WAIT時間等,也是可以進行調(diào)整的。但要記住,不管怎么調(diào)整這些網(wǎng)站服務或操作系統(tǒng)的參數(shù),都必須進行真實的加 載試驗以驗證你的調(diào)整會不會反而減慢用戶訪問的服務或帶來新的問題。此外,一定要弄懂這些參數(shù)之后,再進行調(diào)整。
通過分工進行加速
網(wǎng)站加速還可以考慮的一個出發(fā)點是,不同的網(wǎng)站內(nèi)容可能會擁有不同的提交特性。考慮到不同的內(nèi)容,其特性也不同,我們可以用多個服務器,每個服務器來執(zhí)行不同的內(nèi)容處理,這樣可能比用服務器池(server farm)中的每一個服務來處理同樣的任務要好得多。
我 們來看一個分工進行加速的簡單例子。當你的商務網(wǎng)站給購物車或外部網(wǎng)使用SSL加密的時候,你會發(fā)現(xiàn)當有多個用戶同時訪問的時候,SSL加密帶來 HTTPS段的明顯負載會使你的服務器的性能會急劇下降。這種情況下,把流量分配給另一臺服務器,其意義就十分明顯了。比如,把你的主站點放在 www.domain.com上,把結賬的處理部分放在shop.domain.com上。這個shop.domain.com就是一個專門處理SSL流 量的服務器,可能會用到SSL加速卡。采取分工的方式,可以讓你專心處理結賬的用戶的SSL流量,而不至于像以往SSL的處理會導致服務器整體性能的下 降。對于圖像和其他重量級的二進制的比如PDF文檔或.exe文檔,服務器處理其下載可能要花些力氣,這些連接通常持續(xù)的時間比一般的連接都長,會消耗大 量寶貴的TCP/IP資源。進而,對于這些媒體資源(PDF、.exe、圖像等)的處理,我們也并不需要把它們和文本資源(HTML、CSS和 JavaScript等)等同對待處理。在這種情況下,讓處理文本資源的服務器有高性能的CPU,讓處理媒體資源的服務器有大帶寬,是有的放矢的解決之 道。
分工還可以進一步應用到網(wǎng)頁的生成上。我們可以考慮把生成網(wǎng)頁的工作單獨放在一個服務器上,把處理靜態(tài)內(nèi)容的工作放在另一個 服務器上。現(xiàn)在已然有很多網(wǎng)站是采取這樣的模式了,這其中很多網(wǎng)站會使用一個叫做Squid的反向代理(reverse proxy)。在設置過程中,代理服務器專門提供靜態(tài)的內(nèi)容,速度很快;而后臺的服務器則可以專心處理在訪問時才會產(chǎn)生的動態(tài)內(nèi)容。緩沖控制策略和規(guī)則, 我們在第二部分中談到過,在這時的設置過程中就顯得十分重要了;我們得確保代理服務器的緩沖中儲存的內(nèi)容在共享緩沖中是安全的。
為了爭奪市場而提速
我 們剛才談的那些東西主要是一些低成本的加速技術,在我們本文即將結束的時候,我們來看看一些需要軟硬件成本很高但收益可觀的方法。目前市場上提供有一些需 要花些錢的獨特加速設備,它們可以進行比如網(wǎng)絡連接分流、壓縮、緩沖、和其他等技術,從而達到加速的目的。 如果你不在乎投資高帶寬的話,這些解決方案就十分有效,但是大多數(shù)的網(wǎng)站還是更喜歡我們先前介紹過的物美價廉的方法,比如代碼優(yōu)化、緩沖、和HTTP編碼 等。
就算你有很多資金,可以投資一個服務器池(server farm)、并添加最高檔的加速設備,也使用壓縮和緩沖技術等,但你還是會最后達到一個極限。要想進一步再提速,還有最后一招:把內(nèi)容放在離訪問者最近的 地方,有可能的話,在那個地方再實施上述各類技術(如壓縮、緩沖等)。你肯定注意過,有些網(wǎng)站提供鏡像服務器等,這樣世界各地的訪問者就可以就近訪問所需 內(nèi)容。不過,還有比這個更有地理分布意義的方法,并且可以透明的讓訪問者使用。內(nèi)容分發(fā)網(wǎng)絡(Content Distribution Network – CDN),比如Akamai,就可以讓我們把重型內(nèi)容(如圖象和其他二進制內(nèi)容等)搬移到離訪問者更近的地方,這樣通過內(nèi)容分發(fā)網(wǎng)站在世界各地的邊緣緩 沖,訪問者訪問起來就會更快。這種方式帶來了性能上極大提高,目前世界級的一些大網(wǎng)站都在使用。雖然這算不上是經(jīng)濟實用的方法,但作為這些方法的最后補 充,放在這里以饗讀者。
Thomas A. Powell 是PINT公司的創(chuàng)始人,也是加州大學San Diego分校計算機科學系的講師,以及一些網(wǎng)頁開發(fā)書籍的作者,其所著書目包括《HTML & XHTML: The Complete Reference》和 《JavaScript: The Complete Reference》等。Joe Lima 是Port80軟件公司的首席構架師(architect),同時教授UCSD 擴展的服務器技術。
Port80軟件公司
Port80 Software, Inc. 是微軟 Internet Information Services (IIS) 網(wǎng)絡服務的領先的開發(fā)商. 公司同時提供w3compiler, 一套優(yōu)化代碼的桌面應用軟件。Port80 Software 是微軟認證合作商(MCP ISV)。它位于San Diego, CA. 更多信息請見公司網(wǎng)站 www.port80software.com.