文章目录
- Nginx进程模型解析
- Worker的抢占机制
- Nginx的事件处理机制
- 小结
Nginx进程模型解析
nginx包含了两种进程:
- worker进程:主进程
- master进程:工作进程
通过下面的命令可以看出:
[root@localhost html]# ps -ef|grep nginx
root 4443 1 0 07:10 ? 00:00:00 nginx: master process /usr/local/nginx/sbin/nginx
nobody 4444 4443 0 07:10 ? 00:00:00 nginx: worker process
root 4465 1495 0 07:15 pts/0 00:00:00 grep --color=auto nginx
在nginx.conf里面,第一行就能看到:
#user nobody;
worker_processes 1;
表明只是用1个worker进程,我们将进程数目改为2:
[root@localhost conf]# vi nginx.conf
[root@localhost conf]# nginxup -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@localhost conf]# nginxup -s reload
[root@localhost conf]# ps -ef|grep nginx
root 4443 1 0 07:10 ? 00:00:00 nginx: master process /usr/local/nginx/sbin/nginx
nobody 4481 4443 0 07:21 ? 00:00:00 nginx: worker process
nobody 4482 4443 0 07:21 ? 00:00:00 nginx: worker process
root 4484 1495 0 07:21 pts/0 00:00:00 grep --color=auto nginx
worker和master的关系在很多分布式集群关系中就有提到,主要是通过master来接收外界的信号,然后将任务分配给worker去做。比如接受一个nginxup -s reload
信号后,交给worker去重启。
Worker的抢占机制
首先在服务里面有个master的主进程来监听80端口,当nginx启动的时候,master会创建worker(fork),当有用户请求打入nginx的时候,worker怎么去和请求进行一个相应的连接呢?下图创建了3个worker,到底是哪个worker来处理呢?这里就需要提到抢占机制。
我们的客户端请求会有一个锁🔒,然后worker去抢占这个锁,当请求处理完成后返回客户端,才释放这个锁。
Nginx的事件处理机制
- 传统服务器
在了解了worker的抢占机制后,我们来查看一个传统服务器的事件处理。
如下图所示,传统服务器创建了woker1后,如果请求1产生了阻塞,其他请求就必须去等待woker1处理完第一个请求,这是同步阻塞的。
传统服务器为了解决这个问题,就fork出一个新的woker2进程:
如果连client2也阻塞了,就再创建一个woker3进程:
这样同步阻塞的处理方式性能会非常的低,假设并发达到了几十万后,会去开很多很多的进程去处理新的Client请求。如果产生了很多阻塞,那么对资源的开销是非常的大的。
- Nginx的事件处理
同样Nginx最初也遇到了阻塞的问题:
但是worker1处理方式是异步非阻塞的,当他发现请求1阻塞后,他会去处理请求2;当请求2阻塞后,又会去处理请求3。
这里worker用了linux的epoll模型。,采用了epoll模型,一个worker大概可以处理6-8万的请求。所以,CPU越多,并发越大,处理几十万到几百万的请求是没有问题的。
在nginx.conf中,事件处理参数:
events {
# 默认使用epoll,所以实际上可以不配置use epoll
use epoll;
# 每个worker允许连接的请求最大数目
# 不能盲目修改增大,要跟着硬件走,否则请求会产生卡顿
worker_connections 1024;
}
小结
Nginx的这种抢占机制和事件处理机制,正是它高并发的原因。