• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • 动态配置的大规模虚拟主机

    本文档介绍了如何通过Apache HTTP Server有效地为任意数量的虚拟主机提供服务。甲单独的文档讨论了使用mod_rewrite以创建动态质量虚拟主机。

    动机

    如果您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 实用程序中找到这种过程的一个示例。

    总览

    虚拟主机由两条信息定义:其IP地址和Host:HTTP请求中标头的内容。此处使用的动态批量虚拟主机技术基于自动将此信息插入用于满足请求的文件的路径名中。通过mod_vhost_alias与Apache httpd一起使用,可以很容易地做到这一点。或者,可以使用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文档都使用了它,那么它们将产生误导性的价值。

    使用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"
    

    该结构通过只是把变成基于IP的虚拟主机解决方案UseCanonicalName Off进入UseCanonicalName DNS。然后,从虚拟主机的IP地址派生到文件名中的服务器名称。该变量%0引用请求的服务器名,如Host:标题中所示。

    有关mod_vhost_alias更多用法示例,请参阅文档。

    简化的动态虚拟主机

    这是对上述系统的调整,专门针对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/"
    

    文档中有更复杂的VirtualDocumentRoot设置示例mod_vhost_alias

    在同一服务器上使用多个虚拟主机系统

    通过更复杂的设置,您可以使用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>
    

    注意

    如果第一个虚拟主机块并没有包括ServerName指令,相关IP的反向DNS将被使用。如果这不是您希望使用的服务器名称,ServerName none.example.com则可以添加虚假条目(例如)来解决此问题。

    基于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"
    

    使用mod_rewrite的大量虚拟主机

    也可以mod_rewrite使用简单的RewriteRule指令或使用更复杂的技术(例如,在外部存储vhost定义并通过访问它们)来完成大规模虚拟主机RewriteMap。这些技术在重写文档中进行了讨论。

    使用mod_macro批量虚拟主机

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