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