五种IO模型和nginx的web模块

IO模型

前言

  • 对于一些公共的底层的资源,都是由linux内核来管控的。比如磁盘IO,网络IO等。
  • 用户空间内的程序如果需要调用这些IO,需要向内核发起申请。也叫系统调用
  • 对于程序来说,它内部必定有相对应的函数来进行系统调用。那么在进行交互时,程序和内核的交互消息是怎么通知的?
  • 既然它们有交互,那么程序在等待内核消息的时候它的状态都有哪些?

消息通知

以磁盘IO为例。
同步: 程序在申请磁盘IO的操作时,程序就一直等待,直到内核将申请的磁盘IO功能完整的结束并响应给程序
异步:还是程序申请调用磁盘IO,程序不在傻傻等待内核完成操作的信息,而是先让内核接着工作。程序去做别的事情。但是程序会专门给内核留一个方法,以便内核完成工作的时候可以找到程序。

IO模型

还是以磁盘IO为例,注意:IO不止有磁盘,还有网络IO,但是它们基本没有区别。

对于一次完整的文件IO来说,由两阶段组成:

  • 等待数据,由磁盘将数据复制到内核内存
  • 复制数据,由内核内存复制到进程内存
    这两步操作是因为程序无法直接操作底层硬件。都得去向内核发起系统调用。
    上边已经说了消息通知,同步是等待,问题是怎么等待?这就有了IO模型,用来关注程序(也就是调用者)在结果返回之前的状态。
    在这里插入图片描述
  • 同步阻塞:在结果返回来之前,调用者会被挂起。意思是操作没完成,调用者会睡去,什么都不干。而这个睡眠态是无法唤醒的。谁来都不好使。上图就是同步阻塞,进程通过recvfrom函数向应用进程发送请求访问,应用进程向内核申请调用磁盘数据,在拿不到内核返回的磁盘数据之前,进程将会被阻塞在recvfrom函数调用,直到结果返回。

在这里插入图片描述

  • 同步非阻塞:结果返回来之前,调用者不会被挂起,但是它仍然什么事情都不能干。它的等待方式就是一遍遍的去问内核,完成操作了么?直到内核结束操作。只有第一步是非阻塞的,第二步仍然是阻塞的。上图为同步非阻塞

在这里插入图片描述

  • 复用器IO模型:如果调用者申请的不止磁盘IO,还有键盘IO,还有鼠标IO等等。它就会将自己阻塞在的内核一个复用器上,然后告知内核我就在这个复用器上等你消息,你完成一项就通知我一项好了。对于IO复用的实现:select函数以及poll函数。httpd的prefork工作模式就是采用select函数,它的意思是一个主控进程只能监听1024路个请求,也就是所谓的最大并发数量是1024个。而poll没有限制。 上图为复用器io模型
  • even模型:事件驱动模型。 调用者在发起请求后,不再等待第一步的完成,而是去想干嘛就干嘛。直到结果返回过来说第一步已经完成,这时调用者回来接着完成第二步。对一步来说只是异步的,第二步仍然是阻塞的。事件驱动型的IO实现:epoll函数。
  • 异步非阻塞:完全异步,不参与io的任何操作,直接拿到内核完成两步的结果即可。
    关于io模型的文章发现一篇不错:https://www.cnblogs.com/dongguacai/p/5770287.html

nginx

在这里插入图片描述
Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务。根据上图简单介绍下nginx的工作方式。

  • 一个master主控进程,主要功能:负责加载和分析配置文件。管理work进程。平滑升级(例如你的web服务需要从0.8升级到0.9,先将master升级,然后生成新的worker进程处理0.9版本。老的worker进程等处理完请求之后再升级为0.9版本即可。)
  • worker:可以有一个或多个进程。用来处理并响应用户的请求。worker中的小方块就是nginx自带的模块。master监控work的进程,当有worker进程发生异常退出时,会立马创建一个worker进程。
  • cache loader:载入缓存对象。cache manager:管理缓存对象。当一个用户访问磁盘上的内容时,nginx会把它缓存下来,这样当第二个用户访问同样内容,nginx会将缓存直接响应给第二个用户。
  • nginx采用异步非阻塞、事件驱动模型来保证自己可以拥有高并发、高性能的能力。通过epoll()和select()函数来让自己处理并发更高一筹。
  • IO方面采用sendfile、AIO(异步IO)等,加速磁盘的IO性能。

nginx模块

nginx是高度模块化的,在早期版本中不支持DSO机制,也就是在编译的时候编译进去了什么模块就只有什么模块,不能动态装卸模块。在1.0 版本之后,有了动态装卸模块的功能,但也仅对个别模块有效。

  • nginx模块的分类
    • core_module:核心模块
    • HTTP_modules:web模块
      • Standard HTTP modules:标准模块
      • Optional HTTP modules:可选模块
    • mail module:邮件模块
    • Stream module:流模块
      下面主要讲解core模块和web模块的使用

安装nginx

