Nginx 高效工作原理

Nginx 高效工作的原理

本文参考了一下文章:

Nginx工作原理和优化总结

通俗易懂的Nginx工作原理

关于Nginx入门介绍、在网络请求中工作的位置可以参考上一篇文章:Nginx在网络请求中的工作位置

Nginx的模块划分

​ Nginx本身做的工作实际很少,当它接到一个HTTP请求时,它仅仅是通过查找配置文件将此次请求映射到一个location block,而此location中所配置的各个指令则会启动不同的模块去完成工作,因此模块可以看做Nginx真正的劳动工作者。

Nginx的模块从功能上分为如下四类:

  • Core(核心模块): 构建nginx基础服务、管理其他模块。

  • Handlers(处理器模块): 此类模块直接处理请求,并进行输出内容和修改headers信息等操作。

  • Filters (过滤器模块): 此类模块主要对其他处理器模块输出的内容进行修改操作,最后由Nginx输出。

  • Proxies (代理类模块): 此类模块是Nginx的HTTP Upstream之类的模块,这些模块主要与后端一些服务比如FastCGI等进行交互,实现服务代理和负载均衡等功能。

(1) 当Nginx发送文件或者转发请求到其他服务器,由Handlers(处理模块)或Proxies(代理类模块)提供服务;

(2) 当需要Nginx把输出压缩或者在服务端加一些东西,由Filters(过滤模块)提供服务。

这个流程就基本上是这样的:

客户端发送HTTP请求 –> Nginx基于配置文件中的location block 选择一个合适的处理模块 -> (如果有)负载均衡模块选择一台后端服务器 –> 处理模块进行处理并把输出缓冲放到第一个过滤模块上 –> 第一个过滤模块处理后输出给第二个过滤模块 –> 然后第二个过滤模块又到第三个 –> 依此类推 –> 最后把响应发给客户端。

如下图:

下图引用自Nginx工作原理和优化总结 博客中的插图

img

Nginx请求处理

​ Nginx在启动时会以daemon形式在后台运行,采用多进程+异步非阻塞IO事件模型来处理各种连接请求。

多进程

多进程模型包括一个master进程,多个worker进程,一般worker进程个数是根据服务器CPU核数来决定的。master进程一开始就会根据我们的配置,来建立需要listen的网络socket fd,然后fork出多个worker进程。master进程负责管理Nginx本身和其他worker进程。

https://raw.githubusercontent.com/qlivevilp/images/main/typora_windows/image-20210407192142635.png

master进程负责管理work进程,请求实际是由 work进程来处理的,而每个work进程包含一个进程,每个worker可以并行处理数千个的并发连接和请求。

进程模型的处理方式带来的一些好处就是:进程之间是独立的,也就是一个worker进程出现异常退出,其他worker进程是不会受到影响

的;此外,独立进程也会避免一些不需要的锁操作,这样子会提高处理效率,并且开发调试也更容易。

那么多线程模型就会涉及到以下几个问题:

  1. 怎么决定由哪个work进程来处理请求呢?

    ​ 因为所有的work进程都由master进程派生而来,所以他们都会监听相同的socket fd。因此当一个请求进来的时候,所有的work进程都能监听到。但是只有一个work进程能accept成功,去处理该请求。

    ​ nginx中实现了一个“accept_mutex”类似互斥锁,只有获取到这个锁的进程,就能accept该请求。其他进程全部accept 失败。

  2. 怎么尽量平均分配每个进程处理的请求数呢?

    ​ 如果每次work进行再竞争请求处理时都是随机的,那么可能发生的一个问题就是,大部分请求被某个进程给获取了,其他的work进程都很闲,而某一个进程会处于忙碌状态。而下次请求进来的时候,忙碌进程还有可能会继续去竞争请求。

    ​ 为了避免这种情况,Nginx添加了一个ngx_accept_disabled标识,由他控制一个worker进程是否需要去竞争获取accept_mutex选项,进而获取accept事件。

    ngx_accept_disabled值:nginx单进程的所有连接总数的八分之一,减去剩下的空闲连接数量,得到的这个ngx_accept_disabled。

    当ngx_accept_disabled大于0时,不会去尝试获取accept_mutex锁,并且将ngx_accept_disabled减1

    不去获取accept_mutex锁,就是等于让出获取连接的机会,很显然可以看出,当空闲连接越少时,ngx_accept_disable越大,于是让出的机会就越多,这样其它进程获取锁的机会也就越大。不去accept,自己的连接就控制下来了,其它进程的连接池就会得到利用,这样,nginx就控制了多进程间连接的平衡了。

  3. Nginx如何利用多线程模型实现热部署的?

    ​ 所谓热部署,就是配置文件nginx.conf修改后,不需要stop Nginx,不需要中断请求,就能让配置文件生效!

    ​ 修改配置文件nginx.conf后,重新生成新的worker进程,然后以新的配置进行处理请求,而且新的请求必须都交给新的worker进程,至于老的worker进程,等把那些以前的请求处理完毕后,kill掉即可。

异步非阻塞IO事件

​ 许多请求是需要读写数据,发生IO请求的,此时程序就会发生中断,如果此时我们一直等待IO调用结束,才继续工作,那么这种就是阻塞的,那么很显然后面的请求过来了,都处于等待状态,CPU就将处于空闲状态。

​ 为了提供高并发的能力,Nginx采用的是非阻塞的方式。如果发生IO中断,那么你去做你的事情,但是过一段时间来看看IO调用是否结束,这就是非阻塞:你可以做更多的事情,但是你得时不时的检查中断状态,带来的开销也不小。

​ 那么所谓异步呢?Nginx采用了Linux的epoll模型,epoll模型基于事件驱动机制,它可以监控多个事件是否准备完毕,如果OK,那么放入epoll队列中,这个过程是异步的。worker只需要从epoll队列循环处理即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值