<-
Apache > HTTP Server > 文件 > 2.4 版 > 虛擬主機

動態設定大量虛擬主機

使用語言:  en  |  fr  |  ko  |  tr 

本文件描述如何使用 Apache HTTP Server 有效服務任意數量的虛擬主機。另一份文件 探討使用 mod_rewrite 建立動態大量虛擬主機。

Support Apache!

另請參閱

top

目的

如果您 httpd.conf 的許多 <VirtualHost> 區段基本上相同,例如

<VirtualHost 111.22.33.44>
    ServerName                 customer-1.example.com
    DocumentRoot        "/www/hosts/customer-1.example.com/docs"
    ScriptAlias  "/cgi-bin/"  "/www/hosts/customer-1.example.com/cgi-bin"
</VirtualHost>

<VirtualHost 111.22.33.44>
    ServerName                 customer-2.example.com
    DocumentRoot        "/www/hosts/customer-2.example.com/docs"
    ScriptAlias  "/cgi-bin/"  "/www/hosts/customer-2.example.com/cgi-bin"
</VirtualHost>

<VirtualHost 111.22.33.44>
    ServerName                 customer-N.example.com
    DocumentRoot        "/www/hosts/customer-N.example.com/docs"
    ScriptAlias  "/cgi-bin/"  "/www/hosts/customer-N.example.com/cgi-bin"
</VirtualHost>

我們想以一種可以動態計算的機制取代這些多個 <VirtualHost> 區段。這具有許多優點:

  1. 設定檔變小,因此 Apache 啟動較快,所用的記憶體也會變少。更重要的是,較小的設定較容易維護,錯誤的空間也較少。
  2. 新增虛擬主機只要在檔案系統中建立適當的目錄和 DNS 中的記錄即可,無需重新設定或重新啟動 Apache。

主要缺點是每個虛擬主機無法擁有不同的記錄檔;但是,如果您有許多虛擬主機,這樣做可能是個壞主意,因為所需的檔案描述符數量。更好的方法是 記錄到管線或 fifo,並安排另一端的程序將記錄檔分割成每個虛擬主機一份。您可以從 split-logfile 工具程式中找到這樣的程序範例。

top

概述

虛擬主機由兩項資訊定義:其 IP 位址和 HTTP 要求中 Host: 標頭的內容。在此使用的動態大量虛擬主機技術,是基於自動將此資訊插入用於滿足要求的文件路徑名稱中。最容易做到這一點的方法,是搭配 Apache httpd 使用 mod_vhost_alias。或者,也可以使用 mod_rewrite

這兩個模組預設都是停用的;如果您要使用這項技術,您必須在組態和建置 Apache httpd 時啟用其中一個。

需要從要求中決定幾件事,才能讓動態虛擬主機看起來像一般的。最重要的就是伺服器名稱,伺服器用它來產生自參考 URL 等。它使用 ServerName 指令來組態,而且 CGI 可以透過 SERVER_NAME 環境變數存取它。執行期間使用的實際值,由 UseCanonicalName 設定控制。如果 UseCanonicalName Off,伺服器名稱來自要求中 Host: 標頭的內容。如果 UseCanonicalName DNS,則會從虛擬主機 IP 位址的反向 DNS 查詢中擷取。前者設定用於基於名稱的動態虛擬主機,而後者用於基於 IP 的主機。如果 httpd 無法找出伺服器名稱,是因為沒有 Host: 標頭,或 DNS 查詢失敗,則改用設定在 ServerName 中的值。

另一件要決定的事項是文件根目錄(使用 DocumentRoot 組態,並且可以透過 DOCUMENT_ROOT 環境變數讓 CGI 腳本存取)。在一般的組態中,核心模組使用它在比對 URI 到檔案名稱時使用,但是當伺服器組態為動態虛擬主機時,該工作必須由另一個模組(mod_vhost_aliasmod_rewrite)接手,它有不同的比對方式。這兩個模組都不負責設定 DOCUMENT_ROOT 環境變數,所以如果任何 CGI 或 SSI 文件使用它,它們會得到誤導性的值。

top

使用 mod_vhost_alias 的動態虛擬主機

httpd.conf 擷取的這段內容,實作在 動機 區段中所概述的虛擬主機安排,方法是使用 mod_vhost_alias

# get the server name from the Host: header
UseCanonicalName Off

# this log format can be split per-virtual-host based on the first field
# using the split-logfile utility.
LogFormat "%V %h %l %u %t \"%r\" %s %b" vcommon
CustomLog "logs/access_log" vcommon

# include the server name in the filenames used to satisfy requests
VirtualDocumentRoot "/www/hosts/%0/docs"
VirtualScriptAlias  "/www/hosts/%0/cgi-bin"

