前面的話
對內容資源的存儲、協調以及管理的職責統稱為Web主機托管。主機托管是Web服務器的主要功能之一。保存并提供內容,記錄對內容的訪問以及管理內容都離不開服務器。如果不想自行管理服務器所需的軟硬件,就需要主機托管服務,即托管者。本文將詳細介紹Web主機托管
主機托管
在萬維網的早期,每個組織自行購買自己的計算機硬件,搭建自己的計算機房,申請自己的網絡連接,并管理自己的Web服務器軟件。隨著Web迅速成為主流,每人都想要一個網站,但很少有人有能力或時間來搭建帶空調的服務器機房,注冊域名,或購買網絡帶寬。為了滿足人們的迫切需求,出現了很多新的企業,提供了專業化管理的Web主機托管服務。服務級別有多種,從物理上的設備管理(提供空間、空調以及線纜)到完整的Web主機托管,顧客只需要提供內容就行了
下面主要探討托管Web服務器要提供什么服務。網站運作需要的很多東西(例如,它支持不同語言的能力和進行安全的電子商務交易的能力)都取決于托管Web服務器提供的功能
假設Joe的五金商店和Mary的古董拍賣店都需要網站。Irene網絡服務提供商那里有很多機架,機架上全是一樣的高性能Web服務器,可以租給Joe和Maiy,這樣,他倆就不用自行購買自己的服務器并管理服務器軟件了
在下圖中,Joe和Mary都簽約使用Irene的網絡服務提供商提供的專用Web托 管服務。Joe租了專用的Web服務器,該服務器是Irene網絡服務提供商購買和維護的。Mary也從Irene網絡服務提供商那里租了另一個專用服務器。Irene網絡服務提供商大批量地購買服務器硬件,它們選擇的硬件經久耐用且相對便宜。如果Joe或Mary的網站變得更受歡迎,Irene網絡服務提供商可以立刻給Joe或Mary提供更多的服務器

在這個例子中,瀏覽器向Joe服務器的IP地址發送對www.joes-hardware.com的HTTP請求,向Mary服務器(不同于Joe)的IP地址發送對www.marys-antiques.com的請求
虛擬主機托管
許多人想要在Web上展現自己,但他們的網站流量都不大。對這些人來說,使用專用的Web服務器可能有點兒大材小用,因為他們每月花費數百美元租來的服務器大部分時間都是空閑的
許多Web托管者通過讓一些顧客共享一臺計算機來提供便宜的Web主機托管服務。這稱為共享主機托管或虛擬主機托管。每個網站看起來是托管在不同的服務器上,但實際上是托管在同一個物理服務器上。從最終用戶的角度來看,被虛擬托管的網站應當和托管在專用服務器上的網站沒什么區別
從成本效益、空間以及管理方面考慮,提供虛擬主機托管的公司希望能在同一個服務器上托管數十、上百,甚至上千個網站——但這不一定意味著上千個網站是用一臺PC機來提供服務的。托管者可以創建成排同樣的服務器,稱為服務器集群(server farm),把負載分攤在群里的服務器上。因為群里的每臺服務器都一樣,并且托管了許多虛擬網站,所以管理起來更加方便
當Joe和Mary剛開始商務運作時,他們可能會選擇虛擬主機托管,以節省費用,直到他們網站的流量規模達到值得使用專用服務器的水平為止

【主機信息】
不幸的是,HTTP/1.0中的一個設計缺陷會使虛擬主機托管者抓狂。HTTP/1.0規范中沒有為共享的Web服務器提供任何方法來識別要訪問的是哪一個托管的網站
回想一下,HTTP/1.0請求在報文中只發送了URL的路徑部分。如果要訪問http://www.joes-hardware.com/index.html,瀏覽器會連接到服務器www.joes-hardware.com,但HTTP/1.0請求中只提到GET/index.html,沒有提到主機名。如果服務器虛擬托管了多個站點,就沒有足夠的信息能指出要訪問的是哪個虛擬網站

