Nginx配置虚拟主机

可以实现在一台服务器虚拟出多个网站。例如个人网站使用的虚拟主机。

虚拟主机技术是互联网服务器采用的节省服务器硬件成本的技术,虚拟主机技术主要应用于HTTP服务,将一台服务器的某项或者全部服务内容逻辑划分为多个服务单位,对外表现为多个服务器,从而充分利用服务器硬件资源。

虚拟主机是使用特殊的软硬件技术,把一台真实的物理服务器主机分割成多个逻辑存储单元。每个逻辑单元都没有物理实体,但是每一个逻辑单元都能像真实的物理主机一样在网络上工作,具有单独的IP地址(或共享的IP地址)、独立的域名以及完整的Internet服务器(支持WWW、FTP、E-mail等)功能。

虚拟主机的关键技术在于,即使在同一台硬件、同一个操作系统上,运行着为多个用户打开的不同的服务器程式,也互不干扰。而各个用户拥有自己的一部分系统资源(IP地址、文档存储空间、内存、CPU等)。各个虚拟主机之间完全独立,在外界看来,每一台虚拟主机和一台单独的主机的表现完全相同。所以这种被虚拟化的逻辑主机被形象地称为“虚拟主机”。

  • 基于多IP的方式
  • 基于多端口的方式
  • 基于多域名的方式
1、基于多IP的方式
[root@web01 conf.d]# vim game.conf 
[root@web01 conf.d]# cat game.conf 
server {
    listen 80;
    server_name 192.168.15.7;
    location / {
	root /opt/Super_Marie;
        index index.html;
    }
}
server {
    listen 80;
    server_name 172.16.1.7;
    location / {
        root /opt/tank;
        index index.html;
    }
}
# 测试:浏览器访问
192.168.15.7
172.16.1.7

2、基于多端口的方式
[root@web01 conf.d]# vim game1.conf 
[root@web01 conf.d]# cat game1.conf 
server {
    listen 80;
    server_name 192.168.15.7;
    location / {
        root /opt/Super_Marie;
        index index.html;
    }
}
server {
    listen 81;
    server_name 192.168.15.7;
    location / {
        root /opt/tank;
        index index.html;
    }
}

# 测试:浏览器访问
192.168.15.7
192.168.15.7:81

3、基于多域名的方式
[root@web01 conf.d]# vim game2.conf 
[root@web01 conf.d]# cat game2.conf 
server {
    listen 80;
    server_name www.game.com;
    location / {
        root /opt/Super_Marie;
        index index.html;
    }
}
server {
    listen 80;
    server_name www.game1.com;
    location / {
        root /opt/tank;
        index index.html;
    }
}

# 测试:浏览器访问
www.game.com
www.game1.com

Nginx日志

  • nginx的log日志分为access log 和 error log
  • 其中access log 记录了哪些用户,哪些页面以及用户浏览器、ip和其他的访问信息
  • error log 则是记录服务器错误日志
  • Nginx有非常灵活的日志记录模式,每个级别的配置可以有各自独立的访问日志。日志格式通过log_format命令定义格式
access_log  /var/log/nginx/access.log  main;

access_log  	#日志的模块
/var/log/nginx/access.log  	#日志的路径
main;	#日志的格式


日志的格式
 log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

$remote_addr        # 记录客户端IP地址
$remote_user        # 记录客户端用户名
$time_local         # 记录通用的本地时间
$time_iso8601       # 记录ISO8601标准格式下的本地时间
$request            # 记录请求的方法以及请求的http协议
$status             # 记录请求状态码(用于定位错误信息)
$body_bytes_sent    # 发送给客户端的资源字节数,不包括响应头的大小
$bytes_sent         # 发送给客户端的总字节数
$msec               # 日志写入时间。单位为秒,精度是毫秒。
$http_referer       # 记录从哪个页面链接访问过来的
$http_user_agent    # 记录客户端浏览器相关信息
$http_x_forwarded_for #记录经过的所有服务器的IP地址(在反向代理中生效)
$X-Real-IP		   #记录起始的客户端IP地址和上一层客户端的IP地址
$request_length     # 请求的长度(包括请求行, 请求头和请求正文)。
$request_time       # 请求花费的时间,单位为秒,精度毫秒

# 注:如果Nginx位于负载均衡器,nginx反向代理之后, web服务器无法直接获取到客户端真实的IP地址。
# $remote_addr获取的是反向代理的IP地址。 反向代理服务器在转发请求的http头信息中,
# 增加X-Forwarded-For信息,用来记录客户端IP地址和客户端请求的服务器地址。

ps:出现报错等问题首先应该查看报错日志
排错:
 [root@web01 ~]# systemctl status nginx.service -l
查看报错日志:
 [root@web01 ~]# cat /var/log/nginx/error.log

json日志模板

log_format json '{"@timestamp":"$time_iso8601",'
                  '"host":"$server_addr",'
                  '"service":"nginxTest",'
                  '"trace":"$upstream_http_ctx_transaction_id",'
                  '"log":"log",'
                  '"clientip":"$remote_addr",'
                  '"remote_user":"$remote_user",'
                  '"request":"$request",'
                  '"http_user_agent":"$http_user_agent",'
                  '"size":$body_bytes_sent,'
                  '"responsetime":$request_time,'
                  '"upstreamtime":"$upstream_response_time",'
                  '"upstreamhost":"$upstream_addr",'
                  '"http_host":"$host",'
                  '"url":"$uri",'
                  '"domain":"$host",'
                  '"xff":"$http_x_forwarded_for",'
                  '"referer":"$http_referer",'
                  '"status":"$status"}';
    		access_log /var/log/nginx/access.log json;

Nginx模块介绍

Nginx模块官方文档TP

Nginx访问控制模块

  • ngx_http_access_module
允许或者拒绝某些客户端地址的访问
deny  : 拒绝
allow : 允许

案例1:允许192.168.15.1访问,不允许其他IP访问
server {
    listen 80;
    server_name www.game.com;
    location / {
        root /opt/Super_Marie;
        index index.html;
    }
    allow 192.168.15.1; 
    deny all;
}
   

案例2:允许192.168.15.0这个网段访问,不允许其他网段访问
server {
    listen 80;
    server_name www.game.com;
    location / {
        root /opt/Super_Marie;
        index index.html;
    }
    allow 192.168.15.0/24; 
    deny all;
}


案例3:只允许通过VPN来访问
server {
    listen 80;
    server_name www.game.com;
    location / {
        root /opt/Super_Marie;
        index index.html;
    }
    allow 172.16.1.81; 
    deny all;
}
 
ps:每次修改完配置需要重启nginx
[root@web01 ~]# systemctl restart nginx

Nginx访问认证模块

  • ngx_http_auth_basic_module
访问之前需要登录

# 注釋
auth_basic "Welcome To Login";
# 指定认证的文件
auth_basic_user_file /etc/nginx/auth;


1、安装httpd-tools
[root@web01 ~]# yum install httpd-tools -y

2、生成用户名密码文件
[root@web01 ~]# htpasswd -c /etc/nginx/auth gengfeng
New password: 
Re-type new password: 
Adding password for user gengfeng

3、查看密码文件内容
[root@web01 ~]# cat /etc/nginx/auth 
gengfeng:$apr1$b5wYYZ9b$PzcNn9gq.fgYUR4l0M3OL/


4、将文件路径加入Nginx配置
[root@web01 ~]# vim /etc/nginx/conf.d/game.conf
server {
        listen 80;
        server_name game.test.com;
        location / {
                root /opt/Super_Marie;
                index index.html;
                }
        auth_basic "Welcome To Login";
        auth_basic_user_file /etc/nginx/auth;
        }


5、重启Nginx
[root@web01 ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@web01 ~]# systemctl restart nginx 

6、测试
 浏览器访问 http://game.test.com

nginx的虚拟主机 nginx虚拟主机模块是什么_nginx的虚拟主机

Nginx目录索引模块

  • ngx_http_autoindex_module
展示目录索引

#启用或禁用目录列表输出。(默认off)
autoindex on | off;

#显示具体大小 off 显示K/M/G单位   on 单位就是 bytes (默认on)
autoindex_exact_size on | off;

#显示文件最后修改时间  如果是 off 需要加8小时(默认off)
autoindex_localtime on | off;

#设置目录列表的格式(默认html)
autoindex_format html | xml | json | jsonp;


[root@web01 ~]# vim /etc/nginx/conf.d/game.conf
server {
        listen 80;
        server_name game.test.com;
        location / {
                root /opt/Super_Marie;
                }
        autoindex on;
        autoindex_exact_size on;
        autoindex_localtime on;
        autoindex_format html;
        }
[root@web01 ~]# systemctl restart nginx 

#测试:
 浏览器访问 http://game.test.com

nginx的虚拟主机 nginx虚拟主机模块是什么_nginx的虚拟主机_02

Nginx状态监控模块

  • ngx_http_stub_status_module
监控Nginx运行状态

[root@web01 ~]# vim /etc/nginx/conf.d/game.conf
[root@web01 ~]# cat /etc/nginx/conf.d/game.conf 
server {
        listen 80;
        server_name game.test.com;
        location / {
                root /opt/Super_Marie;
                index index.html;
        }
        location /status {
                stub_status;
        }
}

