📄 details.html
字号:
<li>虚拟主机的默认目录权限将继承主服务器的设置(包括所有模块针对每个目录的配置信息)。</li>
<li>虚拟主机将继承主服务器中每个模块针对主服务器的设置。</li>
</ol>
<p>本质上,主服务器在建立每个虚拟主机的时候,充当了一个默认值或根基的角色。但这些存在于主服务器中的定义的位置是无关紧要的——主服务器的配置在与虚拟主机整合之前就已经解析过了。所以即使一个主服务器的配置出现在虚拟主机定义的后面,它也同样会影响到虚拟主机的配置。</p>
<p>如果没有定义主服务器中的<code>ServerName</code> ,那么将由运行这个<code class="program"><a href="../programs/httpd.html">httpd</a></code>服务的机器的主机名来代替。我们将由DNS查找此<code>ServerName</code>返回的IP地址称为<em>主服务器地址集(main_server address set)</em>。</p>
<p>在没有定义<code>ServerName</code>的情况下,一个基于域名的虚拟主机默认采用定义虚拟主机时在<code>VirtualHost</code>指令中最先出现的地址。</p>
<p>所有使用了"<code>_default_</code>"通配符的虚拟主机将被赋予和主服务器相同的<code>ServerName</code> 。</p>
</div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
<div class="section">
<h2><a name="hostmatching" id="hostmatching">虚拟主机匹配</a></h2>
<p>服务器用下述方法来确定对一个特定的请求使用哪个虚拟主机:</p>
<h3><a name="hashtable" id="hashtable">散列表查找</a></h3>
<p>当客户端第一次连接的时候,会从内部的IP散列表中查找客户端想要连接的IP地址。</p>
<p>如果查找失败(没有找到相应的IP地址),而所请求的端口又存在一个"<code>_default_</code>"虚拟主机,那么这个请求将会由这个虚拟主机来伺服。如果没有找到这样的"<code>_default_</code>"虚拟主机,那么这个请求将会由主服务器来伺服。</p>
<p>如果在散列表中没有找到IP地址,但存在一个"<code>NameVirtualHost *</code>"指令与所请求的端口号相匹配,那么将用这个虚拟主机来处理这个请求。</p>
<p>如果查找成功(找到了对应于这个IP地址的列表),下一步就是看我们要处理的是一个基于IP的虚拟主机还是一个基于域名的虚拟主机。</p>
<h3><a name="ipbased" id="ipbased">基于IP的虚拟主机</a></h3>
<p>如果返回的列表中域名列表为空,那么我们处理的就是一个基于IP的虚拟主机,这个虚拟主机将会直接进行处理而不会有其他步骤。</p>
<h3><a name="namebased" id="namebased">基于域名的虚拟主机</a></h3>
<p>如果返回的域名列表包含一个或多个虚拟主机的结构,那么我们处理的就是一个基于域名的虚拟主机。这个列表包含的虚拟主机的顺序与配置文件中相应<code>VirtualHost</code>指令出现的顺序是相同的。</p>
<p>这个列表中第一个虚拟主机(也就是在配置文件中第一个指定了这个IP地址的虚拟主机)对处理请求有着最高的优先级。所有对未知服务器名或没有"<code>Host:</code>"头的请求都将由它进行处理。</p>
<p>如果客户端在请求中提供了一个"<code>Host:</code>"头,那么将在列表中查找第一个<code>ServerName</code>或<code>ServerAlias</code>与其符合的虚拟主机,并将其用于伺服这个请求。尽管"<code>Host:</code>"头中可以包含端口号,但Apache还是会用收到请求的那个真实端口来进行匹配。</p>
<p>如果客户端提交了一个不包含"<code>Host:</code>"头的HTTP/1.0的请求,我们将无法确认客户端想要连接那个服务器。而如果存在一个<code>ServerPath</code>与客户端提交的请求中的URI相对应,那么列表中第一个符合条件的虚拟主机将用于伺服这个请求。</p>
<p>如果还是找不到对应的虚拟主机,那么这个请求将会由客户端连接的IP对应的列表中的第一个与请求的端口相同的虚拟主机来伺服(如前所述)。</p>
<h3><a name="persistent" id="persistent">持久连接</a></h3>
<p>上述IP查找对一个特定的TCP/IP进程只执行<em>一次</em>。但在持久连接(KeepAlive)中,<em>每个</em>请求都会进行一次这样的查找过程。换句话说,一个客户端在一个持久连接中可以向位于不同的基于域名的虚拟主机的页面提出请求。</p>
<h3><a name="absoluteURI" id="absoluteURI">绝对URI</a></h3>
<p>如果请求提交的URI是一个绝对URI,而其中的主机名和端口号又和主服务器或某个虚拟主机相符合,<em>并且</em>也与作为此请求提交对象的地址和端口相符,那么这个请求的类型/主机名/端口前缀将被抹除,仅留下相对URI为对应的主服务器或虚拟主机所伺服。如果不满足上述符合条件,这个URI将保留原样,而此请求将被作为一个代理请求处理。</p>
<h3><a name="observations" id="observations">备忘录</a></h3>
<ul>
<li>基于域名的虚拟主机和基于IP的虚拟主机之间互相不干扰。基于IP的虚拟主机只接受发送到它自身地址集的请求,而不接受其他IP地址。基于域名的虚拟主机也是一样,它们只接受<code>NameVirtualHost</code>指令定义的地址集的访问。</li>
<li>永远不会对一个基于IP的虚拟主机执行<code>ServerAlias</code>和<code>ServerPath</code>检查。</li>
<li>在配置文件中,基于域名的虚拟主机、基于IP的虚拟主机、"<code>_default_</code>"虚拟主机和<code>NameVirtualHost</code>指令出现的顺序并不重要。而对于某个指定的地址集来说,基于域名的虚拟主机的顺序是不能混淆的:在配置文件中较先出现的虚拟主机在相应的地址集中有较高的优先权。</li>
<li>出于安全性的考虑,在"<code>Host:</code>"头中出现的端口号将不用于匹配。Apache会一直使用客户端所连接的真实端口作为匹配。</li>
<li>如果一个<code>ServerPath</code>指令凑巧是后面出现的另外一个<code>ServerPath</code>指令的前缀,前者将用于匹配,而后者将被忽略。(这里讨论的是没有"<code>Host:</code>"头来将这两个情况分开的情况下)</li>
<li>如果有两个基于IP的虚拟主机使用了同一个地址,则在配置文件中首先出现的那个用于匹配。这种事情可能发生在你疏忽的时候。当服务器遇到这种情况的时候,会在日志文件中写入一个错误信息。</li>
<li>仅当没有其他虚拟主机符合客户端请求的IP地址和端口号时,"<code>_default_</code>"虚拟主机才会捕获这个请求。<em>并且</em>仅当"<code>_default_</code>"虚拟主机的端口号(默认值由您的<code>Listen</code>指定)与客户端发送请求的目的端口号相符时,这个请求才会被捕获。也可以使用通配符(例如:"<code>_default_:*</code>")来捕获任何端口号的请求。这也同样适用于"<code>NameVirtualHost *</code>"的虚拟主机。</li>
<li>仅当客户端连接的目的IP地址和端口号没有指定而且不与任何一个虚拟主机(包括"<code>_default_</code>"虚拟主机)匹配的时候,才会用主服务器来伺服请求。换句话说,主服务器仅捕获没有指定IP地址和端口的请求(除非存在一个匹配端口的"<code>_default_</code>"虚拟主机)。</li>
<li>如果客户端连接到一个用于基于域名的虚拟主机使用的地址(和端口),比如说使用了<code>NameVirtualHost</code>指令,那么一个未知的或没有"<code>Host:</code>"头的请求就<em>不会</em>与"<code>_default_</code>"虚拟主机或是主服务器相匹配。</li>
<li>绝对不能在<code>VirtualHost</code>指令中使用DNS名称,否则您的服务器就会依赖DNS来进行启动。而且,如果您无法控制列表中所有的域,您将会面临安全威胁。您可以在这里获得关于这个问题和以下两个问题的<a href="../dns-caveats.html">更多详情</a>。</li>
<li>应当为每个虚拟主机设定<code>ServerName</code> 。否则就会需要为每个虚拟主机进行DNS查询。</li>
</ul>
</div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
<div class="section">
<h2><a name="tips" id="tips">小技巧</a></h2>
<p>作为<a href="../dns-caveats.html#tips">DNS问题</a>页面小技巧的附加,这里有些额外的技巧:</p>
<ul>
<li>将所有主服务器的定义放在所有<code>VirtualHost</code>定义之前(为了增加可读性),否则会使得类似在虚拟主机旁边的定义影响到所有的虚拟主机这样的问题不容易发现。</li>
<li>将您配置中相应的<code>NameVirtualHost</code>和<code>VirtualHost</code>定义放到一起,以获得更好的可读性。</li>
<li>避免前一个<code>ServerPaths</code>是后一个<code>ServerPaths</code>的前缀。如果您无法避免这样的情况,您最好确保在您的配置文件中"长在前,短在后"(也就是说:"ServerPath/abc/def"应当出现在"ServerPath/abc"之前)。</li>
</ul>
</div></div>
<div id="footer">
<p class="apache">本文允许自由使用、分发、转载,但必须保留译者署名;详见:<a href="../translator_announcement.html#announcement">译者声明</a>。</p>
<p class="menu"><a href="../mod/index.html">模块索引</a> | <a href="../mod/directives.html">指令索引</a> | <a href="../faq/index.html">常见问题</a> | <a href="../glossary.html">词汇表</a> | <a href="../sitemap.html">站点导航</a></p></div>
</body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -