关于虚拟主机的疑问解答

一.什么是虚拟主机:
虚拟主机(Virtual Host)的意思很明显。就是在多个Http服务站点在实际上只运行在一个Http服务器上。一个简单的理解就是“让多个不同的网站事例跑在一个Http服务器上,而不是让它们每个网站都需要各占一台Http服务器。”在一个http服务器上支持多个网站,但是从外部看起来就好像是一个一个独立似的,其实它们都是跑在一个Http服务器上,在后台它们不是真实的一台台主机,而是由主服务器虚拟出来的。这每一个主机,就叫做虚拟主机。

二.虚拟主机基本上可以干吗:
既然虚拟主机的最主要的特性是虚拟,他们是虚拟在宿主服务器上的。那么一个很直接可以想到的原因,就是节省成本,“N个网站可能原本需要各自N台服务器,还要可能需要M个人去管理和维护这N台服务器,现在只需要1台就搞定了,而且管理和维护工作也可以集中在1台上就完事了。”另外可能还出于一些管理工作上需要以及生产环境的需要,关于这些就不多展开了。

三.能讲讲大致配置吗:
虚拟主机的配置文件就是在Apache的主配置文件httpd.conf里面,并且虚拟主机的配置部分在整个主配置文件当中也处于第三章节的位置(Apache的主配置文件httpd.conf一共主要分成3大章节)。

1.首先要讲一些在httpd.conf里非虚拟主机,但是又十分相关而必须了解的配置项:
————————————————————————–
ServerRoot “/etc/httpd”
设定Apache服务器的根路径,也就是说,ServerRoot设定的路径相对Apache服务器来说就像到顶的根目录一样了。

PidFile run/httpd.pid
设 定Apache的 Pid进程号文件。一般采用默认值run/httpd.pid。这个值是采用相对路径写的,因为定义了ServerRoot为/etc /httpd/。那么这里的run/httpd.pid意思其实是/etc/httpd/run/httpd.pid。当然也可以写绝对路径为/etc /httpd/run/httpd.pid。注意,如果一定要用绝对路径表达的话,那么前面要加“/”以示绝对路径和相对路径的区别。

User apache
Group apache
设定Apache服务的服务宿主用户。出于安全性的需要,应该采用默认值,避免使用root这样的高权限用户去支撑服务。

Listen 80
设 定Apache服务器向操作系统申请开放的httpd监听端口。默认是80。当然,这里也可以具体到IP地址,比如 Listen 123.123.123.123:80。这样的话将会强制Apache到服务器的指定网络接口地址上去监听。如果不指定IP地址而只是写端 口的话,那么就是让Apache在服务器的所有可用网络接口上去监听。

ServerName www.aaa.com:80
设定http服务主机的监听域名、地址和端口。这里可以设定IP地址和端口,甚至可以写域名。那么一个疑问是,之前在Listen的配置项当中不是配置过了么?这里还要多余地指定一次?那么我乱填,故意写的和Listen配置项当中的相差很大行不行?其实问了这样的问题也是对ServerName不了解关系(因为这些问题是当初我问的= =|||)。ServerName是用来指定Apache服务主机用来辨识自己主机名和端口号的设定项目。举个例子,如果 你同时拥有www.aaa.com和xxx.bbb.com这两个域名同时指定到你的Web服务器上,而这个时候你 建立好了Apache服务器,并且只 想让www.aaa.com这个域名访问你的Apache网站,而对于同样可以通过DNS解析访问到你的站点的域名xxx.bbb.com,你不想让访客通过访问xxx.bbb.com这个域名也访问到你的Web网站。那么你就可以设定“ServerName www.aaa.com:80”,这样,即使别的域名通过DNS解析也能指向你的Apache主机,但是通过ServerName的设定可以告诉你的Apache服务器应该为什么样的域名服务以及针 对指定的域名接下去该怎么进行操作,而不应该受理什么样的域名。
另外一点,如果ServerName配置项不设定的话,Apache会尝试对服务 器的IP进行反查询来获得主机名。所以,如果在网络上没有DNS名,而且又没有给Apache所在的服务器设定规范的主机名甚至根本忘记设置主机名的时 候,启动Apache的时候会反馈这个错误信息。
所以,ServerName的设定应当十分尊重实际情况的。而且它的设定将是受到Listen这个大设定项的限制的。比如,在Listen中设定的监听端口是80,但是在ServerName中故意设定为其他非Listen中提到的端口,如故意设定成90端口这种随便乱设置的话,那么Apache将仍然向操作系统申请Listen中指定的80端口去监听。而在ServerName中设定的90端口将不影响操作系统,操作系统不会特地为ServerName开放90端口,而ServerName又指定域名监听端口为错误的90端口,这将会引起服务的无效(服务将会照样启动也不报错)。

