【nginx系列】深⼊理解nginx原理
⼀、Nginx 的进程模型
Nginx 模型有两种进程,Master进程和Worker进程,Master进程主要⽤来管理Worker进程,管理包含:
1. 接收来⾃外界的信号
2. 向各worker进程发送信号
3. 监控worker进程的运⾏状态
4. 当worker进程退出后(异常情况下),会⾃动重新启动新的worker进程
⽽基本的⽹络事件,则是放在Worker进程中来处理了,多个Worker进程之间是对等的,他们同等竞争来⾃客户端的请求,各进程互相之间是独⽴的。⼀个请求,只可能在⼀个worker进程中处理,⼀个worker进程,不可能处理其它进程的请求。Worker进程的个数是可以设置的,⼀般我们会设置与机器CPU核数⼀致,这⾥⾯的原因与Nginx进程模型以及事件处理模型分不开。
(1)守护进程
⼀般启动nginx后,在unix系统的后端会以daemon(守护进程)的⽅式运⾏,守护进程是只运⾏的服务器端程序,通常在系统后 台运⾏,没有控制终端,不与前台交互,daemon是长时间运⾏的进程,通常在系统启动后就运⾏,在系统关闭时结束。
(2)Nginx启动⽅式
Nginx的启动⽅式有两种:
单进程启动:此时系统中只有⼀个进程,这个进程既是master进程,也是worker进程。
多进程启动:此时系统中有且仅有⼀个master进程,有多个worker进程,master进程主要是⽤来管理worker进程的。
(3)Nginx进程模型
Nginx 服务器,正常运⾏过程中:
多进程:⼀个 Master 进程、多个 Worker 进程
Master 进程:管理 Worker 进程
(1)对外接⼝:接收外部的操作(信号)
(2)对内转发:根据外部的操作的不同,通过信号管理 Worker
(3)监控:监控 worker 进程的运⾏状态,worker 进程异常终⽌后,⾃动重启 worker 进程
Worker 进程:所有 Worker 进程都是平等的
(1)实际处理:⽹络请求,由 Worker 进程处理;
(2)Worker 进程数量:在 f 中配置,⼀般设置为核⼼数,充分利⽤ CPU 资源,同时,避免进程数量过多,避免进程竞争 CPU 资源,增加上下⽂切换的损耗。
思考:
1. 请求是连接到 Nginx,Master 进程负责处理和转发?
2. 如何选定哪个 Worker 进程处理请求?请求的处理结果,是否还要经过 Master 进程?
(4)怎样操作Nginx?
如上所知,master进程主要是⽤来管理worker进程的,所以操作Nginx只需要操作master进程就好,我们通过发送信号的⽅式来操作master进程。master进程会接收来⾃外界发送来的消息,再根据信号做不同的事情,通过kill向master进程发送信号。
(5)怎样处理请求?
worker进程之间是平等的,每个进程,处理请求的机会也是⼀样的。当我们提供80端⼝的http服务时,⼀个连接请求过来,每个进程都有可能处理这个连接,怎么做到的呢?⾸先,每个worker进程都是从master进程fork过来,在master进程⾥⾯,先建⽴好需要listen的socket之后,然后再fork出多个worker进程,这样每个worker进程都可以去accept这个socket(当然不是同⼀个socket,只是每个进程的这个socket会监控在同⼀个ip地址与端⼝,这个在⽹络协议⾥⾯是允许的)。⼀般来说,当⼀个连接进来后,所有在accept在这个socket上⾯的进程,都会收到通知,⽽只有⼀个进程可以accept这个连接,其它的则accept失败,这是所谓的。当然,nginx也不会视⽽不见,所以nginx提供了⼀个accept_mutex这个东西,从名字上,我们可以看这是⼀个加在accept上的⼀把共享锁。有了这把锁之后,同⼀时刻,就只会有⼀个进程在accpet连接,这样就不会有惊问题了。accept_mutex是⼀个可
控选项,我们可以显⽰地关掉,默认是打开的。当⼀个worker进程在accept这个连接之后,就开始读取请求,解析请求,处理请求,产⽣数据后,再返回给客户端,最后才断开连接,这样⼀个完整的请求就是这样的了。我们可以看到,⼀个请求,完全由worker进程来处理,⽽且只在⼀个worker进程中处理。
(6)如何实现⾼并发?
nginx采⽤了异步⾮阻塞的⽅式来处理请求,也就是说,nginx是可以同时处理成千上万个请求的。
(7)为什么采⽤异步⾮阻塞的⽅式?
虽然每个worker⾥⾯只有⼀个主线程,但nginx采⽤了异步⾮阻塞的⽅式来处理请求,具体到系统调⽤就是
像 select/poll/epoll/kqueue这样的系统调⽤。 它们提供了⼀种机制,让你可以同时监控多个事件,调⽤他们是阻塞的,但可以设置超时时间,在超时时间之内,如果有事件准备好了,就返回。这种机制正好解决了我们上⾯的两个问题,拿epoll为例(在后⾯的例⼦中,我们多以epoll为例⼦,以代表这⼀类函数),当事件没准备好时,放到epoll⾥⾯,事件准备好了,我们就去读写,当读写返回EAGAIN时,我们将它再次加⼊到epoll⾥⾯。这样,只要有事件准备好了,我们就去处理它,只有当所有事件都没
准备好时,才在epoll⾥⾯等着。这样,我们就可以并发处理⼤量的并发了,当然,这⾥的并发请求,是指未处理完的请求,线程只有⼀个,所以同时能处理的请求当然只有⼀个了,只是在请求间进⾏不断地切换⽽已,切换也是因为异步事件未准备好,⽽主动让出的。这⾥的切换是没有任何代价,你可以理解为循环处理多个准备好的事件,事实上就是这样的。
与多线程相⽐,这种事件处理⽅式是有很⼤的优势的,不需要创建线程,每个请求占⽤的内存也很少,没有上下⽂切换,事件处理⾮常的轻量级。并发数再多也不会导致⽆谓的资源浪费(上下⽂切换)。
⼆、Nginx框架处理流程
nginx对请求处理分为11个阶段,在这11个阶段中有处理的先后顺序,如果第⼀个阶段的模块处理并返回后,后⾯的阶段将不会再处理,灰⾊阶段是nginx框架做的事,我们⽆法处理,如下:
2.limit_req(限制每秒连接数)、limit_conn(限制每秒并发连接数)
3.access、auth_basic等是做验证的,可以让客户端输⼊⽤户和密码后才能请求
5.log是记录请求⽇志
三、Nginx的事件处理模型
request:Nginx 中 http 请求。
基本的 HTTP Web Server ⼯作模式:
1. 接收请求:逐⾏读取请求⾏和请求头,判断段有请求体后,读取请求体
2. 处理请求
3. 返回响应:根据处理结果,⽣成相应的 HTTP 请求(响应⾏、响应头、响应体)Nginx 也是这个套路,整体流程⼀致。
四、模块化体系结构
nginx和apache区别
1. main:Nginx在运⾏时与具体业务功能⽆关的参数,⽐如⼯作进程数、运⾏⾝份等。
2. http:与提供http服务相关的参数,⽐如keepalive、gzip等。
3. server:http服务上⽀持若⼲虚拟机,每个虚拟机⼀个对应的server配置项,配置项⾥包含该虚拟机相关的配置。
4. location:http服务中,某些特定的URL对应的⼀系列配置项。
5. mail: 实现email相关的SMTP/IMAP/POP3代理时,共享的⼀些配置项。
⼆、模块体系
Nginx的内部结构是由核⼼部分和⼀系列功能模块组成的,这样可以使得每个模块的功能相对简单,便于对系统进⾏功能扩展,各模块之间的关系如下图:
nginx core实现了底层的通讯协议,为其他模块和Nginx进程构建了基本的运⾏时环境,并且构建了其他各模块的协作基础。
http模块和mail模块位于nginx core和各功能模块的中间层,这2个模块在nginx core之上实现了另外⼀层抽象,分别处理与http协议和email相关协议(SMTP/IMAP/POP3)有关的事件,并且确保这些事件能被以正确的顺序调⽤其它的⼀些功能模块。
nginx功能模块基本上分为如下⼏种类型:
(1) event module:搭建了独⽴于操作系统的事件处理机制的框架,以及提供了各具体事件的处理,包括ngx_event_module、
ngx_event_core_module和ngx_epoll_module等,Nginx具体使⽤何种事件处理模块,这依赖于具体的操作系统和编译选项。
(2) phase handler:此类型的模块也被直接称为handler模块,主要负责处理客户端请求并产⽣待响应内容,⽐如ngx_http_module模块,负责客户端的静态页⾯请求处理并将对应的磁盘⽂件准备为响应内容输出。
(3) output filter:也称为filter模块,主要是负责对输出的内容进⾏处理,可以对输出进⾏修改,⽐如可以实现对输出的所有html页⾯增加预定义的footbar⼀类的⼯作,或者对输出的图⽚的URL进⾏替换之类的⼯作。
(4) upstream:实现反向代理功能,将真正的请求转发到后端服务器上,并从后端服务器上读取响应,发回客户端,upstream模块是⼀种特殊的handler,只不过响应内容不是真正由⾃⼰产⽣的,⽽是从后端服务器上读取的。
(5) load-balancer:负载均衡模块,实现特定的算法,在众多的后端服务器中,选择⼀个服务器出来作为某个请求的转发服务器。
(6) extend module:根据特定业务需要编写的第三⽅模块。
相关⽂章
1.
五、常见问题解析
Nginx vs. Apache
nginx vs. apache:
⽹络 IO 模型:
1. nginx:IO 多路复⽤,epoll(freebsd 上是 kqueue )
1. ⾼性能
2. ⾼并发
3. 占⽤系统资源少
2. apache:阻塞 + 多进程/多线程
1. 更稳定,bug 少
2. 模块更丰富
场景:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论