NGINX 采用 master-workers工作机制:
一个master和多个worker的有点:
1、可以使用 nginx -s reload 热部署
2、每个worker 是独立的进程,如果有其中一个worker出现问题,其他worker是独立的,可以继续进行争抢,实现请求过程,不会造成服务中断。
对于每个worker进程来书,是独立的进程,不需要加锁,省掉了加锁带来的开销。
同时在编程以及问题查找时,也会方便很多。其次,采用独立进程,进程之间不会互相影响
,一个进程因异常退出后,不会影响其他进程工作,服务不会中断。
NGINX 同 Redis类似都采用了io多路复用机制,每个worker都是一个独立进程,但每个进程里
只有一个主线程,通过异步非阻塞的方式处理请求。即使上千万个请求也不在话下,每个worker的
线程可以吧一个cup的性能发挥到机制,所有worker数量和服务器的cpu数量相等为宜,少了浪费cpu
,多了会造成cpu频繁切换上下文带来损耗。
worker_processes:4 worker数量为4
worker_connections : 1024 worker连接数
一个 NGINX 能建立的最大连接数是 worker_connections * worker_processes
能够支持的醉倒并发数量是:如果是支持http的浏览器每次访问腰斩两个连接,对于普通的静态访问
最大的并发数为 worker_connections * worker_processes/2, 如果是HTTP作为反向代理来说 ,最大并发数为
worker_connections * worker_processes/4,因为作为反向代理服务器,没噶并发会建立与客户端的连接和
后端服务的连接,各占用两个connection。
以下内容 转自:https://blog.51cto.com/13363488/2349542
在工作方式上,Nginx分为单工作进程和多工作进程两种模式。
在单工作进程模式下,除主进程外,还有一个工作进程,工作进程是单线程的;
在多工作进程模式下,每个工作进程包含多个线程。Nginx默认为单工作进程模式。
Nginx在启动后,会有一个master进程和多个worker进程。
master进程
主要用来管理worker进程,包含:接收来自外界的信号,向各worker进程发送信号,监控worker进程的运行状态,当worker进程退出后(异常情况下),会自动重新启动新的worker进程。
master进程充当整个进程组与用户的交互接口,同时对进程进行监护。它不需要处理网络事件,不负责业务的执行,只会通过管理worker进程来实现重启服务、平滑升级、更换日志文件、配置文件实时生效等功能。
我们要控制nginx,只需要通过kill向master进程发送信号就行了。比如kill -HUP pid,则是告诉nginx,从容地重启nginx,我们一般用这个信号来重启nginx,或重新加载配置,因为是从容地重启,因此服务是不中断的。master进程在接收到HUP信号后是怎么做的呢?
首先master进程在接到信号后,会先重新加载配置文件,然后再启动新的worker进程,并向所有老的worker进程发送信号,告诉他们可以光荣退休了。
新的worker在启动后,就开始接收新的请求,而老的worker在收到来自master的信号后,就不再接收新的请求,并且在当前进程中的所有未处理完的请求处理完成后,再退出。
当然,直接给master进程发送信号,这是比较老的操作方式,nginx在0.8版本之后,引入了一系列命令行参数,来方便我们管理。比如,./nginx -s reload,就是来重启nginx,./nginx -s stop,就是来停止nginx的运行。如何做到的呢?我们还是拿reload来说,我们看到,执行命令时,我们是启动一个新的nginx进程,而新的nginx进程在解析到reload参数后,就知道我们的目的是控制nginx来重新加载配置文件了,它会向master进程发送信号,然后接下来的动作,就和我们直接向master进程发送信号一样了。
worker进程:
而基本的网络事件,则是放在worker进程中来处理了。多个worker进程之间是对等的,他们同等竞争来自客户端的请求,各进程互相之间是独立的。一个请求,只可能在一个worker进程中处理,一个worker进程,不可能处理其它进程的请求。worker进程的个数是可以设置的,一般我们会设置与机器cpu核数一致,这里面的原因与nginx的进程模型以及事件处理模型是分不开的。
worker进程之间是平等的,每个进程,处理请求的机会也是一样的。当我们提供80端口的http服务时,一个连接请求过来,每个进程都有可能处理这个连接,怎么做到的呢?
首先,每个worker进程都是从master进程fork过来,在master进程里面,先建立好需要listen的socket(listenfd)之后,然后再fork出多个worker进程。所有worker进程的listenfd会在新连接到来时变得可读,为保证只有一个进程处理该连接,所有worker进程在注册listenfd读事件前抢accept_mutex,抢到互斥锁的那个进程注册listenfd读事件,在读事件里调用accept接受该连接。