1。Nginx的进程模型 前面介绍Nginx时有介绍过Nginx的进程模型。Nginx启动时首先启动一个Master进程,然后由Master进程启动一个或者多个Worker子进程。Master进程主要完成配置读取,通过发送信号控制Worker进程的启动和停止等,而Worker子进程是用来处理客户端发来的Http请求,且Worker进程之间会通过共享内存进行通信。1。1worker进程处理请求过程 假设Nginx启动了多个Worker进程,并且在Master进程中通过socket套接字监听80端口。这些Worker进程fork自Master进程,然后每个worker进程都可以去accept这个监听的socket。当一个连接进来后,所有在accept在这个socket上面的进程,都会收到消息,但是只有一个进程可以accept这个连接,其它的则accept失败,这便是所谓的惊群现象。Nginx处理这种情况的方式就是加锁。有了锁之后,在同一时刻,就只会有一个Worker进程在accpet连接,这样就不会有惊群问题了。在Worker进程拿到Http请求后,就开始按照前面介绍的11个阶段处理该Http请求,最后返回响应结果并断开连接。1。2Nginx命令行的处理流程 最早我们学习了Nginx命令行操作,这些命令行操作都是给Master进程发信号,然后再由Master进程发送信号给Worker进程,从而达到控制Worker进程的目标。我们以Nginx的热部署命令。nginxsreload来描述Nginx命令行的执行流程。具体过程如下:首先Master进程会检查nginx。conf文件是否存在语法错误,并从中找到nginx。pid配置路径(没有配置会使用默认值)reload参数表示向Master进程发送HUP信号。Nginx会根据会保存在nginx。pid文件中的值找到Master进程的pid。如果Nginx进程没有启动,则没有该nginx。pid文件,命令行会报错;在Nginx的配置文件中配置nginx。pid的保存路径〔rootserversbin〕。nginxsreloadnginx:〔error〕open()rootnginxlogsnginx。pidfailed(2:Nosuchfileordirectory)Master进程打开新的监听端口;Master进程用新配置启动新的Worker进程。新的Worker进程起来后,开始接收Http请求并处理,此时老的Worker进程会停止接受Http请求;Master进程会向老的Worker进程发送QUIT信号;老的Worker进程关闭监听句柄,处理完正在进行的请求后结束进程。 Nginx命令行中s参数的每个值都对应这一个信号。因此,我们也可以直接对Master进程发生相应信号达到同样的目的。pid表示Nginx的主进程id号kills信号pid2。Nginx的事件驱动模型2。1事件驱动模型 事件驱动模型是实现异步非阻塞的一个手段。对于web服务器来说,客户端A的请求连接到服务端时,服务端的某个进程(Nginx的worker进程)会处理该请求,此进程在没有返回给客户端A结果时,它又去处理了客户端B的请求。服务端把客户端A以及客户端B发来的请求作为事件交给了事件收集器,而事件收集器再把收集到的事件交由事件发送器发送给事件处理器进行处理。最后事件处理器处理完该事件后,通知服务端进程,服务端进程再把结果返回给客户端A、客户端B。在这个过程中,服务端进程做的事情属于用户级别的,而事件处理这部分工作属于内核级别的。也就是说这个事件驱动模型是需要操作系统内核来作为支撑的。2。2Nginx的事件驱动模型介绍 Nginx的事件驱动模型,支持select、poll、epoll、rtsig、kqueue、devpoll、eventport等。最常用的是前三种,特别是epoll模型,这也是Nginx中的默认配置。可以说epoll模型成就了Nginx的高性能和高并发特性。select模型:创建所关注事件的描述符集合,对于一个描述符,可以关注其上面的读(Read)事件、写(Write)事件以及异常发生(Exception)事件。在select模型中,要创建这3类事件描述符集合。调用底层提供的select()函数,等待事件发生。轮询所有事件描述符集合中的每一个事件描述符,检查是否有相应的事件发生,如果有就进行处理。poll模型:poll模型是Linux平台上的事件驱动模型,在Linux2。1。23中引入的,Windows平台不支持该模型。poll模型和select模型工作方式基本相同,区别在于,select模型创建了3个描述符集合,而poll模型只创建一个描述符集合。epoll模型:epoll模型属于poll模型的变种,在Linux2。5。44中引入。epoll比poll更加高效,原因在于它不需要轮询整个描述符集合,而是Linux内核会关注事件集合,当有变动时,内核会发来通知。正式这种异步,非阻塞、IO多路复用的事件驱动模型,才使得Nginx有很高的运行效率。3。案例3。1Nginx进程模型实验 按照前面的讲解,我们测试给Nginx的Master进程直接发送信号,并观察进程情况:确认没有Nginx进程〔rootserversbin〕psefgrepnginxroot1060310137014:23pts200:00:00grepcolorautonginx启动Nginx〔rootserversbin〕。nginx可以看到Nginx启动的进程〔rootserversbin〕psefgrepnginxroot106401014:23?00:00:00nginx:masterprocess。nginxroot1064210640014:23?00:00:00nginx:workerprocessroot1064310640014:23?00:00:00nginx:workerprocessroot1064410640014:23?00:00:00nginx:cachemanagerprocessroot1064510640014:23?00:00:00nginx:cacheloaderprocess 可以看到Nginx启动了Master进程(pid10640),后由Master进程fork除了两个Worker进程和两个Cache进程,他们的父进程id均为10640。现在做如下几个操作:关闭进程号等于10642的Worker进程〔rootserversbin〕sudokillSIGTERM10642〔rootserversbin〕psefgrepnginxroot106401014:23?00:00:00nginx:masterprocess。nginxroot1064310640014:23?00:00:00nginx:workerprocessroot1064410640014:23?00:00:00nginx:cachemanagerprocessroot1086910640014:32?00:00:00nginx:workerprocessroot1093910137014:32pts200:00:00grepcolorautonginx 可以看到原先的Worker进程被杀死后,Nginx的主进程又立马拉起来一个新的Worker进程提供服务。这说明Nginx是非常可靠的,只要Master进程还在就会保证Worker进程持续存在并提供服务。向主进程发送SIGHUP信号,等价于sreload操作。可以看到除了Master进程外,所有其他进程已经是新启动的进程了。〔rootserversbin〕sudokillSIGHUP10640〔rootserversbin〕psefgrepnginxroot106401014:23?00:00:00nginx:masterprocess。nginxroot1105910640014:37?00:00:00nginx:workerprocessroot1106010640014:37?00:00:00nginx:workerprocessroot1106110640014:37?00:00:00nginx:cachemanagerprocessroot1109810137014:37pts200:00:00grepcolorautonginx向主进程发生SIGTERM信号,等价于sstop操作,即停止Nginx服务,关闭所有进程〔rootserversbin〕sudokillSIGTERM10640〔rootserversbin〕psefgrepnginxroot1126710137014:43pts200:00:00grepcolorautonginx向主进程发生USR1信号,等价于srepoen操作,即重新打开日志文件〔rootserversbin〕。nginx〔rootserversbin〕psefgrepnginxroot114081014:48?00:00:00nginx:masterprocess。nginxroot1141011408014:48?00:00:00nginx:workerprocessroot1141111408014:48?00:00:00nginx:workerprocessroot1141211408014:48?00:00:00nginx:cachemanagerprocessroot1141311408014:48?00:00:00nginx:cacheloaderprocessroot1148410137014:49pts200:00:00grepcolorautonginx〔rootserversbin〕ll。。logsaccess。logrwrr1rootroot384349Feb1114:26。。logsaccess。log〔rootserversbin〕rmrf。。logsaccess。log〔rootserversbin〕ll。。logsaccess。logls:cannotaccess。。logsaccess。log:Nosuchfileordirectory〔rootserversbin〕killUSR111408〔rootserversbin〕ll。。logsaccess。logrwrr1rootroot0Feb1114:50。。logsaccess。log 可以看到,在移除Nginx的access。log日志后,在向Nginx主进程发送USR1信号,Nginx会重新生成一个新的access。log日志。4。小结 本节主要介绍Nginx的进程模型以及介绍了Master和Worker之间的通信过程。此外,我们介绍了Nginx的事件驱动模型。异步、多路IO复用、非阻塞等特点早就了Nginx的高性能。接下来,我们完成了Nginx进程模型的几个实验,直观体检Nginx的进程模型。下一节将重点介绍Nginx模块相关的内容,并手动实现一个简单的http模块。