Nginx 采用的是多进程(单线程) & 多路IO复用模型,使用了 I/O 多路复用技术的 Nginx,就成了”并发事件驱动“的服务器,同时使用sendfile等技术,最终实现了高性能。主要从以下几个方面讲述Nginx高性能机制:
- Nginx master-worker进程机制。
- IO多路复用机制。
- Accept锁及REUSEPORT机制。
- sendfile零拷贝机制
1、Nginx进程机制
1.1、Nginx进程机制概述
许多web服务器和应用服务器使用简单的线程的(threaded)、或基于流程的(process-based)架构, NGINX则以一种复杂的事件驱动(event-driven)的架构脱颖而出,这种架构能支持现代硬件上成千上万的并发连接。
NGINX有一个主进程(master process)(执行特定权限的操作,如读取配置、绑定端口)和一系列工作进程(worker process)和辅助进程(helper process)。如下图所示:
如下所示:
# service nginx restart
* Restarting nginx
# ps -ef --forest | grep nginx
root 32475 1 0 13:36 ? 00:00:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
nginx 32476 32475 0 13:36 ? 00:00:00 _ nginx: worker process
nginx 32477 32475 0 13:36 ? 00:00:00 _ nginx: worker process
nginx 32479 32475 0 13:36 ? 00:00:00 _ nginx: worker process
nginx 32480 32475 0 13:36 ? 00:00:00 _ nginx: worker process
nginx 32481 32475 0 13:36 ? 00:00:00 _ nginx: cache manager process
nginx 32482 32475 0 13:36 ? 00:00:00 _ nginx: cache loader process
如上4核服务器所示,NGINX主进程创建了4个工作进程和2个缓存辅助进程(cachehelper processes)来管理磁盘内容缓存(on-disk content cache)。如果我们不配置缓存,那么就只会有master、worker两个进程,worker进程的数量,通过配置文件worker_process进行配置(一般worker_process数与服务器CPU核心数一致),如下所示:
$ cat nginx.conf|grep process
worker_processes 3;
$ ps -ef|grep nginx
501 33758 1 0 四03上午 ?? 0:00.02 nginx: master process ./bin/nginx
501 56609 33758 0 11:58下午 ?? 0:00.00 nginx: worker process
501 56610 33758 0 11:58下午 ?? 0:00.00 nginx: worker process
501 56611 33758 0 11:58下午 ?? 0:00.00 nginx: worker process
NGINX根据可用的硬件资源,使用一个可预见式的(predictable)进程模型:
- Master主进程执行特权操作,如读取配置和绑定端口,还负责创建少量的子进程(以下三种进程)。
- Cache Loader缓存加载进程在启动时运行,把基于磁盘的缓存(disk-based cache)加载到内存中,然后退出。缓存加载进程的调度很谨慎,所以其资源需求很低。
- Cache Manager缓存管理进程周期性运行,并削减磁盘缓存(prunes entries from the disk caches)来使缓存保持在配置的大小范围内。
- Worker工作进程才是执行所有实际任务的进程:处理网络连接、读取和写入内容到磁盘,与upstream服务器通信等。
多数情况下,NGINX建议每1个CPU核心都运行1个工作进程,使硬件资源得到最有效的利用。你可以在配置中设置如下指令:
worker_processes auto;
当NGINX服务器运行时,只有Worker工作进程在忙碌。每个工作进程都以非阻塞的方式处理多个连接,以减少上下文切换的开销。 每个工作进程都是单线程且独立运行的,抓取并处理新的连接。进程间通过共享内存的方式,来共享缓存数据、持久性会话数据(session persistence data)和其他共享资源。
1.2、Master进程
nginx启动后,系统中会以daemon的方式在后台运行,后台进程包含一个master进程和多个worker进程。当然nginx也是支持多线程的方式的,只是我们主流的方式还是多进程的方式,也是nginx的默认方式。我们可以手动地关掉后台模式,让nginx在前台运行,并且通过配置让nginx取消master进程,从而可以使nginx以单进程方式运行。生产环境下肯定不会这么做,所以关闭后台模式,一般是用来调试用的。
master进程主要用来管理worker进程,包含:接收来自外界的信号,向各worker进程发送信号,监控worker进程的运行状态,当worker进程退出后(异常情况下),会自动重新启动新的worker进程。
1.3、Worker进程
每一个Worker工作进程都是使用NGINX配置文件初始化的,并且主节点会为其提供一套监听套接字(listen sockets)。 worker进程之间是平等的,每个进程,处理请求的机会也是一样的。当我们提供80端口的http服务时,一个连接请求过来,每个进程都有可能处理这个连接,怎么做到的呢?首先,每个worker进程都是从master进程fork过来,在master进程里面,先建立好需要listen的socket(listenfd)之后,然后再fork出多个worker进程。
所有worker进程的listenfd会在新连接到来时变得可读,为保证只有一个进程处理该连接,所有worker进程在注册listenfd读事件前抢accept_mutex,抢到互斥锁的那个进程注册listenfd读事件,在读事件里调用accept接受该连接。当一个worker进程在accept这个连接之后,就开始读取请求,解析请求,处理请求,产生数据后,再返回给客户端,最后才断开连接,这样一个完整的请求就是这样的了。所以Worker工作进程通过等待在监听套接字上的事件(accept_mutex和kernel socketsharding)开始工作。事件是由新的incoming connections初始化的。这些连接被会分配给状态机(statemachine)—— HTTP状态机是最常用的,但NGINX还为流(原生TCP)和大量的邮件协议(SMTP,IMAP和POP3)实现了状态机。
状态机本质上是一组告知NGINX如何处理请求的指令。大多数和NGINX具有相同功能的web服务器也使用类似的状态机——只是实现不同。如下图所示,就是一个HTTP请求的生命周期&#x