如果客戶端A試圖訪問http://www.joes-hardware.com/index.html,請求GET/index.html將被發送到共享的Web服務器
如果客戶端B試圖訪問http://www.marys-antiques.com/index.html,同樣的請求GET/index.html也將被發送到共享的Web服務器
就Web服務器而言,沒有足夠的信息可供其判斷究竟要訪問的是哪個網站。盡管請求的是完全不同的文檔(來自不同的網站),但這兩個請求看起來是一樣的,這是因為網站的主機信息已經從請求中剝離了
[注意]HTTP替代物(反向代理)和攔截代理也都需要明確的站點信息
缺失的主機信息是原始HTTP規范的疏忽,它錯誤地假設了每個Web服務器上只托管了一個網站。HTTP的設計者沒有為進行虛擬主機托管的共享服務器提供支持。正因為如此,URL中的主機名信息被當作冗余信息剝離了,只要求發送路徑部分
因為早期的規范沒有考慮到虛擬主機托管,Web托管者需要開發變通的方案和約定來支持共享的虛擬主機托管。這個問題本可以通過要求所有HTTP清求報文發送完整的URL而不只是路徑部分來簡單地解決。而HTTP/1.1的確要求服務器能夠處理HTTP報文請求行上的完整URL,但將現存的應用程序都升級到這個規范還需要很長時間。在此期間,涌現了以下4種技術
1、通過URL路徑進行虛擬主機托管
可以通過分配不同的URL路徑,用這種笨方法把共享服務器上的虛擬站點隔離開。例如,可以給每個邏輯網站一個專門的路徑前綴
Joe的五金商店可以是:http://www.joes-hardware.com/joe/index.html
Mary的古董拍賣店可以是:http://www.marys-antiques.com/mary/index.html
當請求到達服務器時,其中并沒有主機名信息,但服務器可以通過路徑來區分它們
請求Joe的五金商店的網址是GET /joe/index.html
請求Mary的古董拍賣店的網址是GET /mary/index.html
這不是一個好辦法。/joe和/mary這樣的前綴是多余的(主機名中已經提到joe了)
更糟的是,描述主頁鏈接的常見約定:http://www.joes-hardware.com或http://www. joes-hardware.com/index.html 都不能用了
總之,按URL來進行虛擬主機托管是一個糟糕的解決方案,很少會用到
2、通過端口號進行主機托管
除了修改路徑名,還可以在Web服務器上為Joe和Mary的網站分配不同的端口號。不再使用端口 80,而是采用其他端口號,例如,Joe用82,Mary用83。但這個解決方案也有同樣的問題:終端用戶不會樂意在URL中指定非標準的端口號
3、通過IP地址進行主機托管
為不同的虛擬站點分配專門的IP地址,把這些地址都綁定到一臺單獨的機器上。這樣,Web服務器就可以通過IP地址來識別網站名了
一個更常用的、更好的方法是通過IP地址進行虛擬化。每個虛擬網站都分配一個或多個唯一的IP地址。所有虛擬網站的IP地址都綁定到同一個共享的服務器上。服務器可以查詢HTTP連接的目的IP地址,并以此來判斷客戶端的目標網站
比方說,托管者把IP地址209.172.34.3分配給www.joes-hardware.com,把IP地址209.172.34.4分配給www.marys-antiques.com,把這兩個IP地址都綁定到同一個物理服務器上。Web服務器就能使用目的IP地址來識別用戶請求的是哪個虛擬站點了

客戶端A獲取http://www.joes-hardware_com/index.html;客戶端A査詢www.joes-hardware.com的IP地址,得到209.172.34.3;客戶端A打開到共享服務器的TCP連接,目的地址是209.172.34.3;客戶端A發送請求,內容為GET/index.html HTTP/1.0;在Web服務器提供響應之前,它注意到實際的目的IP地址(209.172.34.3),判斷出這是Joe的五金網站的虛擬IP地址,就根據子目錄/joe來完成請求。返回的是文件/joe/index.html
類似地,如果客戶端B請求http://www.marys-antiques.com/index.html。客戶端B査詢www.marys-antiques.com的IP地址,得到209.172.34.4;客戶端B打開到Web服務器的TCP連接,目的地址是209.172.34.4;客戶端B發送請求,內容是GET/index.html HTTP/1.O;Web服務器判斷出209.172.34.4是Mary的網站,根據/mary目錄來完成請求,返問的是文件/mary/index.html
對大的托管者來說,虛擬IP的主機托管能夠工作,但它會帶來一些麻煩
a、在計算機系統上能綁定的虛擬IP地址通常是有限制的。想在共享的服務器上托管成百上千的虛擬站點的服務商不一定能實現愿望
b、IP地址是稀缺資源。有很多虛擬站點的托管者不一定能為被托管的網站獲取足夠多的IP地址
c、托管者通過復制服務器來增加容量時,IP地址短缺的問題就更嚴重了。隨負載均衡體系的不同,可能會要求每個復制的服務器上有不同的虛擬IP地址,因此IP地址的需求量可能會隨復制服務器的數量而倍增
盡管虛擬IP的主機托管存在消耗地址的問題,但它仍然得到了廣泛的運用
4、通過Host首部進行虛擬主機托管
為了避免過度的地址消耗和虛擬IP地址的限制,我們希望在虛擬站點間共享同一個IP地址,且仍能區分站點。但正如我們看到的那樣,因為大多數瀏覽器只是把URL的路徑發給服務器,關鍵的虛擬主機名信息被其丟掉了
為了解決這個問題,瀏覽器和服務器的實現者擴展了HTTP,把原始的主機名提供給服務器。不過,瀏覽器不能只發送完整的URL,因為這會使許多只能接收路徑的服務器無法工作。替代的方法是,把主機名(和端口號)放在所有請求的Host擴展首部中傳送
下圖中,客戶端A和客戶端B都發送了攜帶有要訪問的原始主機名的Host首部。當服務器收到對/index.html的請求時,可以通過Host擴展首部來判斷要使用哪個資源