[root@web01 down]# nginx -s reload  #重载


#测试:浏览器访问 http://game.test.com/status

nginx的虚拟主机 nginx虚拟主机模块是什么_IP_03

Nginx的七种状态

Active connections
   当前活动客户端连接数,包括Waiting连接数。
accepts
   接受的客户端连接总数。
handled
   处理的连接总数。通常,accepts 除非达到某些资源
   限制(例如,worker_connections限制),否则 该参数值是相同的。
requests
   客户端请求的总数。
Reading
   nginx 正在读取请求头的当前连接数。
Writing
   nginx 将响应写回客户端的当前连接数。
Waiting
   当前等待请求的空闲客户端连接数。

#注意:一次tcp连接,可以发起多次请求;
keepalive_timeout  0;   #类似于关闭长连接
keepalive_timeout  65;	#最长65秒没有活动则断开连接

Nginx连接限制模块

  • ngx_http_limit_conn_module
用于限制每个定义的键的连接数,特别是来自单个IP地址的连接数。

limit_conn : 该指令指定每个给定键值的最大同时连接数,当超过这个数字时返回503错误
limit_conn_log_level : 当达到最大限制连接数后,记录日志的等级,默认error级别
limit_conn_status : 指定当超过限制时,返回的状态码。默认是503。
limit_conn_zone : 主要用来定义变量、zone名称、共享内存大小
  $remote_addr
      变量的长度为7字节到15字节,而存储状态在32位平台中占用32字节或64字节,
      在64位平台中占用64字节。
  $binary_remote_addr
      变量的长度是固定的4字节,存储状态在32位平台中占用32字节或64字节,
      在64位平台中占用64字节。

ps:1M共享空间可以保存3.2万个32位的状态,1.6万个64位的状态。如果共享内存空间被耗尽,
   服务器将会对后续所有的请求返回 503 (Service Temporarily Unavailable) 错误。


控制Nginx连接数
[root@web01 ~]# vim /etc/nginx/conf.d/game.conf
[root@web01 ~]# cat /etc/nginx/conf.d/game.conf
limit_conn_zone $remote_addr zone=addr:1m;
limit_conn_log_level error;
limit_conn_status 503;
server {
    listen 80;
    server_name 192.168.15.8;
    limit_conn addr 1;
    location / {
        root /opt/Super_Marie;
        index index.html;
    }
}

[root@web01 down]# nginx -s reload

测试
  1、安装ab压力测试命令
  [root@web01 ~]# yum install httpd-tools -y 

  2、ab 参数
     -n : 总共需要访问多少次
     -c : 每次访问多少个

测试结果:
[root@web01 ~]# ab -n 10000 -c 1000 http://192.168.15.8/
.....

