这篇博客简单看一看Nginx
的工作流程和机制,当然不涉及源码,我还没到那种水平。
Nginx工作流程
先来看一张官网图:
框框里面的是Nginx
的架构,可以看到它里面分为了master、worker。请求进来后由master分发任务,worker负责执行或反向代理给别的服务单元。
我们启动Nginx
后,执行以下命令,查看后台有关Nginx
的进程:
ps -ef | grep nginx
可以看到有一个master进程与worker进程,验证了图片的架构。
接下来再放一张,具体来看一下怎么个工作流程法:
这张图就比较形象,图中client作为浏览器。
当浏览器请求进来后,它先通知master进程,master进程收到请求后,会去通知名下空闲的worker进程,告诉它们有新的请求啦。再之后这些worker会去争抢,谁抢到这个请求就算谁的。抢到之后,由于Nginx
不能直接处理java的要求,需要Tomcat
来做处理,所以这个时候抢到请求的worker会反向代理给后面的Tomcat
执行。
大致的流程就是这样。就好像一个地主家(master)要收购米(浏览器发送的请求),但是这位地主热心肠,他会把收来的米送给下面的工人(worker)。可惜米数量有限呀,于是地主想了个办法,米收购完之后,地主放着,让底下的工人们过来抢,谁抢到就算谁的。这就是我们说的master和worker机制。
该机制的好处
- 还记得
Nginx
有一个命令吗:
./nginx -s reload
这个命令可以重新加载Nginx
,使配置热部署生效。
那和我们的master-worker机制有什么关系呢?
别急,现在来了。在master-worker机制下,当一个worker抢到请求时,那么它会去反向代理给后面的Tomcat
,让其去处理并返回。在这个过程中,我们能够使用上述的热部署命令加载Nginx
,是因为其它没抢到的worker去热加载自身,使其满足最新的配置,而抢到的worker正在工作中(因为抢到请求,需要先处理),等待其工作完成之后也会去热加载自身。这么做有个好处,可以在不影响处理请求的情况下去更新Nginx
的配置。也就是“无缝热部署”。
- 第二个好处其实和第一个有点像,就是每个worker都是一个进程,所以就不需要加锁,大大节省了锁的开销。同时在编程以及问题查找时,也会方便很多。其次,采用独立的进程,可以让互相之间不会影响,一个进程退出后,其它进程还在工作,服务不会中断,master 进程则很快启动新的worker 进程。当然,worker 进程的异常退出,肯定是程序有 bug 了,异常退出,会导致当前 worker 上的所有请求失败,不过不会影响到所有请求,所以降低了风险。
设置多少个worker合适?
Nginx
同 redis 类似都采用了 io 多路复用机制,每个 worker
都是一个独立的进程,但每个进程里只有一个主线程,通过异步非阻塞的方式来处理请求, 即使是千上万个请求也不在话下。
每个 worker
的线程可以把一个 cpu 的性能发挥到极致。所以 worker
数和服务器的 cpu数相等是最为适宜的。设少了会浪费 cpu,设多了会造成 cpu 频繁切换上下文带来的损耗。
也就是说,你cpu是几核的,那么worker
就多少个。
而worker的数量配置,可以直接在Nginx
的配置文件下的全剧快中进行修改:
关于这一块,可以参考以前的博客。
一点小练习
在此之前,引入一个概念:
连接数 worker_connection表示每个 worker 进程所能建立连接的最大值。
那么问题开始。
- 发送请求,占用了 woker 的几个连接数?
答案是2个或者4个。来两张图片解释下。
当浏览器请求是静态请求时,worker直接返回资源,所以是2个:
我们已经知道Nginx
实际的工作模块是worker,所以图片直接用worker表示。
当浏览器请求是动态请求时,worker去反向代理找Tomcat
处理,所以是4个:
关于动静分离的知识,可以参考之前的博客
- 第二个问题,nginx 有一个 master,有四个 woker,每个 woker 支持最大的连接数 1024,支持的最大并发数是多少?
这一问题也是分动态和静态请求。当前请求如果是静态请求时,则:
最大并发数=worker个数(4)*worker支持的最大连接数(1024)/ 所消耗的连接数(2)=2048
如果是动态请求时,同理,则有:
最大并发数=worker个数(4)*worker支持的最大连接数(1024)/ 所消耗的连接数(4)=1024
关于上述公式简单说明一下,最大并发数无非就是当前所有的worker加起来最多可以同时处理多少个请求。那就是所有worker的连接数(worker个数*worker支持的最大连接数),但其中因为动静请求的问题会有来回,损耗了连接数(根据第一个问题可知)。所以所有worker的连接数还需根据请求的类别除以2或4.