Host首部最早是在HTTP/1.0+中引入的,它是開發商實現的HTTP/1.0的擴展超集。遵循HTTP/1.1標準則必須支持Host首部。絕大多數現代瀏覽器和服務器都支持Host首部,但仍有一些客戶端和服務器(以及網絡機器人)不支持它
Host首部
Host首部是HTTP/1.1的請求首部,定義在RFC 2068中。由于虛擬服務器的流行,絕大多數HTTP客戶端(即使是不遵循HTTP/1.1的客戶端),都實現了Host首部
Host首部描述了所請求的資源所在的因特網主機和端口號,和原始的URL中得到的一樣:
Host = "Host" ":" host [ ":" port ]
但要注意以下問題:如果Host首部不包含端口,就使用地址方案中默認的端口;如果URL中包含IP地址,Host首部就應當包含同樣的地址;如果URL中包含主機名,Host首部就必須包含同樣的名字;如果URL中包含主機名,Host首部就不應當包含URL中這個主機名對應的IP地址,因為這樣會擾亂虛擬主機托管服務器的工作,它在同一個IP地址上堆疊了很多虛擬站點;如果URL中包含主機名,Host首部就不應當包含這個主機名的其他別名,因為這樣也會擾亂虛擬主機托管服務器的工作;如果客戶端顯式地使用代理服務器,客戶端就必須把原始服務器,而不是代理服務器的名字和端口放在Host首部中。以往,若干個Web客戶端在啟用客戶端代理設置時,錯誤地把發出的Host首部設置成代理的主機名。這種錯誤行為會使代理和原始服務器都無法正常處理請求;Web客戶端必須在所有請求報文中包含Host首部;Web代理必須在轉發請求報文之前,添加Host首部;HTTP/1.1的Web服務器必須用400狀態碼來響應所有缺少Host首部字段的HTTP/1.1請求報文
下面是一段簡單的HTTP請求報文,用于獲取www.joes-hardware.com的主頁,其中帶有必須的Host首部字段