只要將 UseCanonicalName Off 改成 UseCanonicalName DNS,這個組態就可以變成一個基於 IP 的虛擬主機解決方案。插入到檔案名稱中的伺服器名稱接著會從虛擬主機的 IP 位址派生而來。變數 %0 參考要求的伺服器名稱,如 Host: 標頭中所指示。

請參閱 mod_vhost_alias 文件,以取得更多使用範例。

top

簡化的動態虛擬主機

這是針對 ISP 的 web 托管伺服器調整上述系統而成。使用 %2,我們可以在檔案名稱中選取伺服器名稱的子字串來使用,例如:www.user.example.com 的文件位於 /home/user/www。它使用單一的 cgi-bin 目錄,而不是每個虛擬主機一個。

UseCanonicalName Off

LogFormat "%V %h %l %u %t \"%r\" %s %b" vcommon
CustomLog "logs/access_log" vcommon

# include part of the server name in the filenames
VirtualDocumentRoot "/home/%2/www"

# single cgi-bin directory
ScriptAlias  "/cgi-bin/"  "/www/std-cgi/"

mod_vhost_alias 文件中提供更複雜的 VirtualDocumentRoot 設定範例。

top

在同一個伺服器上使用多個虛擬主機系統

使用更複雜的設定,你可以使用 httpd 的一般 <VirtualHost> 指令來控制多個虛擬主機組態的範圍。例如,你可以為一般客戶的主頁設定一個 IP 位址,並為企業客戶設定另一個 IP 位址,使用以下設定。這可以與傳統的 <VirtualHost> 組態區段結合起來,如下所示。

UseCanonicalName Off

LogFormat "%V %h %l %u %t \"%r\" %s %b" vcommon

<Directory "/www/commercial">
    Options FollowSymLinks
    AllowOverride All
</Directory>

<Directory "/www/homepages">
    Options FollowSymLinks
    AllowOverride None
</Directory>

<VirtualHost 111.22.33.44>
    ServerName www.commercial.example.com

    CustomLog "logs/access_log.commercial" vcommon

    VirtualDocumentRoot "/www/commercial/%0/docs"
    VirtualScriptAlias  "/www/commercial/%0/cgi-bin"
</VirtualHost>

<VirtualHost 111.22.33.45>
    ServerName www.homepages.example.com

    CustomLog "logs/access_log.homepages" vcommon

    VirtualDocumentRoot "/www/homepages/%0/docs"
    ScriptAlias         "/cgi-bin/" "/www/std-cgi/"
</VirtualHost>

注意

如果第一個 VirtualHost 區塊包含 ServerName 指令,系統將使用相關 IP 的反向 DNS。如果你不想使用該伺服器名稱,可以加入一個虛假條目 (例如:ServerName none.example.com) 來解決此問題。

top

更有效率的基於 IP 的虛擬主機

建議的組態變更會將 第一個範例 轉為基於 IP 的虛擬主機設定,會造成一個效率不高的設定。每一個要求都需要一個新的 DNS 查詢。為了避免這個額外的負擔,檔案系統可以調整為對應 IP 位址,而不是主機名稱,從而消除對 DNS 查詢的需求。記錄也將必須調整以符合這個系統。

# get the server name from the reverse DNS of the IP address
UseCanonicalName DNS

# include the IP address in the logs so they may be split
LogFormat "%A %h %l %u %t \"%r\" %s %b" vcommon
CustomLog "logs/access_log" vcommon

# include the IP address in the filenames
VirtualDocumentRootIP "/www/hosts/%0/docs"
VirtualScriptAliasIP  "/www/hosts/%0/cgi-bin"
top

使用 mod_rewrite 的大量虛擬主機

大量的虛擬主機也可以使用 mod_rewrite 來完成,使用簡單的 RewriteRule 指令,或使用更複雜的技術,例如將 vhost 定義儲存在外部,並透過 RewriteMap 來存取它們。這些技術在 rewrite 文件 中有討論。

top

使用 mod_macro 的大量虛擬主機

動態生成的虛擬主機的另一個選項是 mod_macro,你可以使用它來建立一個虛擬主機範本,並對多個主機名稱呼叫它。模組文件的用法區段中提供了這方面的範例。

使用語言:  en  |  fr  |  ko  |  tr 

top

留言

注意
此處並非問與答版塊。放置在此處的意見應針對改善文件或伺服器的建議,而我們的版主可能會移除已實作或被視為無效或離題的意見。有關如何管理 Apache HTTP Server 的問題,應導向我們的 IRC 頻道(在 Libera.chat 上為 #httpd)或傳送至我們的 郵件清單