社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  NGINX

只知道 Nginx 牛逼,却不知道它怎么支持百万并发?

占小狼的博客 • 4 年前 • 377 次点击  

点击上方蓝色字体,选择“设为星标”

优质文章,及时送达

来源 | https://urlify.cn/UN3eUb

Nginx是一个免费的,开源的,高性能的HTTP服务器和反向代理。以其高性能,稳定性,丰富的功能,简单的配置和低资源消耗而闻名。Nginx是一个Web服务器,也可以用作负载均衡器和HTTP缓存。

很多高知名度的网站都使用Nginx,比如:Netflix,GitHub,SoundCloud,MaxCDN等。

1.Nginx的整体架构

1.1.主进程

Nginx启动时,会生成两种类型的进程,一个是主进程(master),一个(windows版本的目前只有一个)或多个工作进程(worker)。

主进程并不处理网络请求,主要负责调度工作进程,也就是图示的3项:加载配置、启动工作进程、非停升级

因此,Nginx启动以后,查看操作系统的进程列表,我们就能看到至少有两个Nginx进程。

1.2.工作进程

服务器实际处理网络请求及响应的是工作进程(worker),在类unix系统上,Nginx可以配置多个worker,而每个worker进程都可以同时处理数以千计的网络请求。

1.3.模块化设计

Nginx的worker进程,包括核心和功能性模块,核心模块负责维持一个运行循环(run-loop),执行网络请求处理的不同阶段的模块功能。

比如:网络读写、存储读写、内容传输、外出过滤,以及将请求发往上游服务器等。

而其代码的模块化设计,也使得我们可以根据需要对功能模块进行适当的选择和修改,编译成具有特定功能的服务器。

1.4.事件驱动模型

基于异步及非阻塞的事件驱动模型,可以说是Nginx得以获得高并发、高性能的关键因素,同时也得益于对Linux、Solaris及类BSD等操作系统内核中事件通知及I/O性能增强功能的采用,如kqueue、epoll及eventports。

1.5.代理(proxy)设计

代理设计,可以说是Nginx深入骨髓的设计,无论是对于HTTP,还是对于FastCGI、Memcache、Redis等的网络请求或响应,本质上都采用了代理机制。所以,Nginx天生就是高性能的代理服务器。

2.Nginx的模块化设计

高度模块化的设计是Nginx的架构基础。Nginx服务器被分解为多个模块,每个模块就是一个功能模块,只负责自身的功能,模块之间严格遵循“高内聚,低耦合”的原则。

如下图所示:

2.1.核心模块

核心模块是Nginx服务器正常运行必不可少的模块,提供错误日志记录、配置文件解析、事件驱动机制、进程管理等核心功能。

2.2.标准HTTP模块

标准HTTP模块提供HTTP协议解析相关的功能,比如:端口配置、网页编码设置、HTTP响应头设置等等。

2.3.可选HTTP模块

可选HTTP模块主要用于扩展标准的HTTP功能,让Nginx能处理一些特殊的服务,比如:Flash多媒体传输、解析GeoIP请求、网络传输压缩、安全协议SSL支持等。

2.4.邮件服务模块

邮件服务模块主要用于支持Nginx的邮件服务,包括对POP3协议、IMAP协议和SMTP协议的支持。

2.5.第三方模块

第三方模块是为了扩展Nginx服务器应用,完成开发者自定义功能,比如:Json支持、Lua支持等。

3.Nginx的请求方式处理

Nginx是一个高性能的Web服务器,能够同时处理大量的并发请求。它结合多进程机制和异步机制,异步机制使用的是异步非阻塞方式,接下来就给大家介绍一下Nginx的多线程机制和异步非阻塞机制。

3.1.多进程机制

服务器每当收到一个客户端时,就有服务器主进程(master process)生成一个子进程(worker process)出来和客户端建立连接进行交互,直到连接断开,该子进程就结束了。