有少量在用的老式瀏覽器不會發送Host首部。如果某個虛擬主機托管服務器使用Host首部來判斷所服務的是哪個網站,而報文中沒有出現Host首部的話,那它可能會把用戶導向某個默認的Web頁面(例如網絡服務提供商的Web頁面),也可能返回一個錯誤頁面建議用戶升級瀏覽器
對于沒有進行虛擬主機托管,而且不允許資源隨請求主機的不同而變化的原始服務器來說,可以忽略Host首部字段的值。但資源會隨主機名的不同而變化的原始服務器,都必須在一條HTTP/1.1請求判斷其所請求的資源時使用下列規則
1、如果HTTP請求報文中的URL是絕對的(也就是說,包含方案和主機部分),就忽略Host首部的值
2、如果HTTP請求報文中的URL沒有主機部分,而該請求帶有Host首部,則主機/端口的值就從Host首部中取
3、如果通過第(1)步或第(2)步都無法獲得有效的主機,就向客戶端返回400 Bad Request 響應
某些版本的瀏覽器發送的Host首部不正確,尤其是配置使用代理的時候。例如,配置使用代理時,一些老版本的Apple和PointCast客戶端會錯誤地把代理的名字,而不是原始服務器的名字放在Host首部里發送
網站運作
在下面列出的這些時間段內,網站通常是無法運作的:服務器宕機的時候;交通擁堵:突然間很多人都要看某個特別的新聞廣播或涌向某個大甩賣網店。突然的擁堵可以使Web服務器過載,降低其響應速度,甚至使它徹底停機;網絡中斷或掉線
下面會展示一些預判和處理這些常見問題的方法
【鏡像的服務器集群】
服務器集群是一排配置相同的Web服務器,互相可以替換。每個服務器上的內容可以通過鏡像復制,這樣當某個服務器出問題的時候,其他的可以頂上
鏡像的服務器常常組成層次化的關系。某個服務器可能充當“內容權威”——它含有原始內容(可能就是內容作者上傳的那個服務器)。這個服務器稱為主原始服務器(master origin server)。從主原始服務器接收內容的鏡像服務器稱為復制原始服務器(replica origin server)。一種簡單的部署服務器集群的方法是用網絡交換機把請求分發給服務器。托管在服務器上的每個網站的IP地址就設置為交換機的IP地址
下圖顯示的鏡像服務器集群中,主原始服務器負責把內容發送給復制原始服務器。對集群外部來說,內容所在的IP地址就是交換機的IP地址。交換機負責把請求發送到服務器上去

鏡像Web服務器可以在不同的地點包含同樣內容的副本。下圖展示了4個鏡像服務器,其中主服務器在芝加哥,復制服務器在紐約,邁阿密和小石城。主服務器為芝加哥地區的客戶端服務,并肩負把內容傳播給復制服務器的任務

在上圖的場景中,有以下兩種方法把客戶端的請求導向特定的服務器
1、HTTP重定向
該內容的URL會解析到主服務器的IP地址,然后它會發送重定向到復制服務器
2、DNS重定向
該內容的URL會解析到4個IP地址,DNS服務器可以選擇發送給客戶端的IP地址
【內容分發網絡(CDN)】
簡單地說,內容分發網絡(CDN)就是對特定內容進行分發的專門網絡。這個網絡中的節點可以是Web服務器、反向代理或緩存
1、CDN中的反向代理緩存
復制原始服務器可以用反向代理(也稱為替代物)緩存來代替。反向代理緩存可以像鏡像服務器一樣接受服務器請求。它們代表原始服務器中的一個特定集合來接收服務器請求。根據內容所在的IP地址的廣告方式,原始服務器和反向代理緩存之間通常有協作關系,到特定的原始服務器的請求就由反向代理緩存來接收
反向代理和鏡像服務器之間的區別在于反向代理通常是需求驅動的。它們不會保存原始服務器的全部內容副本,它們只保存客戶端請求的那部分內容。內容在其髙速緩存中的分布情況取決于它們收到的請求,原始服務器不負責更新它們的內容。為了更容易地訪問“熱點”內容(就是高請求率的內容),有些反向代理具有“預取”特性,可以在用戶請求之前就從服務器上載入內容
CDN中帶有反向代理時,可能會由于存在代理的層次關系而增加其復雜性
2、CDN中的代理緩存
與反向代理不同,傳統的代理緩存能收到發往任何Web服務器的請求。在代理緩存與原始服務器之間不需要有任何工作關系或IP地址約定。但是與反向代理比起來,代理緩存的內容一般都是按需驅動的,不能指望它是對原始服務器內容的精確復制。某些代理緩存也可以預先載入熱點內容
按需驅動的代理緩存可以部署在其他環境中——尤其是攔截環境,在這種情況下,2層或3層設備(交換機或路由器)會攔截Web流量并將其發送給代理緩存
攔截環境依賴于在客戶端和服務器之間設置網絡的能力。這樣,所有合適的HTTP請求才能真正發送到緩存中去。根據收到的請求,將內容分布在緩存中
【加速訪問】
上面提到的很多技術也能幫助網站更快地加載。服務器集群和分布式代理緩存或反向代理服務器分散了網絡流量,可以避免擁塞。分發內容使之更靠近終端用戶,這樣從服務器到客戶端的傳輸時間就更短了。請求和響應穿過因特網,在客戶端和服務器間傳輸的方式是影響資源訪問速度最主要的因素
加速網站訪問的另一種方法是對內容進行編碼以便更快地傳輸。比如,對內容進行壓縮,但前提是接收的客戶端能夠把內容解壓縮
文章列表