nginx是以多进程的方式来工作的。
nginx在启动后,会有一个master进程和多个worker进程。

  



master进程主要用来管理worker进程:
包含:
1、接收来自外界的信号,向各worker进程发送信号。
2、监控worker进程的运行状态,当worker进程退出后(异常情况下),会自动重新启动新的worker进程。


而基本的网络事件,则是放在worker进程中来处理了。worker进程之间是对等的,一个请求,只可能在一个worker进程中处理,一个worker进程,不可能处理其它进程的请求。
worker进程的个数,一般会设置与机器cpu核数一致。当我们提供80端口的http服务时,一个连接请求过来,每个进程都有可能处理这个连接。


处理过程如下:
master(master进程会先建立好需要listen的socket)--------fork生成子进程workers,继承socket(此时workers子进程们都继承了父进程master的所有属性,当然也包括已经
建立好的socket,当然不是同一个socket,只是每个进程的这个socket会监控在同一个ip地址与端口,这个在网络协议里面是允许的)------当一个连接进入,产生惊群现象。
一般来说,当一个连接进来后,所有在accept在这个socket上面的进程,都会收到通知,而只有一个进程可以accept这个连接,其它的则accept失败。




惊群现象:指一个fd的事件被触发后,等候这个fd的所有线程/进程都被唤醒。虽然都被唤醒,但是只有一个会去响应。最常见的例子就是对于socket的accept操作,当多个
用户进程/线程监听在同一个端口上时,由于实际只可能accept一次,因此就会产生惊群现象,


Nginx对惊群现象的处理:
     nginx提供了一个accept_mutex这个东西,这是一个加在accept上的一把共享锁。有了这把锁之后,同一时刻,就只会有一个进程在accpet连接,这样
就不会有惊群问题了。accept_mutex是一个可控选项,我们可以显示地关掉,默认是打开的。




worker进程工作:

     当一个worker进程在accept这个连接之后,就开始读取请求,解析请求,处理请求,产生数据后,再返回给客户端,最后才断开连接,一个完整的请求。一个请求,完全由
worker进程来处理,而且只在一个worker进程中处理。


小结:
1)一个完整的请求读取请求、解析请求、处理请求,产生数据后,再返回给客户端,最后断开连接。
2)一个完整的请求完全由一个worker进程处理。


好处:
     1)节省锁带来的开销。每个worker进程都是独立的进程,不共享资源,不需要加锁。同时在编程以及问题查上时,也会方便很多。
     2)独立进程,减少风险。采用独立的进程,可以让互相之间不会影响,一个进程退出后,其它进程还在工作,服务不会中断,master进程则很快重新启动新的worker进程。当然,worker进程的异常退出,肯定是程序有bug了,异常退出,会导致当前worker上的所有请求失败,不过不会影响到所有请求,所以降低了风险。


Nginx的事件处理机制


       对于一个基本的web服务器来说,事件通常有三种类型:网络事件、信号、定时器。Nginx采用异步非阻塞的事件处理机制,由进程循环处理多个准备好的事件,从而实现

高并发和轻量级。


        以epoll为例:当事件没有准备好时,就放入epoll里面。如果有事件准备好了,那么就去处理;如果事件返回的是EAGAIN,那么继续将其放入epoll里面。从而,只要有事件准备好了,我们就去处理她,只有当所有时间都没有准备好时,才在epoll里面等着。这样,我们就可以并发处理大量的并发了,当然,这里的并发请求,是指未处理完的请求,线程只有一个,所以同时能处理的请求当然只有一个了,只是在请求间进行不断地切换而已,切换也是因为异步事件未准备好,而主动让出的。这里的切换是没有任何代价,你可以理解为循环处理多个准备好的事件,事实上就是这样的。




问题1: Nginx采用worker进程来处理请求,一个worker进程只有一个主线程,那么有多少个worker子进程就能处理多少个并发,那么能够处理的并发数有限。概括的讲,Nginx如何实现高并发?
        回答1:采用异步非阻塞的事件处理机制。之所以能够并发处理大量的未处理完的请求,是通过异步非阻塞方式,由进程循环处理多个准备好的事件。以epoll为例,为准备好的事件都会放入epoll中,只要有事件准备好,就会进行处理。                   


问题2:何为异步非阻塞方式
        回答2:http://www.ibm.com/developerworks/cn/linux/l-async/



问题3:Nginx与Apache对于高并发处理上的区别。
        回答3:对于Apache,每个请求都会独占一个工作线程,当并发数到达几千时,就同时有几千的线程在处理请求了。这对于操作系统来说,占用的内存非常大,线程的上下文切换带来的cpu开销也很大,性能就难以上去,同时这些开销是完全没有意义的。

     对于Nginx来讲,一个进程只有一个主线程,通过异步非阻塞的事件处理机制,实现了循环处理多个准备好的事件,从而实现轻量级和高并发。



问题4:为何推荐worker的个数为cpu的个数?
        回答4:因为更多的worker数,只会导致进程相互竞争cpu资源,从而带来不必要的上下文切换




nginx 配置高并发
一、一般来说nginx 配置文件中对优化比较有作用的为以下几项:
1. worker_processes 8;
nginx 进程数,建议按照cpu 数目来指定,一般为它的倍数 (如,2个四核的cpu计为8)。
2. worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;
为每个进程分配cpu,上例中将8 个进程分配到8 个cpu,当然可以写多个,或者将一
个进程分配到多个cpu。
3. worker_rlimit_nofile 65535;
这个指令是指当一个nginx 进程打开的最多文件描述符数目,理论值应该是最多打开文
件数(ulimit -n)与nginx 进程数相除,但是nginx 分配请求并不是那么均匀,所以最好与ulimit -n 的值保持一致。  

0 评论  
添加一条新评论