<-
Apache > HTTP 服务器 > 文档 > 版本 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 指令配置,并且可以通过 SERVER_NAME 环境变量提供给 CGI。运行时使用的实际值由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 的网站托管服务器。使用 %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 指令,还是使用更复杂的技术,例如将虚拟主机定义存储在外部并通过 RewriteMap 访问它们。这些技术在rewrite 文档中进行了讨论。

top

使用 mod_macro 的大量虚拟主机

动态生成虚拟主机的另一个选择是 mod_macro,您可以使用它创建虚拟主机模板,并为多个主机名调用它。模块文档的用法部分提供了此示例。

可用语言:  en  |  fr  |  ko  |  tr 

top

评论

注意
这不是问答部分。此处发布的评论应针对有关改进文档或服务器的建议,如果这些评论已被实施或被认为无效/与主题无关,则可能会被我们的版主删除。有关如何管理 Apache HTTP Server 的问题应发送到我们的 IRC 频道 #httpd(在 Libera.chat 上)或发送到我们的邮件列表