一、網站系統的組成
只要在一臺計算機上安裝了WEB服務器軟件,從功能上講,這臺計算機就可以稱為WEB服務器。一個網站的規模可大可小,功能可多可少,最簡單的網站只需要一臺Web服務器即可對外提供網頁瀏覽服務。復雜的網站包括多臺WEB服務器組成的群集系統、負載均衡設備、具有緩存功能的代理服務器(可以有多級,甚至包括放置在服務器端的緩存系統)、數據庫系統等,如圖2.2所示。

圖2.2
www.sina.com網站系統采用的基本上就是圖2.2所示的架構,不同地區的人們在訪問www.sina.com站點時,瀏覽器實際上所訪問的服務器是不一樣的,例如,吉林省的用戶訪問的服務器實際是sina放在吉林地區的代理服務器,湖北省的用戶訪問的服務器實際是sina放在湖北地區的代理服務器。各地區的瀏覽器訪問www.sina.com站點的過程如圖2.3所示。

圖2.3
為了能夠讓瀏覽器透明地訪問到WEB站點,讓用戶感覺不到是在訪問區域代理服務器,在DNS系統中需要將www.sina.com主機名指向所有的區域代理服務器的IP地址。在瀏覽器訪問www.sina.com站點中的頁面而向DNS服務器請求解析www.sina.com主機名時,DNS服務器根據訪問者的地理位置信息返回他附近的區域代理服務器的IP地址,這樣,瀏覽器的訪問請求將發送給該區域代理服務器。只有當區域代理服務器中沒有瀏覽器要訪問的頁面時,區域代理服務器才去從真正的www.sina.com站點服務器上獲取該頁面并進行緩存,以后該區域的其他瀏覽器就都可以就近從區域代理服務器中訪問到該頁面了,從而大大提高了訪問效率和減少了網絡流量。
WEB瀏覽器與WEB服務器建立連接后,除了將請求URL中的資源路徑發送給WEB服務器外,還會將URL中的主機名部分作為HTTP請求消息的Host頭發送給WEB服務器。例如,在瀏覽器地址欄中輸入http://www.it315.org,瀏覽器發送給www.it315.org主機上的WEB服務器的請求消息內容如下:
GET / HTTP/1.1<回車>
Host: www.it315.org<回車>
<回車>
WEB服務器接收到瀏覽器的訪問請求消息后,根據Host頭字段中所設置的主機名,就知道該選擇哪個WEB站點來進行響應,因此,可以使用不同的主機名來作為區分同一個WEB服務器上的不同站點的標識信息。
Tomcat的Server.xml配置文件中有一個<Host>元素,一個<Host>元素用于建立一個WEB站點,使用多個<Host>元素則可以建立多個WEB站點。<Host>元素的父級元素為<Engine>元素,嵌套在同一個<Engine>元素中的多個<Host>元素的name屬性不能相同,<Host>元素的name屬性指定WEB站點所對應的主機名稱。Tomcat的Server.xml配置文件中初始設置的<Host>元素內容如下:
<Host name="localhost" appBase="webapps" …>
…
</Host>
<Host>元素中的appBase屬性指定了一個路徑,該路徑將作為嵌套在它里面的<Context>元素的docBase屬性中設置的相對路徑的基準路徑。
當Tomcat接收到訪問請求時,將比較請求消息中的Host頭字段的值與<Host>元素的name屬性值,并以匹配的<Host>元素所創建的WEB站點來響應。如果Server.xml文件中沒有與請求消息的Host頭字段匹配的<Host>元素,Tomcat將以默認的WEB站點來響應。只要<Engine>元素的defaultHost屬性設置為嵌套在它里面的某個<Host>元素的name屬性值,該<Host>元素所創建的WEB站點就成了該引擎的默認WEB站點。例如,Tomcat的Server.xml文件中的<Engine>元素的默認設置如下:
<Engine name="Standalone" defaultHost="localhost" debug="0">
…
<Host name="localhost" appBase="webapps" …>
…
</Host>
…
</Engine>
上面的這段配置信息說明,該引擎的默認WEB站點為嵌套在<Engine>元素中的name屬性為“localhost”的<Host>元素所創建的WEB站點。
在同一臺計算機上建立了多個基于主機名的虛擬主機后,WEB瀏覽器要訪問其中的某個虛擬主機的資源時,在訪問URL中必須采用主機名,而不能采用IP地址。這是因為WEB瀏覽器要將URL中的主機名部分作為HTTP請求消息的Host頭發送給WEB服務器,如果URL中的主機名部分使用的是IP地址,那么,瀏覽器發出的請求消息中的Host頭字段的值就是這個IP地址,而在同一臺計算機上建立的多個基于主機名的虛擬主機共享同一個IP地址,在Host頭字段使用IP地址根本就無法區分不同的站點。
即使在URL中指定的是主機名時,WEB瀏覽器還是要先獲得該主機名所對應的IP地址,然后再使用這個IP去連接WEB服務器。所以,在建立基于主機名的虛擬主機時,除了要在Tomcat的server.xml文件中進行設置外,還需要在整個網絡系統中建立主機名與IP地址的映射關系,即必須將主機名添加到名稱解析系統,以便WEB瀏覽器能夠從名稱解析系統中查詢出主機名所對應的IP地址。建立主機名與IP地址的映射關系的慣用方式有兩種:一是使用客戶機本地的Hosts 文件,二是使用DNS(Domain Name System,域名系統)服務器。Hosts 文件和DNS的作用都是允許用戶使用“友好”的、文本格式的主機名稱,而不是數字格式的IP地址來訪問網絡中的計算機。Hosts文件可用于小型的Intranet(企業內部網),網絡中的所有計算機上都需要使用Hosts文件。DNS通常用于大型的網絡,特別是Internet上對外提供服務的計算機都是通過DNS來建立其主機名與IP地址的映射關系。客戶機首先在本地的Hosts文件中查找主機名稱所映射的IP地址,如果沒有找到,再去查詢DNS服務器。為了簡單起見,這里僅介紹一下Hosts文件。對于Windows 2000系統,Hosts 文件位于操作系統根目錄(取決操作系統所在的分區,通常是c:\winnt)下的System32\Drivers\Etc子目錄中,默認情況下,該文件中有如下一行內容:
127.0.0.1 localhost
這行文本的作用就是將IP地址(127.0.0.1)映射成主機名(localhost),這也就是在IE瀏覽器地址欄中可以使用localhost訪問本地WEB服務器的原因。如果要增加更多的主機名與IP地址的映射,可以在Hosts文件中增加更多的行,然后參照上面這行內容的格式在每行中填寫IP地址和相應的主機名。
:動手體驗:使用Tomcat建立基于主機名的虛擬主機
(1)用UltraEdit打開<Tomcat主目錄>/conf目錄下的Server.xml文件,使用“查找”菜單查找內容為“</Host>”的行,緊接該行下面增加一對<Host></Host>標簽。參照前面的<Host>標簽的屬性設置情況,設置新增的<Host>標簽的屬性,并在它里面嵌套一個設置該WEB站點根目錄的<Context>元素,最終的內容如下:
<Host name="site1" debug="0" appBase="d:\VirtualHost1">
<Context path="" docBase="." debug="0"/>
</Host>
這樣,將創建一個新的WEB站點。上面的<Context>元素的docBase屬性值被設置為一個點(.),即表示使用<Host>元素的appBase屬性中所設置的路徑作為這個<Context>所映射的目錄。
(2)在上面新增的<Host></Host>標簽對下面再增加一對<Host></Host>標簽,并將它設置為如下形式:
<Host name="site2" debug="0" appBase="d:\VirtualHost2">
<Context path="" docBase="." debug="0"/>
</Host>
這又創建了一個新的WEB站點,該站點的主機名稱為site2,根目錄對應的本地文件系統目錄為d:\VirtualHost2。
(3)在d:盤下創建名稱為VirtualHost1和VirtualHost2兩個目錄,并在這兩個目錄中分別創建一個名為test.html的文件,在d:\VirtualHost1\test.html文件中寫入如下一行內容:
這是d:\VirtualHost1目錄中的test.html文件
在d:\VirtualHost2\test.html文件中寫入如下一行內容:
這是d:\VirtualHost2目錄中的test.html文件
(4)保存修改后的Server.xml文件,重新啟動Tomcat WEB服務器程序。打開一個新的命令行窗口中,并在這個命令行窗口中執行如下命令:
telnet 127.0.0.1 8080
接著在連接成功的telnet程序命令窗口中,輸入如下內容:
GET /test.html HTTP/1.1<回車>
Host:<空格>site1<回車>
<回車>
這時在telnet程序窗口中可以看到,WEB服務器返回內容的正文部分為d:\VirtualHost1\test.html文件中的內容。接著WEB服務器返回內容的下邊,輸入如下內容:
GET /test.html HTTP/1.1<回車>
Host:<空格>site2<回車>
<回車>
在telnet程序窗口中又可以看到,WEB服務器這次返回內容的正文部分為d:\VirtualHost2\test.html文件中的內容。接著WEB服務器返回內容的下邊,輸入如下內容:
GET /test.html HTTP/1.1<回車>
Host:<空格><回車>
<回車>
在telnet程序窗口中又可以看到,WEB服務器這次返回內容的正文部分為d:\test\test.html文件中的內容。接著WEB服務器返回內容的下邊,再次輸入如下內容:
GET /test.html HTTP/1.1<回車>
Host:<空格>xxx<回車>
<回車>
在telnet程序窗口中又可以看到,WEB服務器這次返回內容的正文部分仍然為d:\test\test.html文件中的內容。
上面的整個交互過程如圖2.34所示,Tomcat根據第1次和第2次請求中所指定Host頭的值,查找Server.xml文件中與之相匹配的<Host>元素的name屬性值,并以匹配的<Host>元素所設置的WEB站點來響應;在第3次和第4次請求中所指定Host頭的值,在Server.xml文件中沒有與之對應的<Host>元素的name屬性值,Tomcat將以默認的WEB站點來響應。