官方提供了官方安装的版本,centos上在epel仓库中也提供了安装版本。两者有略微不同,功能都是一样的。下面以epel仓库安装的为示例。

yum  install epel-release
yum install nginx

程序环境:

  • 主配置文件:nginx.conf
  • 主程序文件:/usr/sbin/nginx
  • Unit File:nginx.service

nginx命令的用法:

[root@ydong2 ~]# nginx -h
nginx version: nginx/1.12.2
Usage: nginx [-?hvVtTq] [-s signal] [-c filename] [-p prefix] [-g directives]

Options:
  -?,-h         : this help
  -v            : show version and exit        #输出版本号
  -V            : show version and configure options then exit    # 输出编译默认添加的模块以及安装路径
  -t            : test configuration and exit      #测试nginx.conf文件中的语法是否正确
  -T            : test configuration, dump it and exit   
  -q            : suppress non-error messages during configuration testing
  -s signal     : send signal to a master process: stop, quit, reopen, reload   #可以给nginx发送信号,停止,退出,重启,重载
  -p prefix     : set prefix path (default: /usr/share/nginx/) #重新设置安装路径
  -c filename   : set configuration file (default: /etc/nginx/nginx.conf) # 重新设置配置文件路径
  -g directives : set global directives out of configuration file

运行nginx:systemctl start nginx.service
和httpd一样,运行完成之后监听在80端口,可直接在网页访问本地地址。
在这里插入图片描述

nginx.conf的配置

(1)主配置文件的配置指令:directive value [value2 ...];
注意:

  • 配置文件中的指令要以;号结尾
  • 可以使用nginx中的变量
    • 内建变量:由nginx模块提供, 可以直接引用。但是有的变量被某些模块所依赖,所以只能使用编译安装模块的内建变量。有的变量没有指明模块,则可以直接使用。
    • 自定义变量:由用户自定义设置变量,set variable_name value;
      在这里插入图片描述
      (2)主配置文件的架构:
配置段解释
main block主配置段,也就是全局配置
event事件驱动类型的相关配置,比如并发数量等
httpHTTP的相关配置
mailmail的相关配置
streamstream的相关配置
main段相关指令

main配置段常见的配置指令: 相关配置可查看官方文档里的Core functionality

  • 正常运行必备的配置
  • 优化性能相关的配置
  • 用于调试及定位问题相关的配置
  • 事件驱动相关的配置

在这里插入图片描述
以上图为例:
1、正常运行必备的配置
(1)user:定义启动worker进程的用户,安装nginx之后,默认为nginx。

nginx      8050  0.0  0.3 127476  3576 ?        S    23:20   0:00 nginx: worker process
nginx      8051  0.0  0.3 127476  3776 ?        S    23:20   0:00 nginx: worker process
nginx      8052  0.0  0.3 127476  3796 ?        S    23:20   0:00 nginx: worker process
nginx      8053  0.0  0.3 127476  3568 ?        S    23:20   0:00 nginx: worker process

(2)pid /run/nginx.pid:指明存储nginx主进程号码的文件路径

