文章目录
- [1. nginx的应用特点](#1. nginx的应用特点)
- [2. nginx多进程架构](#2. nginx多进程架构)
-
- [2.1 nginx多进程模型](#2.1 nginx多进程模型)
- [2.2 master进程的作用](#2.2 master进程的作用)
- [2.3 进程控制](#2.3 进程控制)
- [2.4 worker进程的作用](#2.4 worker进程的作用)
- [2.5 worker进程处理请求的过程](#2.5 worker进程处理请求的过程)
- [2.6 nginx处理网络事件](#2.6 nginx处理网络事件)
1. nginx的应用特点
Nginx是互联网企业使用最为广泛的轻量级高性能Web服务器,其特点是占用内存少、并发能力强。Nginx之所以被大家所喜爱,除了其高性能外,还有其优雅的系统架构。与Memcached的经典多线程模型相比,Nginx是经典的多进程模型。
在介绍Nginx应用特点前,首先介绍一下IO密集型和计算密集型:
- IO密集型就是指IO占主要任务,计算量很小,比如请求网页,读写文件。
- 计算密集型就是指CPU计算占主要任务,CPU一直处于满负荷状态,比如大循环计算。
而Nginx本质上是一个Web Server,Web Server的作用是解析HTTP请求返回静态数据或者把一些动态请求托付给其它server端程序。基于Nginx的这样的工作性质,决定每个request的大部份生命都是在网络传输中,实际上花费在server机器上的时间片不多。因此Nginx属于网络IO密集型应用,不算是计算密集型。基于这样的特点,才有可能实现多进程解决高并发的设计方案。
2. nginx多进程架构
2.1 nginx多进程模型
nginx的高性能与其架构是分不开的。
nginx采用的是经典的master-worker模型的多进程模型,即一个master进程管理一个或者多个worker进程。基本的事件处理都在worker进程,master进程负责一些全局初始化,以及对worker进程的管理,如下图所示:
nginx分为单进程模式和多进程模式,默认以多进程的方式来工作。
单进程模式常常在开发环境调试时候使用,在对外服务时nginx多以多进程方式工作。
Nginx启动后,会运行一个master进程和多个worker进程。其中master充当整个进程组与用户的交互接口,同时对进程进行监护,管理worker进程来实现重启服务、平滑升级、更换日志文件、配置文件实时生效等功能。worker用来处理基本的网络事件,worker之间是平等的,他们共同竞争来处理来自客户端的请求。
2.2 master进程的作用
master进程主要功能包括:
- 接收来自外界的信号。
- 向各worker进程发送信号。
- 监控worker进程的运行状态
- 当worker进程退出后(异常情况下),会自动重新启动新的worker进程。
2.3 进程控制
在启动后,我们应该如何操作nginx呢?
上面已经知道master进程可以用来管理worker进程,所以我们只需要与master进程通信就行了。master进程会接收来自外界发来的信号,再根据信号做不同的事情。所以我们要控制nginx,只需要向master进程发送信号就行了。
比如kill -HUP pid
,我们一般用这个信号来从容地重启nginx。master进程在接收到HUP
信号后,会先重新加载配置文件,然后再启动新的worker进程,并向所有老的worker进程发送信号,告诉他们可以光荣退休了。新的worker在启动后,就开始接收新的请求,而老的worker在收到来自master的信号后,就不再接收新的请求,并且在当前进程中的所有未处理完的请求处理完成后,再退出。
2.4 worker进程的作用
worker进程负责处理网络事件:
- 多个worker进程之间是对等的,他们同等竞争来自客户端的请求。
- 各进程互相之间是独立的。
- 一个请求,只可能在一个worker进程中处理,一个worker进程,不可能处理其它进程的请求。
- worker进程的个数是可以设置的,一般我们会设置与机器cpu核数一致。
2.5 worker进程处理请求的过程
worker进程之间是平等的,每个进程,处理请求的机会也是一样的。当我们提供80端口的http服务时,一个连接请求过来,每个进程都有可能处理这个连接,怎么做到的呢?
每个worker进程都是从master进程fork出来的,在master进程里面,首先会建立好监听的socket,然后再fork出多个worker进程。这样每个worker进程都可以去accept这个socket(当然不是同一个socket,只是每个进程的这个socket会监控在同一个ip地址与端口,这个在网络协议里面是允许的)。
一般来说,当一个连接进来后,所有accept在这个socket上面的进程,都会收到通知,但是只有一个进程可以accept这个连接,其它的则accept失败,这是所谓的惊群现象。
nginx提供了一个accept_mutex这个东西,从名字上,我们可以看这是一个加在accept上的一把共享锁。有了这把锁之后,同一时刻,就只会有一个进程在accpet连接,这样就不会有惊群问题了。accept_mutex是一个可控选项,我们可以显示地关掉,默认是打开的。当一个worker进程在accept这个连接之后,就开始读取请求,解析请求,处理请求,产生数据后,再返回给客户端,最后才断开连接,这样一个完整的请求就是这样的了。我们可以看到,一个请求,完全由worker进程来处理,而且只在一个worker进程中处理。
2.6 nginx处理网络事件
Nginx采用异步非阻塞的方式来处理网络事件,具体过程如下图:
![](https://i-blog.csdnimg.cn/direct/ace07e0ded864540888290f0094df6f2.png)
master进程先建好需要监听的socket后,再fork出多个worker进程,这样每个worker进程都可以去接收这个socket。当一个client连接到来时,所有的worker进程都会收到通知,但只有一个可以accept成功。这里Nginx提供了一个共享锁accept_mutex,虽然所有的worker都会收到通知,但只有一个进程抢到锁,其它失败,成功的worker进程接收请求。当一个worker进程在accept这个连接之后,就开始读取请求,解析请求,处理请求,产生数据后,再返回给客户端,最后才断开连接。
当运行过程中,如果worker进程出现异常,master会对worker进行重启。重启时会先启动新的worker进程,然后向老的worker发送信号。新的worker启动后,就开始接收新的请求;而老的worker在收到信号后不再接收请求,将当前进程中所有未处理完的请求处理完成后,再退出。这样最大程度的满足可用性要求。