圖2.34
(5)在Windows 2000系統中,用記事本程序打開c:\winnt\System32\Drivers\Etc\Hosts文件,可以看到有如下一行內容:
127.0.0.1 localhost
緊接這行文本的下面,用它復制出兩行文本,并將這兩行文本中的localhost分別修改成site1和site2,這樣,就使用Hosts文件為當前計算機設置了多個主機名。如果要用site1和site2這個兩主機名訪問其他計算機上的WEB站點,則應將127.0.0.1修改成其他計算機的實際IP地址。保存Hosts文件后,在命令行窗口中執行“ping site1”和“ping site2”命令,查看該主機名是否被正確解析到了相應的IP地址上。建立site1和site2與計算機IP地址的映射后,在IE瀏覽器地址欄中輸入http://localhost:8080/test.html、http://site1:8080/test.html和http://site2:8080/test.html,可以看到瀏覽器將顯示出各自站點中的test.html網頁文件的內容。
可見,使用主機名的方式在同一臺WEB服務器上創建多個虛擬主機后,在WEB瀏覽器中使用主機名訪問Web服務器時,Web服務器將選擇與該主機名關聯的WEB站點進行響應。通過這種方式,多個WEB站點可以共享同一個IP地址和相同的端口號,唯一不足的就是WEB瀏覽不能通過IP地址去訪問這些WEB站點。基于主機名的虛擬主機是目前Internet上的大多數虛擬主機業務提供商所通常采用的方式。只要找出幾個小型公司或個人的網站,如果在WEB瀏覽器地址欄中輸入“http://主機名”可以訪問到該WEB站點,接著在命令行窗口中執行“ping 主機名”,查看到該域名對應的IP地址,然后在WEB瀏覽器地址欄中輸入“http://IP地址”時,卻無法訪問這個WEB站點了,那么,這個WEB站點就是一個基于主機名的虛擬主機,它與其他一些WEB站點共享一臺WEB服務器,而不是自己獨享一臺WEB服務器。
注意:當使用安全套接字層 (SSL) 時,不能使用主機頭字段來實現虛擬主機,這是因為使用SSL的HTTP請求有加密保護。主機頭字段是加密內容的一部分,不能被解釋和路由到正確的站點。