并发处理机制
一般情况下并发处理机制有三种:多进程、多线程和异步机制,Nginx
对于并发的处理同时采用了这三种机制。当然,其异步机制使用的是异步非阻塞的方式。
我们知道Nginx
的进程分为两类:master
进程与worker
进程,每个master
进程可以生成多个worker
进程,所以其是多进程的。每个worker
进程可以同时处理多个用户请求,每个用户请求会由一个线程来处理,所以其是多线程的。
那么,如何解释异步机制?worker
进程采用的是epoll
多路复用机制来对后端服务器进行处理的。当后台服务器返回结果后,后端服务器就会回调epoll
多路复用器,由多路复用器对相应的worker
进行通知,此时worker
进程就会挂起当前正在处理的事务,拿IO
返回结果去相应客户端请求,响应完毕后,会继续执行挂起的事务,这个过程是异步非阻塞的。关于IO
多路复用可以参考IO多路复用这篇文章,讲得很详细。
全局模块调优
worker_processes
打开nginx.conf
配置文件,可以看到worker_processes
的默认值为1
,如下图所示
当我们把它改成2
,并运行时,查看运行的Nginx
运行的进程如下图所示
worker_processes
用于指定Nginx
的工作进程数量,其数值一般设置为CPU
内核数量,或者内核数量的整数倍。不过需要注意,该值不仅仅取决于CPU
内核数量,还与硬盘数量及负载均衡模式相关。在不确定时可以指定其值为auto
。
worker_cpu_affinity
将worker
进程与具体的哪个内核进行绑定,不过,若指定worker_processes
的值为auto
,则无法设置worker_cpu_affinity
。
该设置是通过二进制进行的,每个内核使用一个二进制位来表示,0
代表内核关闭,1
表示内核开启,也就是说,有几个内核,就需要使用几个二进制位。
worker_rlimit_nofile
worker_rlimit_nofile
用于设置一个worker
进程所能够打开的最多文件数量,其默认值与当前的Linux
系统可以打开的最大文件描述符数量相同。
我们可以通过命令ulimit -n
查看自己系统的可以打开的最大文件描述符数量,如下图所示
可以使用ulimit -n 65535
把能打开的文件描述数量改成65535
个(这只是临时修改,重启服务器后又会失效),想要永久修改打开的最大文件描述数量,修改/etc/security/limits.conf
文件,修改soft nofile 65535 hard nofile 65535
这两行。
events模块调优
worker_connection 1024
设置每一个worker
进程可以并发处理的最大连接数。该值不能超过worker_rlimit_nofile
的值。
accept_mutex
-
on
:默认值,表示一个新连接到达时,那些没有处于工作状态(阻塞状态)的worker
将以串行方式来处理这个连接。请求还没有过来时,最初的worker
进程的状态都是处于阻塞状态的,因为缺少相应的资源,如果accept_mutex
设置为on
,当连接请求过来时,那么把worker
进程从阻塞状态变成就绪状态的激活资源是互斥锁,只有一个worker
进程能够获得互斥锁进入就绪状态(一般都是阻塞队列头元素),分到了时间片就会进入运行状态。其他没有获得互斥锁的worker
进程还是处于阻塞状态。 -
off
:表示当一个新连接到达时,所有的worker
都会被唤醒,不过只有一个worker
能获得取新连接,其他的worker
会重新进入阻塞状态,这就是惊群
现像。请求还没有过来时,激活资源是新连接,请求过来时,所有的worker
都会变成就绪态,并且竞争连接资源,没有得到连接资源的worker
进程又会变成阻塞状态。
nginx
的作者对于惊群的解释:apache
服务器进程一般是成百上千的,一旦发生惊群,会对系统影响特别大,但是nginx
的工作进程最多是几十个,一个新连接来了之后,所有的进程的状态从阻塞状态变成就就绪状态,对系统的影响不大,实际工作中,
举个例子,比如1000
多的请求过来时,相当于一把米,如果accept_mutex
设置为on
的话,相当于每次取出worker
阻塞队列头元素,比于成一只鸡,每次都是取出一只鸡喂一粒米,这样会很慢;如果accept_mutex
设置为on
的话,因为所有阻塞的worker
都已经唤醒了,相当于直接将这把米一撒,所有的鸡都可以直接吃,这样效率肯定是高的。
所以,高并发情况下,一般设置成off
,并发量不大的系统设置成on
。
accept_mutex_delay
当上面的参数accept_mutex
设置成on
时,表示阻塞队列中队首的worker
尝试获取互斥锁的时间间隔,默认值为500
毫秒。即阻塞队列中队首的worker
每隔500
毫秒会查看是否有新连接过来,如果有的话就会尝试获取互斥锁。
multi_accept on
off
:系统会逐个拿出连接按照负载均衡策略,将其分配给当前处理连接数个数最少的worker
。on
:系统会实时的统计出各个worker
当前正在处理的连接个数,然后会按照缺编
最多的worker
,一次性将这么多的新连接分配给该worker
.
设置中的缺编
指的是因为一般一个worker
最大能处理的并发连接请求数量一般是1024
,如果当前worker
进程处理的连接数量越小,即1024-当前进程处理的连接数量=缺编数量
。设置成on
的话会将请求一次性给了缺编最大的worker
进程,这种方式处理比较快,而设置成off
的话会一个一个给当前处理连接数量最少的worker
进程,这种方式处理比较慢但是也不一定说multi_accept on
就比off
好,因为on
的话需要mater
实时计算所有worker
的缺编,也会占用很多的系统资源
use epoll
设置worker
与客户端连接的处理方式,Nginx
会自动选择适合当前系统的最高效的方式,当然,也可以使用use
指令明确指定所要使用的连接处理方式。use
的取值有这几种:select | poll | epoll | rtsig | kqueue | /dev/poll
select | poll | epoll
:这是三种多路复用机制,select
与poll
工作原理几乎相同,而epoll
效率最高,是现在使用最多的一种多路复用机制。rtsig
:realtime signal
,实时信号,Linux2.2.19+
的高效廉洁处理方式,但是在Linux2.6
版本后不再支持该方式。kqueue
:应用在BSD
系统上的epoll
。/dev/poll
:Unix
系统上使用的poll
.
http模块调优
非调优属性简介
include mime.type
:表示将/usr/local/nginx/conf/mime.type
文件包含进来,mime.type
文件指定文件类型,可以打开该文件看一下如下图所示
-
default_type application/octet-stream
:表示对于无扩展名的文件,默认其为application/octet-stream
类型,即Nginx
会将其作为一个八进制流文件来处理。 -
charset utf-8
:设置请求与响应的字符编码。
sendfile on
设置为on
表示开启Linux
系统的零拷贝机制,否则不启用零拷贝,当然开启后是否起作用,要看所使用的系统版本,CentOS6
及其以上版本支持sendfile
零拷贝。关于零拷贝可以参考:深入理解零拷贝这篇文章,讲得很详细。
tcp_nopush on
on
:以单独的数据包形式发送Nginx
的响应头信息,而真正的响应体数据会再以数据包的形式发送,这个数据包中就不再包含响应头信息了。off
:默认值,响应头信息包含在每一个响应体数据包中。
tcp_nodelay on
on
:不设置数据发送缓存,即不推迟发送,适合于传输小数据,无需缓存。off
:开启发送缓存。若传输的数据是图片等大数据量文件,则建议设置为off
。
keepalive_timeout 65
设置客户端与Nginx
间所建立的长连接的超时时间,时间到达,则连接将会自动关闭。单位为秒。
keepalive_requests 10000
设置一个长连接最多可以发送的的请求数。该值需要在真实环境下测试。
client_body_timeout 10
设置客户端获取Nginx
响应的超时时限,即一个请求从客户端发出到接收到Nginx
的响应的最长时间间隔,若超时,则认为本次请求失败。