Benchmarking 192.168.15.8 (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
Completed 10000 requests
Finished 10000 requests


Server Software:        nginx/1.20.2
Server Hostname:        192.168.15.8
Server Port:            80

Document Path:          /
Document Length:        1703 bytes

Concurrency Level:      1000
Time taken for tests:   6.416 seconds
Complete requests:      10000  #总共访问1万次
Failed requests:        128    #失败次数128次
   (Connect: 0, Receive: 0, Length: 64, Exceptions: 64)
Write errors:           0
Total transferred:      19246032 bytes
HTML transferred:       16921008 bytes
Requests per second:    1558.69 [#/sec] (mean)
Time per request:       641.562 [ms] (mean)
Time per request:       0.642 [ms] (mean, across all concurrent requests)
Transfer rate:          2929.56 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0  243 253.4    203    1310
Processing:    75  371 111.0    365     656
Waiting:        0  311 106.6    310     612
Total:        173  613 270.2    569    1752

Percentage of the requests served within a certain time (ms)
  50%    569
  66%    599
  75%    654
  80%    667
  90%    719
  95%   1479
  98%   1637
  99%   1718
 100%   1752 (longest request)

Nginx请求限制模块

  • ngx_http_limit_req_module
基于漏桶算法实现的请求限流模块,用于对指定KEY对应的请求进行限流,比如按照IP维度限制请求速率

limit_req : 配置限流区域、桶容量(突发容量,默认0)、是否延迟模式(默认延迟)
limit_req_log_level : 配置记录被限流后的日志级别,默认error级别
limit_req_status : 配置被限流后返回的状态码,默认返回503
limit_req_zone : 配置限流KEY、及存放KEY对应信息的共享内存区域大小、固定请求速率
    $binary_remote_addr
       变量,可以将每条状态记录的大小减少到64个字节,这样1M的内存可以保存大约1万6千个64字节的记录。
    zone=one:10m  
       区域名称为one,大小为10m
    固定请求速率
       使用rate参数配置,支持10r/s和60r/m,即每秒10个请求和每分钟60个请求,不过最终都会转换
       为每秒的固定请求速率(10r/s为每100毫秒处理一个请求;60r/m,即每1000毫秒处理一个请求)


控制Nginx访问量

	1、连接池
		limit_req_zone $remote_addr zone=one:10m rate=1r/s;
		声明连接池       变量          名称 连接池的大小  速率

	2、限制数

案例:要求每秒只能有一个访问。
[root@web01 ~]# vim /etc/nginx/conf.d/game.conf
[root@web01 ~]# cat /etc/nginx/conf.d/game.conf
limit_req_zone $remote_addr zone=one:10m rate=1r/s;
limit_req_log_level error;
limit_req_status 503;
server {
    listen 80;
    server_name game.test.com;
    limit_req zone=one burst=5;
    location / {
        root /opt/Super_Marie;
        index index.html;
    }
}

[root@web01 down]# nginx -s reload

nginx的虚拟主机 nginx虚拟主机模块是什么_nginx的虚拟主机_04

Nginx的location配置

使用Nginx location可以控制访问网站的路径, 但一个server可以有多个location配置, 多个location的优先级该如何区分。

location 的匹配顺序其实是“先匹配普通,再匹配正则”。
   nginx 是“先匹配正则 location 再匹配普通 location ”,其实这是一个误区, nginx 其实
   是“先匹配普通 location ,再匹配正则 location ”。
   但是普通 location 的匹配结果又分两种:
     一种是“严格精确匹配”,官方英文说法是“ 准确匹配 ”;
     一种是“最大前缀匹配”,官方英文说法是“ 字面值字符串匹配开始部分 查询的-将使用最具体的匹配 ”。

location 匹配的优先级(与location在配置文件中的顺序无关)
  = 精确匹配会第一个被处理。如果发现精确匹配,nginx停止搜索其他匹配。
  普通字符匹配,正则表达式规则和长的块规则将被优先和查询匹配,也就是说如果该项匹配还需去看有
  没有正则表达式匹配和更长的匹配。
  ^~ 则只匹配该规则,nginx停止搜索其他匹配,否则nginx会继续处理其他location指令。最后匹配
  带有"~"和"~*"的指令,如果找到相应的匹配,则nginx停止搜索其他匹配;当没有正则表达式或者没有
  正则表达式被匹配的情况下,那么匹配程度最高的逐字匹配指令会被使用

location语法

Syntax:	location [ = | ~ | ~* | ^~ ] uri { ... }
location @name { ... }
Default:	—
Context:	server, location

location匹配符号

匹配符

匹配规则

优先级

=

精确匹配

1

^~

以某个字符串开头,一般用来匹配目录

2

~

区分大小写的正则匹配

3

~*

不区分大小写的正则匹配

4

/

通用匹配,任何请求都会匹配到

5

优先级认证

示例:
[root@web01 ~]# cat /etc/nginx/conf.d/text.conf 
server {
    listen 80;
    server_name 192.168.15.8;
   
    location ~* /python {
        default_type text/html;
        return 200 "Location ~*";
    }

    location ~ /Python {
        default_type text/html;
        return 200 "Location ~";
    }

    location ^~ /python {
        default_type text/html;
        return 200 "Location ^~";
    }

    location = /python {
        default_type text/html;
        return 200 "Location =";
    }
}

案例:
[root@web01 ~]# cat /etc/nginx/conf.d/text1.conf 
server {
   listen 80;
   server_name 192.168.15.8;
	# 访问站点根目录
	 location / {
		root /usr/share/nginx/html;
		index index.html;
	 }
	
	# 访问图片
	 location ~* \.(jpg|gif|png|jpeg) {
	 deny all;
	 }
	# 访问监控,需要输入用户名密码
	 location =/status {
		auth_basic           "closed site";
		auth_basic_user_file /etc/nginx/auth_basic;
		stub_status;
	 }
}

location应用场景

#通用匹配,任何请求都会匹配到
location / {
    ...
}
 
#严格区分大小写,匹配以.py结尾的都走这个location    
location ~ \.py$ {
    ...
}
 
#严格区分大小写,匹配以.html结尾的都走这个location 
location ~ \.html$ {
    ...
}
 
#不区分大小写匹配,只要用户访问.jpg,gif,png,js,css结尾的都走这条location
location ~* .*\.(jpg|gif|png|js|css)$ {
    ...
}
 
#不区分大小写匹配
location ~* "\.(sql|bak|tgz|tar.gz|.git)$" {
    ...
}

从来就没有正确的选择,我们只不过是要努力奋斗,使当初的选择变得正确。