使用进程的好处是各个进程之间相互独立,不需要加锁,减少了使用锁对性能造成影响,同时降低编程的复杂度,降低开发成本。

其次,采用独立的进程,可以让进程互相之间不会影响,如果一个进程发生异常退出时,其它进程正常工作,master进程则很快启动新的worker进程,确保服务不会中断,从而将风险降到最低。

缺点是操作系统生成一个子进程需要进行内存复制等操作,在资源和时间上会产生一定的开销。当有大量请求时,会导致系统性能下降。

3.2.异步非阻塞机制

每个工作进程使用异步非阻塞方式,可以处理多个客户端请求。

当某个工作进程接收到客户端的请求以后,调用IO进行处理,如果不能立即得到结果,就去处理其他请求(即为非阻塞),而客户端在此期间也无需等待响应,可以去处理其他事情(即为异步)

当IO返回时,就会通知此工作进程,该进程得到通知,暂时挂起当前处理的事务去响应客户端请求。

4.Nginx事件驱动模型

在Nginx的异步非阻塞机制中,工作进程在调用IO后,就去处理其他的请求,当IO调用返回后,会通知该工作进程。

对于这样的系统调用,主要使用Nginx服务器的事件驱动模型来实现,如下图所示:

如上图所示,Nginx的事件驱动模型由事件收集器、事件发送器和事件处理器三部分基本单元组成。

事件收集器:负责收集worker进程的各种IO请求;

事件发送器:负责将IO事件发送到事件处理器;

事件处理器:负责各种事件的响应工作。

事件发送器将每个请求放入一个待处理事件列表,使用非阻塞I/O方式调用事件处理器来处理该请求。

其处理方式称为“多路IO复用方法”,常见的包括以下三种:select模型、poll模型、epoll模型。

5.Nginx进程处理模型

Nginx服务器使用 master/worker 多进程模式,多线程启动和执行的流程如下:

主程序Masterprocess启动后,通过一个for循环来接收和处理外部信号

主进程通过fork()函数产生worker子进程,每个子进程执行一个for循环来实现Nginx服务器对事件的接收和处理

一般推荐worker进程数与CPU内核数一致,这样一来不存在大量的子进程生成和管理任务,避免了进程之间竞争CPU资源和进程切换的开销。

而且Nginx为了更好的利用多核特性,提供了CPU亲缘性的绑定选项,我们可以将某一个进程绑定在某一个核上,这样就不会因为进程的切换带来Cache的失效。

对于每个请求,有且只有一个工作进程对其处理。首先,每个worker进程都是从master进程fork过来。在master进程里面,先建立好需要listen的socket(listenfd)之后,然后再fork出多个worker进程。

所有worker进程的listenfd会在新连接到来时变得可读,为保证只有一个进程处理该连接,所有worker进程在注册listenfd读事件前抢占accept_mutex

抢到互斥锁的那个进程注册listenfd读事件,在读事件里调用accept接受该连接。

当一个worker进程在accept这个连接之后,就开始读取请求,解析请求,处理请求,产生数据后,再返回给客户端,最后才断开连接,一个完整的请求就是这样。

我们可以看到,一个请求,完全由worker进程来处理,而且只在一个worker进程中处理。

如下图所示:

在Nginx服务器的运行过程中,主进程和工作进程需要进程交互。交互依赖于Socket实现的管道来实现。

5.1.主进程与工作进程交互

这条管道与普通的管道不同,它是由主进程指向工作进程的单向管道,包含主进程向工作进程发出的指令工,作进程ID等。同时主进程与外界通过信号通信;每个子进程具备接收信号,并处理相应的事件的能力。

5.2.工作进程与工作进程交互

这种交互和主进程-工作进程交互基本一致,但是会通过主进程间接完成,工作进程之间是相互隔离的。

所以当工作进程W1需要向工作进程W2发指令时,首先找到W2的进程ID,然后将正确的指令写入指向W2的通道,W2收到信号采取相应的措施。




明天见(。・ω・。)ノ♡
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/56071
 
377 次点击