DocumentRoot “/var/www/html”
设定网页主机的主路径。一般会在这个主路径里放入网站的主页Index。(这里我说称呼为网页主机而不是Apache,是因为一个网页主机就会有一个网页的主路径,而Apache里面可以支持多个网页主机,当然,其中大部分将是虚拟主机。)

Include conf.d/*.conf
设 定配置文件的扩展。Apache的主配置文件为httpd.conf。一般来说Apache的主要的、基本的功能配置项目都被httpd.conf包括 了。但是,如果Apache的结构复杂,功能需求多而大的时候,那么它的配置将会复杂而庞大。这个时候的确不适合将所有配置都集中些在 httpd.conf这一个文件里。一般的做法则是,让httpd.conf仅仅保存一些Apache全局的、基本的、必要的功能配置项。而额外具体的 Apache特性配置将独立保存在其他地方,做到与主配置文件分开,这样可以做到避免主配置文件过于庞大的问题,而且将具体配置模块分开处理记录也是一种 便于管理、便于修改的良好规划。
Include将指定扩展配置文件的路径。默认Include conf.d/*.conf,这里表示的同样是一个相对路径(前提是ServerRoot设定为了/etc/httpd/),意思是/etc/httpd/下的一个conf.d/这个目录中所有.conf结尾(“*”号表示通配符)都是httpd.conf的扩展文件,这些文件当中记载的配置项目,将和直接写在httpd.conf中的配置项目效果相同。
那这里又有一个比较瓜三的问题:那我在扩展配置文件中乱写配置可以不可以?或者我在扩展配置文件中故意写了和主配置文件相同的配置项从而造成与主配置文件冲突,或者,我干脆在扩展配置文件的目录中也放置一个一模一样的httpd.conf然后故意造成和主配置文件冲突,那么 Apache将会听谁的呢?(嘛~这些问题也是我当初自己提出的= =||老是这样做很变态吧= =哼,这样才能加深理解阿!)答案是:凡是和配置项和主 配置文件当中冲突,甚至你搞2份httpd.conf(一份放在扩展配置文件目录中),那么Apache将会以配置项错误报错提醒(针对第一种做法)或者 以/etc/httpd/conf/httpd.conf主配置文件为准的方式处理(针对第二种做法)。
另外Apache允许对个Include 配置项,用于让用户将不同功能模块的扩展配置功能进行分开规划(这里是说可以进行多个Include配置项设定,而不是在一个Include后面连续跟着多个值,那样不符合配置文件的格式,在启动服务器的时候会引起语法报错。)这里我一般会专门建立一个目录来专门存放关于虚拟主机的扩展配置文件的。一般我是在/etc/httpd/这个路径下再建立一个myconf的目录,接着在httpd.conf中添加一条“Include myconf /*.conf”,然后里面放置虚拟主机的扩展配置文件virthosts.conf(名字当然可以随便取,后缀的.conf是为了让Apache辨认)
————————————————————————–

2.虚拟主机的配置部分:
一 般我会把httpd.conf中的第三章节关于虚拟主机的配置部分挖出来,另存在我Include的虚拟主机专用扩展配置目录中。并要先保存一份样本,我 一般取名为virthosts.conf.temp,故意不要用conf结尾省得让Apache将配置文件搞混,另一方面也作为一个虚拟主机的配置模版, 供以后自己参考。
[root@kcapache ~]# cat /etc/httpd/myconf/virthosts.conf.temp
————————————————————————–
### Section 3: Virtual Hosts
#
# VirtualHost: If you want to maintain multiple domains/hostnames on your
# machine you can setup VirtualHost containers for them. Most configurations
# use only name-based virtual hosts so the server doesn’t need to worry about
# IP addresses. This is indicated by the asterisks in the directives below.
#
# Please see the documentation at
# <URL:http://httpd.apache.org/docs-2.0/vhosts/>
# for further details before you try to setup virtual hosts.
#
# You may use the command line option ’-S’ to verify your virtual host
# configuration.
这里是一个重要的提示。当你配置好了虚拟主机的时候,请先用命令加上“-S”(S要大写)的参数进行确认功能结果。如果是RPM安装的Apache的话,命令应该是httpd -S,如果是源码安装的话那么命令应该是apachectl -S。
#
# Use name-based virtual hosting.
#
#NameVirtualHost *:80
这个NameVirtualHost参数在虚拟主机当中是一个非常重要的配置项。如果将它解注并进行配置的话,那么将意味着启用了“基于域名区别方式的虚拟主机”。如果注释掉它不启用它的话,那么则意味着启用了“基于IP或者端口区别方式的虚拟主机”。当然,这两种虚拟主机方式也可以同时存在(一般来说这样做没有什么必要而且有点自找麻烦的感觉= =)但是对概念的明确将会有很大的帮助。
(我喜欢讲得区别性大一点。“基于域名区别的虚拟主机”,其实 就是我们平时称呼为“基于域名的虚拟主机”的方式。这里我特别加入“区别”这两个字,是为了明确概念。虚拟主机之间是需要互相区别的,以使得当一个网页请 求递交到Apache的服务器中来的时候,这么虚拟主机当中谁应该响应请求,该怎么处理。)
#
# NOTE: NameVirtualHost cannot be used without a port specifier
# (e.g. :80) if mod_ssl is being used, due to the nature of the
# SSL protocol.
#

#
# VirtualHost example:
# Almost any Apache directive may go into a VirtualHost container.
# The first VirtualHost section is used for requests without a known
# server name.
#
#<VirtualHost *:80>
#    ServerAdmin webmaster@dummy-host.example.com
#    DocumentRoot /www/docs/dummy-host.example.com
#    ServerName dummy-host.example.com
#    ErrorLog logs/dummy-host.example.com-error_log
#    CustomLog logs/dummy-host.example.com-access_log common
#</VirtualHost>
上面这段就是一个虚拟主机的配置范例。从<VirtualHost>到</VirtualHost>的这个段当中就是一个虚拟主机的配置。一个虚拟主机的明细就要在这个段里设置好。可以从虚拟主机的配置文件当中发现也有ServerAdmin、DocumentRoot、 ServerName、ErrorLog、CustomLog这些配置项(其实还有更多的没写出来而已= =)。按我的说法,把这些当作“局部参数”来理解将更容易理解,也就是说,完全相同的这些配置项,在之前的httpd.conf这个主配置文件当中出现并设定的,是“全局参数”,这些“全局参数”的作用和影响范围将是整个Apache服务器。这样讲就会非常明确了“局部参数”了,每个虚拟主机都有“局部参数”,这些局部参数的影响范围只能是这个虚拟主 机的本身范围,它不会跨出这个范围去影响Apache全局设定,也不会去干扰其他虚拟主机的内部。另外一点,这些局部参数有些可以缺省有些却不能缺省!那些可以起到“与其他虚拟主机区别”特征的配置参数(如ServerName、DocumentRoot等)将不应该缺省,而另外一些可以缺省的参数(如一些性能控制等),如果不具体设定的话,将采用Apache的主配置文件中的全局设定,如果在虚拟主机内设定的话,那么虚拟主机将优先采用(前提是不超出全 局的设定和限制,比如不应该故意监听使用Apache服务器根本没有向系统申请的端口,或者使用Apache全局根本不存在的IP地址或域名等等。)
————————————————————————–

四.有几种类型的虚拟主机?
按照大路的说法,应该有2种类型:分别是基于IP的虚拟主机、以及基于域名的虚拟主机。
为了明确概念,按我的观点,是整理成3种类型:分别是“基于IP地址区别的虚拟主机”、“基于端口区别的虚拟主机”、“基于域名区别的虚拟主机”。

1.基于IP地址区别的虚拟主机:
意思就是根据IP地址的不同而彼此区别的虚拟主机。举一个例子:在一个Apache服务器里比如有3个虚拟主机,而假设这个运行Apache的服务器又正好 有3个IP地址。那么这3个虚拟主机一人一个。这里假设Apache对这3个IP地址都进行监听。那么当一个网页访问的请求递交过来给Apache受理的时候,这个请求指定的目的地址是哪个IP地址,那么哪个捆绑这个IP的地址虚拟主机将会响应请求。绝对不会和其他两个不同IP的虚拟主机搞混也不会冲突。因为光靠IP地址就可以区分彼此,不会有问题,所以叫做“基于IP地址区别的虚拟主机”。当然这种方式的虚拟主机有个很明显的特点,就是 “吃”IP地址。

2.基于端口区别的虚拟主机:
意思就是根据监听端口的不同而彼此区别的虚拟主机。举一个例子:在一个Apache服务器里 比如有3个虚拟主机,而假设这个运行Apache的服务器又只有一个1个IP地址。那么这个3个虚拟主机将共享这一个IP地址,但是他们要求Apache 给他们各自开放不同的端口来响应,假设是81、82、83这三个端口,同时在httpd.conf这个主配置文件当中也要写三条Listen配置项分别向操作系统申请81、82、83这三个端口(如果在虚拟主机上配置了特殊监听端口而在主配置Listen项中又不同样添加的话,那么Apache只会向系统 申请Listen项中提到的端口来监听请求,那些没有虚拟主机中提到但是又没有在Listen中申请的端口将无效)。那么同样当一个网页的请求递交给 Apache的时候(当然这个请求必须也要指定端口),那么Apache会根据请求的目的端口来让对应的虚拟主机来响应请求。由于其他两台虚拟主机监听的端口不同,所以它们互相之间也不会搞混和冲突,因为靠端口Port区分了彼此,不会有问题。所以叫做“基于端口区别的虚拟主机”。很明显,这种方式的虚拟主机也有个性的特点:“麻烦”。由于使用了特殊端口进行请求侦听,虽然回避了吃IP地址的问题,但是对于客户段,对方也要知道你Apache服务开放的特 定端口,否则客户段和服务段就就“不和谐”了。

3.基于域名区别的虚拟主机:
意思就是根据域名的不同而彼此区别的虚拟 主机。举一个例子:在一个Apache服务器里也有3个虚拟主机,而且假设这个Apache服务器又只有1个IP地址,另外它也不想搞什么特殊端口,省得 麻烦它还是使用80这个默认端口监听。但是它在公网DNS上有三个合法域名都能指向Apache所在的服务器的IP地址,假设为aaa.aaa.com、 bbb.bbb.net、ccc.ccc.org这3个域名。那么这种情况下,就可以将这3个域名分配到这3个虚拟主机上去。对于Apache来说,它仍 然监听的是同一个IP地址,仍然监听着同一个httpd端口。但是它已经为虚拟主机绑定了各自的域名。当一个网页请求发过来的时候,Apache将仍然用 相同的IP和端口去受理这个请求,但是根据请求中指定的访问域名不同而明确地将请求转交给相对应的虚拟主机去处理。所以叫做“基于域名区别的虚拟主机”。
这里你也许会有一个问题:“当客户段发出访问请求的时候,通过IP直接访问也好,通过DNS将域名解析也好,总是最后得到的应该是个IP地址吧?客户端是应 该去访问IP地址上的主机,等客户段向DNS解析出来Apache服务器的IP地址的时候客户段就凭借解析出来的IP直接就访问Apache了,它解析到 这一步了,怎么还会带有域名?Apache服务器也应该是接到访问自己IP地址的请求而以,对方是解析了IP地址,那么Apache怎么通过请求知道客户 端要访问的是哪个虚拟主机呢?aaa.aaa.com、bbb.bbb.net、ccc.ccc.org不是都通过DNS解析出来同一个IP么?那对于 Apache来说应该怎么区别这个请求是该给谁的呢?” (这是以前我困惑过的问题之一)
有这样的问题,是原于对HTTP协议的不了解所造成的。 的确,客户端首先会去解析域名而得到IP地址,并且它也将通过IP地址来访问Apache主机。但是这说到了网络层的部分,HTTP协议是一个应用层的协 议。当客户端通过IP找到了Apache主机之后会用目的端口80来进行访问,开始进行HTTP协议的交互,客户端这个时候会向Apache提出访问的主 机头“Host”关键字。按照上个例子,如果客户端欲访问bbb.bbb.net这个域名的话,那么在HTTP协议的交互过程当中就会有 “HOST:bbb.bbb.net”这个消息。而Apache就是在这个阶段捕获了主机头的请求,并知道该把这个请求转交到哪台虚拟主机上了。

Leave a Reply

 

 

 

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

企业邮箱
虚拟主机
?> ?> ?>