进程模型
当nginx启动之后,会有一个master进程和多个worker进程。默认是一个worker进程。
master进程的作用:接收来自外界信号,向各worker进程发送信号,监控worker进程的运行状态,当worker进程在异常情况下退出后,会自动重新启动新的worker进程。
worker进程作用:处理基本的网络事件。
多个worker进程之间时对等的,他们同等竞争来自客户端的请求,各进程互相之间是独立的。一个请求只可能在一个worker进程中处理,不可能处理其它进程的请求。worker进程的个数是可以设置的,一般我们会设置与机器cpu核数一致,原因与nginx的进程模型以及事件处理模型是分不开的。
当有请求到来,master进程只是通知(发信号)每个worker进程有请求到来,然后worker进程去争抢请求。而不是从master进程获取请求。
设计优点
- 方便热部署(./nginx -s relaod)的实现
当master进程在收到信号后,会重新加载配置,启动新的worker,并向所有老的worker进程发送信号,不再接收新的请求,并且在老进程处理完所有未处理完的请求后,退出。
由于一个master进程和多个worker进程,可以实现不需要重启nginx的情况下,重新加载配置。 - 节省资源和健壮性好
由于每个worker进程是独立的,不需要像线程一样需要加锁,省掉了锁的开销。
并且每个worker之间不会影响,一个进程退出,其它进程还在工作,服务不会终端,并且master进程会启动新的worker进程。当然worker进程的异常退出会导致当前worker上的所有请求失败,不过不会影响所有的请求,所以减低了风险。
事件模型
nginx采用的epoll模型,异步非阻塞,IO多路复用机制。对于nginx来说,把一个完整的连接请求处理都划分成了一个事件。每部分都有相应的模块去处理,一个完整的请求可能由几百个模块去处理。
例如:一个worker一开始注册了一个accpet事件,当一个客户端请求连接时,连接事件变为可读,worker进程执行相应的模块,再注册监听连接事件,等待请求的到来。当有请求到来变为可读时,epoll模型就会通知worker进程执行相应的模块处理。处理完,再注册发送事件,当可以发送事件就绪时,再通知worker进程执行相应的模块。
真正核心的就是事件收集和分发模块,只有核心模块的调度才能让对应的模块占用CPU资源。拿一个http请求来说,首先事件收集分发模块注册感兴趣的监听事件,注册好之后不阻塞直接返回,当有连接来临时,内核会通知(epoll模型会通知进程),CPU就可以处理其它事情了。
为什么说worker进程的个数和机器cpu核数一致最好?
worker是一个单独的进程,里面只有一个主线程,通过异步非阻塞的方式来处理请求,即使千万个请求也可以处理,每一个worker线程可以把cpu的性能发挥到极致。所以worker数和服务器的cpu核数相等最为适宜。设少了会浪费CPU,设多了会导致CPU频繁切换上下文带来损耗。
连接数
- 客户端发送请求,占用了worker的几个连接数?
2个或者4个。
当访问的是静态资源时,worker进程接收请求一个连接,然后将静态资源返回一个连接,总共两个连接。
当访问的时动态资源时,worker进程接收请求一个连接,发送请求动态资源请求给动态资源服务器一个连接,再接收动态资源服务器响应一个连接,然后将动态资源返回一个连接,总共四个连接。 - 当nginx有一个master进程,四个worker进程,每个worker进程支持最大连接数为1024,worker支持最大并发数(请求数)为多少?
最大连接数为:4 * 1024
最大并发数为:4 * 1024 / 2(访问静态资源) 或 4 * 1024 / 4 (反向代理,访问动态资源)