(3)include /usr/share/nginx/modules/*.conf:指明要装载的模块

(4)include /PATH/TO/*.conf:指明包含进来的其他配置的片段

2、性能优化相关的配置
(1) worker_processes auto | number:决定worker进程的数量。它是由你的CPU物理核心决定的,比如你是4核的,auto就自动启动为4个进程。当然也可以指定你要启动的进程数Number。通常要设置成小于等于你的物理核心。如果你设置超过了你的核心数,只会增加nginx的负担。epel包安装完成之后,默认auto。

示例:将worker进程数设置为2
在这里插入图片描述

nginx      8273  0.0  0.4 128176  4188 ?        S    23:39   0:00 nginx: worker process
nginx      8274  0.0  0.4 128176  4188 ?        S    23:39   0:00 nginx: worker process

(2)worker_cpu_affinity auto [cpumask]:绑定进程到指定的cpu物理核心上
假如你的CPU上有2个核心,每个核心上处理一个进程。这两个进程可能在某一时刻会互换CPU核心。大家知道每个cpu核心上都有缓存功能。如果进程来回互换位置,那么进程换一次就要重新缓存。这样极大的浪费了CPU时钟周期。所以我们要把进程进行绑定到CPU核心上,让它们不再互换位置。
示例:
在这里插入图片描述
在这里插入图片描述
将worker_cpu_affinity设置成auto,自动绑定进程和cpu。也可以使用mask来指定要绑定的cpu核心。例如你的cpu核心数为4个,那它的从0-3的表示方法就是:0001,0010,0100,1000。就是你有几个核心数,就有几个0。
示例:
在这里插入图片描述

[root@ydong2 ~]# ps axo user,psr,comm  | grep nginx
root       1 nginx
nginx      3 nginx
nginx      2 nginx
nginx      1 nginx
nginx      0 nginx
#再次进行压测,cpu就不会改变了。

(3) worker_priority number:用来设置worker进程的优先级,默认为0

[root@ydong2 ~]# ps axo user,comm,ni | grep nginx
root     nginx             0
nginx    nginx             0
nginx    nginx             0
nginx    nginx             0
nginx    nginx             0

在这里插入图片描述

[root@ydong2 ~]# ps axo user,comm,ni | grep nginx
root     nginx             0
nginx    nginx           -10
nginx    nginx           -10
nginx    nginx           -10
nginx    nginx           -10

(4)worker_rlimit_nofile number:worker进程能够打开文件的数量上限。主要用于并发访问时请求打开文件的数量。
在这里插入图片描述
当并发数量超过打开文件上限,会有一些用户会得不到响应。配置的太小也会影响并发访问的性能。当然设置这么高,也不一定就会打开这么多的文件。
3、调试,定位问题的配置
(1)daemon on|off:是否以守护进程运行nginx。主要用于开发过程中。
(2)master_process on|off:是否以master/worker架构来运行nginx,默认为on。off表示只以master来进程处理。off也只适用于开发人员。
(3)error_log file [level] :管理错误日志,这是自我管理,而非rsyslog管理。因为nginx产生的日志量太大了。所以要专门放置一个文件来存放它自己的日志。
level的级别有:debug, info, notice, warn, error, crit, alert, or emerg.默认级别: error, crit, alert, and emerg
示例:
在这里插入图片描述
4、事件驱动类型配置 events{...}
(1)worker_connections:每个worker进程能够打开的并发最大响应数量,默认为1024路。所以4个进程能够打开的是4*1024
在这里插入图片描述

(2)use method:指明并发连接请求的处理方法。
官方解释:nginx支持各种连接处理方法。特定方法的可用性取决于所使用的平台。在支持多种方法的平台上,nginx通常会自动选择最有效的方法。如果要使用:可以选择selectpollkqueueepoll官方文档的解释

(3)accept_mutex on | off:处理新的连接的请求方法。on意味着每个worker进程轮流处理心情求。off表示每个新请求的到达都会通知所有的worker进程。
解释:例如10个请求进来之后,分给了4个进程。on的意思就是在重新进来1个请求之后,还是分给第一个进程,无论它是否还在处理别的进程。off的意思就是重新进来一个请求之后,4个进程谁先抢到就给谁处理。off的话再请求进来之后会将所有的进程唤醒,反而会影响机器的

示例:
在这里插入图片描述

HTTP模块配置

在这里插入图片描述

与套接字相关的配置

1、server{…}

用来配置虚拟主机,每一个server就是一个虚拟主机。
2、listen指令
语句格式:listen address[:port] [default_server] [ssl] [http2 | spdy] [backlog=number] [rcvbuf=size] [sndbuf=size]

解释
addressIP地址
port监听端口
default_server默认主机
ssl限制仅能够通过ssl连接提供服务
backlog=number后援队列长度
rcvbuf=size接收缓冲区大小
sndbuf=size发送缓冲区大小

3、server_name name
指明虚拟主机的主机名称。由以下几种方式:

  • 支持*号通配任意长度的任意字符;
  • 支持~号起始的字符做正则表达式模式匹配

对于有多个虚拟主机的匹配机制:

  • 字符串精确匹配;
  • 左侧*通配符;
  • 右侧*通配符;
  • 正则表达式;
  • \d表示0-9
    在这里插入图片描述

4、tcp_nodelay on | off
在keepalived模式下的连接是否启用TCP_NODELAY选项。
delay:延迟发送,当报文从应用层向下传输封装的时候,外部的封装已经大于报文本身的大小。这时候发送就会很浪费带宽。所以就攒着一块儿发送。这就是delay。用户在接收报文的时候,小的的报文会延迟收到。大大的影响了用户体验。只有nodelay,有多大发多大。不延迟,用户体验才好。

5、tcp_nopush on|off
它与nodelay差不多,也是将包攒起来 一起发送。只不过它可以设置一次发送包的大小。它只能和sendfile搭配使用。

6、sendfile on|off
当请求报文进来之后,由内核转交给用户空间进程,然后用户空间进程向内核发起系统调用。内核从硬盘读取数据复制到自己的内存中。再将数据由内核空间复制到用户空间的内存中去。用户空间响应时再次将处理的数据发送至内核中,然后由内核转发给用户响应报文。sendfile去除了由内核空间和用户空间之间的转换。直接由内核进行硬盘的数据处理,发送给用户响应报文。

点击这里查看3者的区别。

7、types_hash_max_size number
设置hash表的最大值,当一个资源请求发过来时,nginx为了加速内部的运行,将访问资源的hash值保存在内存中。当另一个同样的资源请求发过来时,nginx就可以使用已经保存的hash值来快速响应给客户。epel包安装完成之后默认为2048

8、隐藏nginx版本
为了不显示当前服务器使用的nginx的版本,需要server_tokens off即可

[root@localhost ~]# curl -I www.a.com
HTTP/1.1 200 OK
Server: nginx   #就不会再显示版本号了

与路径相关的配置

1、root path
设置web资源路径映射,相当于httpd的DocumentRoot。它的配置范围区域:http,server,location,if in location。
http配置段内的root和server中root不一样,server中的root会覆盖掉http中的root。同样,location内的root也是如此。

2、location [ = | ~ | ~ | ^~ ] uri { … }*
主要用于在server中实现从uri到文件路径的实现。nginx会根据用户请求的URI来检查定义的所有location,并找出一个最佳匹配,而后应用其配置。

符号解释
=做精确匹配,优先级最高
^~对URI的左半部分做匹配检查。不区分大小写,优先级次之
~对URI做正则表达式匹配,区分大小写,优先级第三
~*对URI做正则表达式匹配,不区分大小写,优先级与~一样
不带符号匹配始于此URI的所有的URL

URL和URI的区别

示例:

  1 server {
  2     listen 80;
  3     server_name www1.ydong.com;
  4     root /data/;
  5     location = / {                         #1
  6         root /data/nginx/;
  7     }
  8 
  9     location /pictures/ {                 #2
 10         root /data/nginx/;
 11     }
 12 
 13     location ~* \.(jpg|png)$ {           #3
 14         root /data/nginx/;
 15     }
 16 
 17 
 18     location / {                         #4
 19         root /data/nginx/;
 20     }
 21 
 22     location ^~ /images/ {                #5
 23         root /data/nginx/;
 24     }
 25 }   

(1)当访问www1.ydong.com的时候,匹配1,4,但是优先级最高的是第一个。用location精确定位主页访问,可以加速网页的访问。

(2)访问www1.ydong.com/pictures/fish.jpg, 匹配2,3,4,优先级最高的为3。

(3)访问www1.ydong.com/images/book.jpg,匹配3,5 ,  优先级最高为5。
注意:location中定义的root会自动覆盖掉server中定义的root。     

3、 alias path
定义路径别名,文档映射的另一种机制,只能用于location的上下文中。
location中的root和alias的区别:

  • root,给定的路径对应于location中/uri/左侧的/。例如/images/ root /data/nginx/ images前面的/号是nginx后面的/号
  • alias ,与root相反,是位于右侧。例如:/images/ alias /data/nginx/ nginx后面的/是images右侧的/,简单理解就是访问images时,访问的内容是/data/nginx/下的index.html
 官方解释:location /i/ {
        alias /data/w3/images/;
    }
    on request of “/i/top.gif”, the file /data/w3/images/top.gif will be sent.
    访问/i/top.gif,/data/w3/images/top.gif会发送出去。

示例:

 server {
  2     listen 80;
  3     server_name www1.ydong.com;
  4     root /data/;
  5     location = / {
  6         root /data/nginx/;
  7     }
  8 
  9     location /pictures/ {
 10         root /data/nginx/;
 11     }
 22     location ^~ /images {
 23         alias /data/nginx/;
 24     }
 25 }
[root@ydong2 nginx]# ls
fish.jpg  flower.jpg  index.html  pictures  www2    #data/nginx/下的图片文件。

访问www1.ydong.com/images/fish.jpg
路径下并没有images的文件夹,但是通过alias可以将data/nginx/fish.jpg发送出去。

在这里插入图片描述
4、error_page code … [=[response]] uri
定义自定义的错误页以及响应码。
示例:

server {
	listen 80;
	server_name www1.ydong.com;
	root /data/;
	location = / {
		root /data/nginx/;
	}
	location ^~ /images {
		alias /data/nginx/;
	}
	error_page 404 =200  /error.html;#此处是将404错误码改为200的正常响应码。 可以防止某些恶意劫持错误页。后面是错误网页
	location = /error.html {        #定义错误网页地址
		root /data/nginx/error_page; 
	}
}

[root@ydong2 nginx]# cat /data/nginx/error_page/error.html 
<h1>error 1111</h1>

在这里插入图片描述

5、try_files file … uri; try_files file … =code;
按顺序检查文件是否存在,返回第一个找到的文件或文件夹(结尾加斜线表示为文件夹),如果所有的文件或文件夹都找不到,会进行一个内部重定向到最后一个参数。只有最后一个参数可以引起一个内部重定向,之前的参数只设置内部URI的指向。最后一个参数是回退URI且必须存在,否则会出现内部500错误

[root@localhost ~]# cat /etc/nginx/conf.d/a.com.conf
server{
	listen 80;
	server_name www.a.com;
	root /data/a;

	location /images/ {
		try_files  $uri /images/day.jpg;
	}
}
# 用户在请求页面时,服务器会先查找用户请求images下的资源,如果images没有,则重定向到/images/day.jpg

在这里插入图片描述
在这里插入图片描述

所以我们将访问不到的资源直接重定向到一个提示页面。

[root@localhost a]# cat /etc/nginx/conf.d/a.com.conf 
server{
	listen 80;
	server_name www.a.com;
	root /data/a;
	error_page 404 /error.html;

	location / {
		try_files  $uri $uri/index.html $uri.html =404;
	}
	location /error.html {
		root /data/a;
	}
}

#用户在访问根下的目录,如果请求的uri无资源,先查找请求的资源是否有index.html,如果没有就跳转到404页面。

在这里插入图片描述

定义客户端请求的相关配置

1、keepalive_timeout timeout [header_timeout]
设定持续连接的超时时长,0表示禁止长连接,默认为75秒。epel安装包改为了65秒。
2、keepalive_requests number
在一次长连接上所允许请求资源的最大数量,默认为100。
3、keepalive_disable none | brower
对哪种浏览器禁止使用长连接。
4、send_timeout time
向客户端发送响应报文的超时时长,仅在两个连续的写操作之间设置超时,而不是为整个响应的传输。如果客户端在此时间内未收到任何内容,则会关闭连接。
5、client_body_buffer_size size
用于接收客户端请求报文的body部分的缓冲区大小,64位的默认为16K。32位的默认8K。超出此大小时,将被临时存储在磁盘上由client_body_temp_path指令所定义的位置。一般用于博客等需要上传的时候使用。
6、clien_body_temp_path path [leve1 [level2] [level3] ]
设定用于存储客户端请求报文的body部分的临时存储路径及子目录结构和数量;
最多可以使用3级子目录层级结构。、
在这里插入图片描述
需要找寻目录3下,子目录2中的文件时,如果能直接定位到目录3,然后在定位到子目录2下。会大大的节省时间。上述指令就是实现该功能,只不过它是使用了16进制的数字目录结构。

示例:

[root@localhost ~]# sha1sum anaconda-ks.cfg 
f34da9b6f9d93e37a88ebe8bc30bda2aac3d64ac  anaconda-ks.cfg

#一级子目录以结尾创建,16进制就有16个1级子目录,2级子目录使用4a来创建,两个16进制的数组成的数目就是256, 同样3级子目录也是两位,也是256。  
所以这样进行创建之后,1级目录下有16个子目录,  16个子目录里,每个目录有256个二级子目录。    256个二级子目录的子目录里又有256个三级子目录。
对客户端进行限制的相关配置

1、limit_rate rate
限制响应给客户端的传输速率,单位是bytes/second 默认是0,无限制
2、limit_except method … {…}
限制对指定的请求方法之外的其他方法的使用客户端。该method参数可以是下列之一: GET, HEAD, POST, PUT, DELETE, MKCOL, COPY, MOVE, OPTIONS, PROPFIND, PROPPATCH, LOCK, UNLOCK,或 PATCH。

limit_except GET {
    allow 192.168.1.0/32;
    deny  all;
}
#限制除GET以外的所有方法。  
文件操作优化的配置

1、aio on | off | threads[=pool]
是否启动异步IO功能。
2、directio size | off;
在Linux主机启用O_DIRECT标记,此处意味文件大于等于给定的大小时使用,默认为4M。 可以参考此处文章。
3、 open_file_cache off | open_file_cache max=N [inactive=time]

nginx可以换缓存一下三种信息:

  • 文件的描述符、文件大小和最近一次的修改时间
  • 打开的目录结构
  • 没有找到的或者没有权限访问的文件的相关信息
    注意:此种缓存方式是缓存的元数据,并非数据内容。

max=N:设置缓存的缓存项上限,达到上限后会启用LRU算法来进行管理。LRU:就是最近最少使用的缓存。

inactive=time:缓存项的非活动时长,此处指定的时长内未被命中的或者命中的次数少于open_file_cache_min-users指令所指定的次数的缓存项即为非活动项

3、 open_file_cache_valid time
用来指明多长时间去检查一下缓存项。

4、open_file_cache_min_uses number
在inactive time设定的时长内,至少命中多少次缓存项才能被认为活动项。

5、 open_file_cache_errors on | off
是否缓存查找时发生错误的文件一类的缓存信息。

基于ip的访问控制功能,ngx_http_access_module

总共就两个指令:

  • allow address | CIDR | unix: | all:允许哪些IP地址访问
  • deny address | CIDR | unix: | all:禁止哪些IP地址访问
    示例:
  1 server {
  2     listen 80;
  3     server_name www2.ydong.com;
  4     root /data/;
  5     keepalive_requests 1;
  6     location = / {
  7         index file.html;
  8         keepalive_requests 1;
  9         deny 192.168.199.146;
 10         allow all;
 11     }
 12 }   
 #访问www2.ydong.com 时,允许除146客户端的所有客户端访问。
ngx_http_auth_basic_module模块

实现基于用户的访问控制,使用basic机制进行用户认证
1、auth_basic string | off
提示登录时的验证信息。
2、auth_basic_user_file file
设置用于存放帐号密码的文件。可以使用htpasswd
示例:


  1 server {
  2     listen 80;
  3     server_name www2.ydong.com;
  4     root /data/;
  5     location /admin/ {
  6         root /data/nginx/;
  7         auth_basic "Enter your name and password";
  8         auth_basic_user_file /data/nginx/.passwd;
  9     }
 10 }
~          

在这里插入图片描述

ngx_http_stub_status_module模块

用户输出nginx模块的状态页面,相当于httpd的status。
示例:

 1 server {
  2     listen 80;
  3     server_name www2.ydong.com;
  4     root /data/;
  5     location /admin/ {
  6         root /data/nginx/;
  7         auth_basic "Enter your name and password";
  8         auth_basic_user_file /data/nginx/.passwd;
  9     }
 10 
 11     location /status {
 12         auth_basic "import,be careful";
 13         auth_basic_user_file  /data/nginx/.passwd;
 14         stub_status;
 15     }
 16 }

在这里插入图片描述

状态信息解释
Active connections活动状态的连接数
accepts已接受的客户端的请求的总数
handled已处理完成客户端的请求的总数
requests客户端发来请求的总数
Reading处于读取客户端请求报文首部的连接的连接数
Writing处于向客户端发送响应报文过程中的连接数
Waiting处于等待客户端发出请求的空闲连接数
ngx_http_log_module

用来定义日志格式的模块
1、log_format name [escape=default|json|none] string …
定义日志格式,string可以使用http核心模块以及其他模块的内嵌变量

2、access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]]
访问日志文件路径,格式及相关缓冲的配置。
access_log off:用来关闭日志。

3、open_log_file_cache max=N [inactive=time] [min_uses=N] [valid=time]
缓存各日志文件相关的元数据信息

  • max:缓存的最大文件描述符数量
  • min_uses:在inactive指定的时长内访问大于等于此值方可被当作活动项
  • inactive:非活动时长
  • valid:验正缓存中各缓存项是否为活动项的时间间隔
ngx_http_gzip_module

将传输数据进行压缩,虽然会影响CPU的时钟周期,但是可以大大节约带宽。
1、gzip on | off
是否启用压缩功能

2、gzip_comp_level level {0-9}
指定压缩级别

3、 gzip_disable regex …
对具有与任何指定正则表达式匹配的“User-Agent”标头字段的请求禁用gzipping响应。

4、gzip_min_length length
启用压缩功能的响应报文大小阈值

5、gzip_buffers number size
支持实现压缩功能时为其配置的缓冲区数量及每个缓存区的大小

6、gzip_proxied off | expired | no-cache | no-store | private | no_last_modified | no_etag | auth | any …
nginx作为代理服务器接收到从被代理服务器发送的响应报文后,以何种条件下启用压缩功能。

  • off:对代理的请求不启用
  • no-cache, no-store,private:表示从被代理服务器(后端真正的服务器)收到的响应报文首部的Cache-Control的值为此三者中任何一个,则启用压缩功能

7、gzip_types mime-type ….
压缩过滤器,仅对此处设定的MIME类型的内容启用压缩功能,查看mime-type:/etc/nginx/mime.types
示例:

 1 server {
  2     listen 80;
  3     server_name www2.ydong.com;
  4     root /data/;
  5     gzip on;
  6     gzip_comp_level 5;
  7     gzip_proxied any;
  8     gzip_types  image/gif image/jpeg text/css text/xml;
  9     gzip_min_length 60;
      }

在这里插入图片描述

ngx_http_ssl_module

1、ssl on | off
是否启动ssl功能,在listen段用了ssl。就无需再显式指明这一项。
2、ssl_certificate file
当前虚拟机上使用PEM格式的证书文件
3、ssl_certificate_key file
当前虚拟机上与其证书匹配的私钥文件
4、ssl_protocols [SSLv2] [SSLv3] [TLSv1] [TLSv1.1] [TLSv1.2]
支持的协议版本
5、ssl_session_cache off | none | [builtin[:size]] [shared:name:size]

  • [builtin[:size]]:使用openssl内建的缓存,此缓存为每worker进程私有
  • [shared:name:size]:在各个worker之间共享的缓存。

6、ssl_session_timeout time
客户端一侧的连接可以复用ssl session cache中缓存的ssl参数的有效时长
示例:
ydong1主机为自建CA证书, ydong2为nginx服务机

[root@ydong1 CA]# (umask 077; openssl genrsa -out private/cakey.pem 2048)
Generating RSA private key, 2048 bit long modulus
....................+++
................+++
e is 65537 (0x10001)
[root@ydong1 CA]# openssl req -new -x509 -key private/cakey.pem  -out cacert.pem -days 365
[root@ydong1 CA]# mkdir index.txt
[root@ydong1 CA]# echo 01 > serial
#上边为构建CA

[root@ydong2 ssl]# (umask 077; openssl genrsa -out nginx_ssl.key 2048)
Generating RSA private key, 2048 bit long modulus
....+++
.........+++
e is 65537 (0x10001)
[root@ydong2 ssl]# openssl req -new -key nginx_ssl.key -out ngx_ssl.csr -days 365
#ydong2创建签署证书请求

[root@ydong1 CA]# openssl ca -in /tmp/ngx_ssl.csr -out certs/ngx_ssl.crt -days 365
#ydong1签署请求。
将签好的证书以及CA自己的证书一并发过去。

主机设置
server {
	listen 443 ssl;    #注意,要使用ssl功能,一定要在监听的端口后面写上ssl
	server_name www2.ydong.com;
	root /data/;
	ssl on;
	ssl_certificate /etc/nginx/ssl/ngx_ssl.crt;
	ssl_certificate_key /etc/nginx/ssl/nginx_ssl.key;
	ssl_session_timeout 20m;
}

在这里插入图片描述
在这里插入图片描述

多个ssl虚拟主机实现
1)首先未站点a.com, b.com创建自签证书。

[root@www certs]# pwd
/etc/pki/tls/certs

[root@www certs]# ll
总用量 28
-rw-------  1 root root 1310 4月  16 15:42 a.com.crt
-rw-------  1 root root 1679 4月  16 15:42 a.com.key
-rw-------  1 root root 1310 4月  16 15:43 b.crt
-rw-------  1 root root 1679 4月  16 15:43 b.key

2)将它们放置在/etc/nignx/conf.d目录下。

[root@www certs]# mv a.com.* b.* /etc/nginx/conf.d/

3)为站点提供配置文件

[root@www conf.d]# cat a.com.conf
server{
	listen 443 ssl;
	server_name www.a.com;
	root /data/a;
	ssl_certificate /etc/nginx/conf.d/a.com.crt;
	ssl_certificate_key /etc/nginx/conf.d/a.com.key;
	ssl_session_timeout 10m;
	ssl_session_cache shared:sslshare:20m;
}

[root@www conf.d]# cat b.com.conf
server{
	listen 443 ssl;
	server_name www.b.com;
	root /data/b;
	ssl_certificate /etc/nginx/conf.d/b.crt;
	ssl_certificate_key /etc/nginx/conf.d/b.key;
	ssl_session_timeout 10m;
	ssl_session_cache shared:sslshare:20m;
}



4)测试

[root@localhost ~]# curl -k https://www.a.com
a.com
[root@localhost ~]# curl -k https://www.b.com
b.com

ngx_http_rewrite_module

将用户请求的URI基于regex所描述的模式进行检查,而后完成替换。
rewrite模块可以理解为httpd的重定向。
rewrite工作机制:

  • 客户端发送请求时,服务端发现请求的页面为已经改变网址的页面,然后向客户端发送响应报文,带有location的首部报文,客户端根据location的指向重新访问。
  • rewrite可以有多个,但是有隐藏的循环机制,它由上而下进行匹配,假如说总共有三条rewrite,请求进来后,发现第一条匹配,所以转换成了第一条的内容,然后走着发现第三条匹配,于是又转换成了第三条。但是它匹配完第三条之后,会自上而下再次进行匹配,直到最后谁也匹配不到为止。简而言之:就是匹配到一条,就自上而下重新匹配一遍。

1、rewrite regex replacement [flag]

  • regex:查找的内容
  • replacement:替换的内容,不支持正则表达式

示例:

[root@www conf.d]# cat a.com.conf 
server{
	listen 80 default_server;
	server_name www.a.com;
	root /data/a;
	location /bbs {
		rewrite ^/bbs/(.*)$ /blog/$1;
	}
}

#访问bbs下内容时直接转换成blog下的资源

[flag]:

  • last:重写完成之后停止对当前URI在当前location中后续的其他重写操作,而后对新的URI启动新一轮重写检查,提前重启新一轮循环
  • break:重写完成后停止对当前URI在当前location中后续的其他操作,而后直接跳转至重写配置之后的配置。结束循环。
  • redirect:重写完成后以临时重定向方式直接返回重写后生成的新URI给客户端,由客户端重新发起请求;不能以http或https开头。
  • permanent:重写完成后以永久重定向方式直接返回重写后生成的新URI给客户端,由客户端重新发起请求。
  • 上诉所有操作全由nginx内部自己完成,无需客户端参与。
  • 注意:如果替换的字符串是以http,https开头的,直接将重定向返回给客户端。

示例:

[root@ydong2 nginx]# ls
admin  error_page  fish.jpg  flower.jpg  index.html  pictures
#nginx的根目录下并没有.png文件。

 [root@ydong2 pictures]# cat /etc/nginx/conf.d/www1.conf
server {
	listen 80;
	server_name www2.ydong.com;
	root /data/;
	location / {
		rewrite /(.*).png$ /$1.jpg;    #访问的png图片全部重定向至.jpg
	}
}


在这里插入图片描述
对flag进行测试
last

[root@www conf.d]# cat a.com.conf 
server{
	listen 80 default_server;
	server_name www.a.com;
	root /data/a;
	location / {
		rewrite /(.*).html /$1.txt last;
		rewrite /(.*).txt /$1.html;
	}
}

[root@localhost ~]# curl -IL http://www.a.com/1.txt
HTTP/1.1 500 Internal Server Error
Server: nginx
Date: Thu, 16 Apr 2020 08:15:58 GMT
Content-Type: text/html
Content-Length: 170
Connection: close
# 造成死循环,导致内部出错
[root@www conf.d]# cat a.com.conf 
server{
	listen 80 default_server;
	server_name www.a.com;
	root /data/a;
	location / {
		rewrite /(.*).html /$1.txt break;
		rewrite /(.*).txt /$1.html;
	}
}


[root@localhost ~]# curl  http://www.a.com/1.html
1.txt
[root@localhost ~]# curl  http://www.a.com/2.html
2.txt
[root@localhost ~]# curl  http://www.a.com/2.txt
2.txt
# break,直接停止处理,以第三个为例,首先2.txt转换成2.html,然后从第一行将2.html转换成2.txt。然后break终止替换
[root@www conf.d]# cat a.com.conf 
server{
	listen 80 default_server;
	server_name www.a.com;
	root /data/a;
	location / {
		rewrite /(.*).html /$1.txt redirect;
		rewrite /(.*).txt /$1.html;
	}
}

[root@localhost ~]# curl  -IL http://www.a.com/1.txt
curl: (47) Maximum (50) redirects followed

# 死循环,导致curl命令退出。  permanent和redirect一样、

2、return
return code [text] | return code URL| return URL
停止处理并将指定的内容返回code给客户端

3、rewrite_log on | off
是否开启重写日志。

4、 if (condition) { … }
引入一个新的配置上下文 ;条件满足时,执行配置块中的配置指令

操作比较符解释
== 和!=运算比较符
~模式匹配,区分字符大小写
~*模式匹配,不区分字符大小写
!~模式不匹配,区分字符大小写
!~*模式不匹配,不区分字符大小写
-f、!-f检查文件是否存在
-d、!-d检查文件是否是目录
-e、!-e检查文件,目录或符号链接是否存在
-x、!-x检查文件是否为执行文件

将http跳转到https上。

[root@www conf.d]# cat a.com.conf 
server{
	listen 80 default_server;
	server_name www.a.com;
	root /data/a;
	location / {
		rewrite /(.*) https://www.a.com/$1 redirect;
	}
}

server{
	listen 443 ssl;
	server_name www.a.com;
	root /data/a;
	ssl_certificate /etc/nginx/conf.d/a.com.crt;
	ssl_certificate_key /etc/nginx/conf.d/a.com.key;
	ssl_session_timeout 10m;
	ssl_session_cache shared:sslshare:20m;
}


但是如果将https和http写在同一个server中,需要增加if条件

[root@www conf.d]# cat a.com.conf 
server{
	listen 80 default_server;
	listen 443 ssl;
	server_name www.a.com;
	root /data/a;
	ssl_certificate /etc/nginx/conf.d/a.com.crt;
	ssl_certificate_key /etc/nginx/conf.d/a.com.key;
	ssl_session_timeout 10m;
	ssl_session_cache shared:sslshare:20m;
	location / {
		rewrite /(.*) https://www.a.com/$1 redirect;
	}
}
#这样会导致死循环。



[root@www conf.d]# cat a.com.conf 
server{
	listen 80 default_server;
	listen 443 ssl;
	server_name www.a.com;
	root /data/a;
	ssl_certificate /etc/nginx/conf.d/a.com.crt;
	ssl_certificate_key /etc/nginx/conf.d/a.com.key;
	ssl_session_timeout 10m;
	ssl_session_cache shared:sslshare:20m;
	location / {
		if ( $scheme = http ) {
			rewrite /(.*) https://www.a.com/$1 redirect;
		}
	}
}

[root@localhost ~]# curl -kL http://www.a.com
a.com


ngx_http_referer_module

用于阻止对“Referer”头字段中具有无效值的请求访问站点。对于Referer来说,它是非常容易伪造的。所以该模块可以用于阻止大部分的非法请求。

1、valid_referers none | blocked | server_names | string …

名词 解释
none请求报文首部没有referer首部
block请求报文中的referer没有值
server_name可以有值作为主机或者主机名模式。

其中server_name有两种特别方式:

  • *:用来表示通配符。
  • ~:使用正则表达式,必须要写在需要正则表达式字符串的开头。例如 ~*..magedu.com

Referer主要用来表明是用户从哪个网站跳转过来的,当用户直接在地址栏里输入某网站的IP,它当前的主页是没有Referer首部的。就是上边none的意思。如果用户从一个网页跳转到别的网页之后,Referer后边没有值,那就无法判定用户是否从合法网页过来,所以都允许它们访问。也就是block。该指令被用作防盗链功能。
示例:

server {
	listen 80;
	server_name www2.ydong.com;
	root /data/;
	valid_referers none blocked server_names ~\.baidu\. *.magedu.com ~\.google\. ;
	if ($invalid_referer){
		return 403;
	}    #含有baiud和googlle的域名,以及magedu.com的网址可以跳转至本网站,别的不可以。
	location / {
		#rewrite /(.*)\.png$ http://www2.ydong.com/$1.jpg break;
		rewrite /(.*).png$ /$1.jpg;
		rewrite /(.*)$ https://www2.ydong.com/$1;
		
	}
	
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值