2020-03-23 Nginx虚拟主机配置实战

1. 虚拟主机概念和类型介绍

1.1 虚拟主机概念

所谓虚拟主机,在Web服务里就是一个独立的网站站点,这个站点既可以对应独立的域名(也可能是IP或端口),具有独立的程序及资源目录,又可以独立地对外提供服务供用户访问。
这个独立的站点在配置里是由一定格式的标签段标记,对于Apache软件来说,一个虚拟主机的标签段通常被包含在内,而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虚拟主机配置的下面,增加的内容如下图所示。

Nginx基于域名的虚拟主机图

在整体格式上,新增域名虚拟主机的配置和前面配置过的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:  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:  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:  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:  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等,具体将根据业务需求进行选择。

你可能感兴趣的:(2020-03-23 Nginx虚拟主机配置实战)