1. 虚拟主机概念和类型介绍
1.1 虚拟主机概念
所谓虚拟主机,在Web服务里就是一个独立的网站站点,这个站点既可以对应独立的域名(也可能是IP或端口),具有独立的程序及资源目录,又可以独立地对外提供服务供用户访问。
这个独立的站点在配置里是由一定格式的标签段标记,对于Apache软件来说,一个虚拟主机的标签段通常被包含在<VirtualHost></VirtualHost>内,而Nginx软件则使用一个Server{}标签来标示一个虚拟主机,一个Web服务里可以有多个虚拟主机标签对,即同时可以支持多个虚拟主机站点。
1.2 虚拟主机类型
(1)基于域名的虚拟主机
所谓基于域名的虚拟主机,意思就是通过不同的域名区分不同的虚拟主机。基于域名的虚拟主机是企业应用最广的虚拟主机类型,几乎所有对外提供服务的网站都是使用基于域名的虚拟主机,如www.etiantian.org。
(2)基于端口的虚拟主机
同理,所谓基于端口的虚拟主机,意思就是通过不同的端口来区分不同的虚拟主机,此类虚拟主机对应的企业应用主要为公司内部的网站,如一些不希望直接对外提供用户访问的网站后台等。访问基于端口的虚拟主机地址里要带有端口,如http://etiantian.org:9000。
(3)基于IP的虚拟主机
同理,所谓基于IP的虚拟主机,意思就是通过不同的IP区分不同的虚拟主机,此类虚拟主机对应的企业应用非常少见。一般不同业务需要使用多IP的场景都会在负载均衡器上进行VIP绑定,而不是在Web上通过绑定IP区分不同的虚拟机。
三种虚拟主机类型既可独立使用,也可以互相混合一起使用。
2. 基于域名的虚拟主机配置实战
2.1 配置基于域名的nginx.conf内容
这里使用grep过滤命令来生成基础的Nginx主配置文件nginx.conf,然后根据生成的初始配置进行修改,使其成为所需的形式,具体步骤为:
[root@web01 ~]# cd /application/nginx/conf/
[root@web01 conf]# diff nginx.conf.default nginx.conf ---初始时这两个配置文件是一致的
[root@web01 conf]# egrep -v "#|^$" nginx.conf.default > nginx.conf
---过滤包含#号和空行生成新文件
[root@web01 conf]# cat nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
2.2 创建域名对应的站点目录及文件
此处配置的是基于域名的虚拟主机,即创建对应的域名站点目录及文件。
[root@web01 conf]# mkdir ../html/www -p ---创建www站点目录,注意目录层次
[root@web01 conf]# echo "http://www.etiantian.org" >../html/www/index.html ---追加内容到首页文件
[root@web01 conf]# cat ../html/www/index.html
http://www.etiantian.org
上述命令的作用是创建了一个/application/nginx/html/www站点目录,对应于虚拟主机配置文件里root根目录的html/www设置(root html/www;)。然后生成一个默认的首页文件index.html,文件的内容是"http://www.etiantian.org"。
2.3 检查语法并重新加载Nginx
[root@web01 conf]# nginx -t
nginx: the configuration file /application/nginx-1.16.0//conf/nginx.conf syntax is ok
nginx: configuration file /application/nginx-1.16.0//conf/nginx.conf test is successful
[root@web01 conf]# nginx -s reload ---平滑重启,重新加载配置文件
再检查Nginx重新加载后的情况,如进程和端口是否OK。
[root@web01 conf]# netstat -lntup | grep nginx
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 9584/nginx: master
最后测试域名站点配置的访问结果。
[root@web01 conf]# echo "192.168.9.7 www.etiantian.org" >> /etc/hosts
[root@web01 conf]# tail -1 /etc/hosts
192.168.9.7 www.etiantian.org
[root@web01 conf]# ping www.etiantian.org
PING www.etiantian.org (192.168.9.7) 56(84) bytes of data.
64 bytes from www.etiantian.org (192.168.9.7): icmp_seq=1 ttl=64 time=0.045 ms ---hosts解析成功
^C
--- www.etiantian.org ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2004ms
rtt min/avg/max/mdev = 0.019/0.030/0.045/0.011 ms
[root@web01 conf]# curl www.etiantian.org ---访问测试
http://www.etiantian.org
2.4 配置多个基于域名的虚拟主机
(1)增加新域名对应的配置
前面已经增加了一个www.etiantian.org虚拟主机的配置,下面再增加两个虚拟主机的配置,站点域名分别为bbs.etiantian.org和blog.etiantian.org。增加的配置一定要在nginx.conf的HTTP{}区块内,最好放在www.etiantian.org虚拟主机配置的下面,增加的内容如下图所示。
在整体格式上,新增域名虚拟主机的配置和前面配置过的www.etiantian.org域名的虚拟主机是一样的,区别就是server_name和root参数的配置不同,此时基于3个域名的完整nginx.conf配置文件内容为:
[root@web01 conf]# cat -n nginx.conf
1 worker_processes 1;
2 events {
3 worker_connections 1024;
4 }
5 http {
6 include mime.types;
7 default_type application/octet-stream;
8 sendfile on;
9 keepalive_timeout 65;
10 server {
11 listen 80;
12 server_name www.etiantian.org;
13 location / {
14 root html/www;
15 index index.html index.htm;
16 }
17 error_page 500 502 503 504 /50x.html;
18 location = /50x.html {
19 root html;
20 }
21 }
22
23 server {
24 listen 80;
25 server_name bbs.etiantian.org;
26 location / {
27 root html/bbs;
28 index index.html index.htm;
29 }
30 }
31
32 server {
33 listen 80;
34 server_name blog.etiantian.org;
35 location / {
36 root html/blog;
37 index index.html index.htm;
38 }
39 }
40 }
(2)创建新虚拟主机站点对应的目录和文件
下面的命令用于创建上述两个新增域名分别对应的站点目录及文件。
[root@web01 conf]# mkdir ../html/bbs ../html/blog -p
[root@web01 conf]# echo "http://bbs.etiantian.org" > ../html/bbs/index.html
[root@web01 conf]# echo "http://blog.etiantian.org" > ../html/blog/index.html
[root@web01 conf]# cat ../html/bbs/index.html
http://bbs.etiantian.org
[root@web01 conf]# cat ../html/blog/index.html
http://blog.etiantian.org
也可以使用Shell脚本一条命令搞掂。
for n in www blog bbs;
do
mkdir -p ../html/$n;
echo "http://$(n).etiantian.org" > ../html/$n/index.html;
cat ../html/$n/index.html;
done
检查html站点的目录结构:
[root@web01 conf]# tree ../html/
../html/
├── 50x.html
├── bbs
│ └── index.html
├── blog
│ └── index.html
├── index.html
└── www
└── index.html
3 directories, 5 files
(3)重新加载Nginx配置
每次更改Nginx的配置都需要管理员重新加载,使配置生效,这是因为Nginx在启动时已把所有配置信息都加载到内存中了,若更改了磁盘上的nginx.conf配置文件,需要把新配置重新加载到内存中生效。这样设计的目的是可以大幅度提升Nginx服务访问性能。
[root@web01 conf]# nginx -t
nginx: the configuration file /application/nginx-1.16.0//conf/nginx.conf syntax is ok
nginx: configuration file /application/nginx-1.16.0//conf/nginx.conf test is successful
[root@web01 conf]# nginx -s reload
(4)在客户端测试
[root@web01 conf]# vi /etc/hosts ---增加两个域名的解析
192.168.9.7 www.etiantian.org bbs.etiantian.org blog.etiantian.org
[root@web01 conf]# curl www.etiantian.org
http://www.etiantian.org
[root@web01 conf]# curl bbs.etiantian.org
http://bbs.etiantian.org
[root@web01 conf]# curl blog.etiantian.org
http://blog.etiantian.org
3. 基于域名的虚拟主机通信原理介绍
Nginx客户端发起请求过程如下:
1)浏览器输入www.etiantian.org回车。
2)浏览器请求LDNS,通过LDNS最终找到授权DNS获取IP。
3)请求Web服务器发起TCP三次握手。
4)建立HTTP请求(192.168.9.7的80端口)。
5)发起HTTP请求报文(请求头里携带:host www.etiantian.org字段)。
Nginx服务端处理请求过程如下:
1)监听本地所有网卡对80端口的请求。
2)读取接收到的HTTP报文里的信息。
3)读取Nginx配置文件虚拟主机Server标签。
4)先匹配Server标签中请求的端口号。
5)相同端口再去匹配Server标签对应server_name指定的域名(和读取请求头里host字段比对)。
6)把对应域名下面站点目录下的首页文件(index.xx)发给客户端。
7)如果没有匹配的域名,就把排在第一个顺序Server标签虚拟机对应内容发给客户端。
基于域名的虚拟主机通信原理如下图所示。
4. 基于端口的虚拟主机配置实战
基于端口的虚拟主机在生产环境中不多见,仅偶尔会用到,一般是为公司内部人员提供访问的,如OA系统/网站程序的后台、CMS发布后台、MySQL的Web客户端phpmyadmin等,使用特殊端口多是从安全上考虑的。
4.1 配置虚拟主机监听的端口
如果要配置基于端口的虚拟主机,就需要每个虚拟主机配置有不同的端口。编辑nginx.conf主配置文件,然后把每隔虚拟主机的“listen 80;”的配置行的80数字端口部分分别修改掉,内容见下文,注意server_name域名位置可以不做任何变更,哪怕是相同域名也可以,因为,基于端口的虚拟主机就是通过端口来唯一区别不同的虚拟主机的,只要端口不同就是不同的虚拟主机。
4.2 修改虚拟主机配置
[root@web01 conf]# cat -n nginx.conf
1 worker_processes 1;
2 events {
3 worker_connections 1024;
4 }
5 http {
6 include mime.types;
7 default_type application/octet-stream;
8 sendfile on;
9 keepalive_timeout 65;
10 server {
11 listen 80;
12 server_name www.etiantian.org;
13 location / {
14 root html/www;
15 index index.html index.htm;
16 }
17 error_page 500 502 503 504 /50x.html;
18 location = /50x.html {
19 root html;
20 }
21 }
22
23 server {
24 listen 81; ---由80端口改成81端口
25 server_name bbs.etiantian.org;
26 location / {
27 root html/bbs;
28 index index.html index.htm;
29 }
30 }
31
32 server {
33 listen 82; ---由80端口改成82端口
34 server_name blog.etiantian.org;
35 location / {
36 root html/blog;
37 index index.html index.htm;
38 }
39 }
40 }
4.3 检查语法重新加载配置生效
[root@web01 conf]# nginx -t
nginx: the configuration file /application/nginx-1.16.0//conf/nginx.conf syntax is ok
nginx: configuration file /application/nginx-1.16.0//conf/nginx.conf test is successful
[root@web01 conf]# nginx -s reload
[root@web01 conf]# netstat -lntup|grep nginx
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 9584/nginx: master
tcp 0 0 0.0.0.0:81 0.0.0.0:* LISTEN 9584/nginx: master
tcp 0 0 0.0.0.0:82 0.0.0.0:* LISTEN 9584/nginx: master
4.4 测试不同端口的访问结果
[root@web01 conf]# curl http://www.etiantian.org:80
http://www.etiantian.org
[root@web01 conf]# curl http://bbs.etiantian.org:81
http://bbs.etiantian.org
[root@web01 conf]# curl http://blog.etiantian.org:82
http://blog.etiantian.org
4.5 基于IP的虚拟主机配置实战
4.5.1 在服务器网卡上增加多个IP
临时增加2个不同的IP
[root@web01 conf]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:50:56:33:39:23 brd ff:ff:ff:ff:ff:ff
inet 192.168.9.7/24 brd 192.168.9.255 scope global dynamic ens33
valid_lft 5403165sec preferred_lft 5403165sec
inet6 fe80::250:56ff:fe33:3923/64 scope link
valid_lft forever preferred_lft forever
[root@web01 conf]# ip addr add 192.168.9.208/24 dev ens33 label ens33:1 ---临时添加IP
[root@web01 conf]# ip addr add 192.168.9.209/24 dev ens33 label ens33:2 ---临时添加IP
[root@web01 conf]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:50:56:33:39:23 brd ff:ff:ff:ff:ff:ff
inet 192.168.9.7/24 brd 192.168.9.255 scope global dynamic ens33
valid_lft 5403085sec preferred_lft 5403085sec
inet 192.168.9.208/24 scope global secondary ens33:1
valid_lft forever preferred_lft forever
inet 192.168.9.209/24 scope global secondary ens33:2
valid_lft forever preferred_lft forever
inet6 fe80::250:56ff:fe33:3923/64 scope link
valid_lft forever preferred_lft forever
[root@web01 conf]# ping 192.168.9.208 ---ping检查
PING 192.168.9.208 (192.168.9.208) 56(84) bytes of data.
64 bytes from 192.168.9.208: icmp_seq=1 ttl=64 time=0.017 ms
^C
--- 192.168.9.208 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.017/0.017/0.017/0.000 ms
[root@web01 conf]# ping 192.168.9.209 ---ping检查
PING 192.168.9.209 (192.168.9.209) 56(84) bytes of data.
64 bytes from 192.168.9.209: icmp_seq=1 ttl=64 time=0.011 ms
64 bytes from 192.168.9.209: icmp_seq=2 ttl=64 time=0.019 ms
^C
--- 192.168.9.209 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.011/0.015/0.019/0.004 ms
4.5.2 增加虚拟主机配置
基于IP的虚拟主机实际配置示例如下。这是一个端口和IP混合的虚拟主机示例,可以自行修改,使其仅仅基于IP,即每个虚拟主机的server_name字段都换成IP地址。
[root@web01 conf]# cat -n nginx.conf
1 worker_processes 1;
2 events {
3 worker_connections 1024;
4 }
5 http {
6 include mime.types;
7 default_type application/octet-stream;
8 sendfile on;
9 keepalive_timeout 65;
10 server {
11 listen 192.168.9.7:80;
12 server_name www.etiantian.org; ---此处也可以换成对应IP192.168.9.7
13 location / {
14 root html/www;
15 index index.html index.htm;
16 }
17 error_page 500 502 503 504 /50x.html;
18 location = /50x.html {
19 root html;
20 }
21 }
22
23 server {
24 listen 192.168.9.208:80;
25 server_name bbs.etiantian.org; ---此处也可以换成对应IP192.168.9.208
26 location / {
27 root html/bbs;
28 index index.html index.htm;
29 }
30 }
31
32 server {
33 listen 192.168.9.209:80;
34 server_name blog.etiantian.org; ---此处也可以换成对应IP192.168.9.209
35 location / {
36 root html/blog;
37 index index.html index.htm;
38 }
39 }
40 }
重新加载Nginx服务使得修改的配置生效。
[root@web01 conf]# nginx -t
nginx: the configuration file /application/nginx-1.16.0//conf/nginx.conf syntax is ok
nginx: configuration file /application/nginx-1.16.0//conf/nginx.conf test is successful
[root@web01 conf]# nginx -s reload ---平滑加载配置不生效
[root@web01 conf]# netstat -lntup|grep nginx
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 9584/nginx: master
tcp 0 0 0.0.0.0:81 0.0.0.0:* LISTEN 9584/nginx: master
tcp 0 0 0.0.0.0:82 0.0.0.0:* LISTEN 9584/nginx: master
[root@web01 conf]# nginx -s stop ---必须先停止nginx服务
[root@web01 conf]# nginx ---再开启服务
[root@web01 conf]# netstat -lntup|grep nginx
tcp 0 0 192.168.9.209:80 0.0.0.0:* LISTEN 14376/nginx: master
tcp 0 0 192.168.9.208:80 0.0.0.0:* LISTEN 14376/nginx: master
tcp 0 0 192.168.9.7:80 0.0.0.0:* LISTEN 14376/nginx: master
4.5.3 Linux客户端中的访问结果
[root@web01 conf]# curl 192.168.9.7
http://www.etiantian.org
[root@web01 conf]# curl 192.168.9.208
http://bbs.etiantian.org
[root@web01 conf]# curl 192.168.9.209
http://blog.etiantian.org
5. Nginx配置虚拟主机的步骤
1)增加一个完整的Server标签段到结尾处。注意,要放在HTTP的结束大括号前,也就是将Server标签段放入HTTP标签。
2)更改server_name及对应网页的root根目录,如果需要其他参数,可以增加或修改。
3)创建server_name域名对应网页的根目录,并且建立测试文件,如果没有index首页,访问会出现403错误。
4)检查Nginx配置文件语法,平滑重启Nginx服务,快速检查启动结果。
5)在客户端对server_name处配置的域名做host解析或DNS配置,并检查(ping域名看返回的IP对不对)。
6)在Win32浏览器中输入地址访问,或者在Linux客户端做hosts解析,用wget或curl接地址访问。
7. 企业场景中重启Nginx后的检测策略
在企业运维实战场景中,每一个配置操作处理完毕后都应该进行快速有效的检查,这是一个合格运维人员的良好习惯。在大型企业中,在启动Nginx的同时,还会调用脚本通过获取header信息或模拟用户访问指定URL(wget等方式)来自动检查Nginx的启动是不是真的正常,最大限度地保证服务重启后,能迅速确定网站情况,而无须收工敲命令查看。这样,如果配置有问题(非语法问题,语法问题已经用-t参数检查过了),就可以迅速使用上一版备份的配置文件覆盖回来,使得影响用户的时间最短。
下面是一个重启Nginx服务后,检查启动是否正常的脚本,可以把它包含在Nginx启动脚本(需要另外开发)内部的start等启动位置。
[root@web01 conf]# cat -n check_url.sh
1 #!/bin/bash
2 #--------function split--------
3 . /etc/rc.d/init.d/functions
4 function checkURL()
5 {
6 checkUrl=$1
7 echo 'check url start ...'
8 judge=($(curl -I -s --connect-timeout 2 ${checkUrl}|head -1 | tr " " "\n"))
9 if [[ "${judge[1]}" == '200' && "${judge[2]}" == 'OK' ]]
10 then
11 action "${checkUrl}" /bin/true
12 else
13 action "${checkUrl}" /bin/false
14 echo -n "retrying again...";sleep 3;
15 judgeagain=($(curl -I -s --connect-timeout 2 ${checkUrl}| head -1| tr "\r" "\n"))
16 if [[ "${judgeagain[1]}" == '200' && "${judgeagain[2]}" == 'OK' ]]
17 then
18 action "${checkUrl}, retried again" /bin/true
19 else
20 action "${checkUrl}, retried again" /bin/false
21 fi
22 fi
23 sleep 1;
24 }
25 # usage method
26 checkURL http://www.etiantian.org
[root@web01 conf]# sh check_url.sh
check url start ...
http://www.etiantian.org [失败]
retrying again...http://www.etiantian.org, retried again [ 确定 ]
此脚本功能是检测访问WWW网站时相应header是否返回200,以及状态是否为OK。当检测失败时,3秒后再检测一次,然后,格式化检测结果输出,如果有多个域名可以对上述命令传参的不同域名循环检查。检测方法可以是端口、URI、相应header等,具体将根据业务需求进行选择。
网友评论