当前位置: 首页 > 科技观察

深入理解Nginx的架构

时间:2023-03-20 17:46:21 科技观察

前言最近在看Nginx相关的书籍,做一些读书笔记。Nginx作为业界知名的高性能服务器,应用非常广泛。它的高性能源于其出色的架构设计。其架构主要包括以下几点:模块化设计、事件驱动架构、请求的多阶段异步处理、管理进程和多worker进程设计、内存池设计,以下内容依次进行讲解。模块化设计高度模块化的设计是Nginx的架构基础。在Nginx中,除了少量的核心代码,其他都是模块。所有模块都分为层和类别。Nginx官方有五类模块:核心模块、配置模块、事件模块、HTTP模块、邮件模块。它们之间的关系如下:五个模块中,配置模块和核心模块与Nginx框架密切相关。事件模块是HTTP模块和邮件模块的基础。HTTP模块和邮件模块的“地位”是相似的,都更侧重于应用层面。事件驱动架构事件驱动架构,简单的说就是一些事件源产生事件,事件收集器收集并分发事件,然后事件处理器处理这些事件(事件处理器需要先在事件收集器中注册您要处理的事件)。对于Nginx服务器来说,事件一般是由网卡和磁盘产生的。Nginx中的事件模块会负责事件的收集和分发;所有模块都可能是事件消费者。他们首先需要向事件模块Type注册感兴趣的事件,这样当有事件发生时,事件模块会将事件分发给相应的模块进行处理。对于传统的Web服务器(如Apache),使用的所谓事件驱动往往仅限于TCP连接建立和关闭事件。一个连接建立后,关闭之前的所有操作都不再是事件驱动的,此时会退化成批处理模式,依次执行每个操作,这样连接建立后每次请求都会一直占用系统资源,并且在关闭之前不会释放资源。这种请求占用服务器资源等待处理的模式会造成服务器资源的极大浪费。如下图所示,传统的Web服务器通常使用进程或线程作为时间消费者。当请求产生的事件被进程处理时,进程资源会被请求占用,直到请求处理结束。一个典型的例子就是Apache同步阻塞的多进程模式。传统Web服务器处理事件的简单模型(矩形代表进程):Nginx采用事件驱动架构,以不同于传统Web服务器的方式处理业务。它不使用进程或线程作为事件消费者,所谓的事件消费者只能是某个模块。只有事件收集器和分发器才有资格占用进程资源。它们在分发事件时会调用事件消费模块使用当前占用的进程资源,如下图,列出了5种不同的事件。在事件收集和分发进程的一次处理中,当这5个事件按顺序收集后,当前进程会开始分发事件,从而调用相应的事件消费者处理事件。当然,这种分配和调用也是有秩序的。Nginx处理事件的简单模型:从上图可以看出,在处理请求事件时,Nginx的事件消费者只是在很短的时间内被事件分发进程调用。这种设计使得网络性能和用户感知的请求延迟都得到了改善,每个用户的请求产生的事件都会得到及时的响应,整个服务器的网络吞吐量也会因为对事件的及时响应而增加。当然这也带来了一定的要求,就是每个事件消费者不能有阻塞行为,否则其他事件会因为长期占用事件分发进程而无法及时响应。Nginx的非阻塞特性是由于它的模块都满足了这个要求。请求的多级异步处理请求的多级异步处理与事件驱动架构密切相关,也就是说,请求的多级异步处理只能基于事件驱动架构来实现。多阶段异步处理是将一个请求的处理按照事件触发的方式分成多个阶段,每个阶段都可以由事件收集器和分发器触发。处理获取静态文件的HTTP请求时的切分阶段和各阶段的触发事件如下:如果想学Java工程,高性能,分布式,很容易理解。微服务、Spring、MyBatis、Netty源码分析的朋友可以加我Java进阶交流:854630135。群里有阿里大牛的现场讲解技术,还有Java大型互联网技术视频免费分享给大家。本例中,请求大致分为7个阶段,这些阶段可以重复。因此,一个下载静态资源的请求可能会因为请求数据过多、网速不稳定等因素分解成几百上千个。上面列出的阶段。异步处理和多阶段是相辅相成的。只有把请求分成多个阶段,才有所谓的异步处理。当一个事件分发给事件消费者处理时,事件消费者处理该事件只相当于处理了1个请求阶段。什么时候可以处理下一阶段?这只能等待内核的通知,即下次事件发生时,epoll等事件分发器会得到通知,然后调用事件消费者进行处理。管理进程,多worker进程设计Nginx启动后,会有一个master进程和多个worker进程。master进程主要用来管理worker进程,包括接收外界的信号,向各个worker进程发送信号,监控worker进程的运行状态,启动worker进程。工作进程用于处理来自客户端的请求事件。多个工作进程是平等的,它们平等地竞争来自客户的请求。每个进程相互独立,一个请求只能在一个worker进程中处理。worker进程数可以设置,一般设置为与机器的CPU核数一致。其原因与事件处理模型有关。Nginx的进程模型可以用下图表示:查看服务器上的Nginx进程:这种设计带来了以下好处:1)利用多核系统的并发处理能力现代操作系统已经支持多核CPU架构,可以让多个进程占用不同的CPU核心分别工作。Nginx中的所有工作进程都是完全平等的。这提高了网络性能并减少了请求延迟。2)负载均衡多个worker进程通过进程间通信实现负载均衡,即当有请求到来时,更容易分配给负载较轻的worker进程处理。这也在一定程度上提高了网络性能,减少了请求延迟。3)管理进程将负责监控工作进程的状态并管理其行为。管理进程不会占用太多系统资源。它仅用于启动、停止、监视或使用其他行为来控制工作过程。首先,这提高了系统的可靠性。当worker进程出现问题时,管理进程可以启动一个新的worker进程,避免系统性能下降。其次,管理进程支持Nginx服务运行过程中的程序升级、配置项修改等操作。这种设计使得动态可伸缩性和动态定制更容易实现。内存池的设计为了避免内存碎片,减少操作系统对内存的申请次数,降低各个模块的开发复杂度,Nginx设计了一个简单的内存池。它的作用主要是将多次申请内存的操作集成到系统中一次,大大减少了CPU资源的消耗,同时减少了内存碎片。因此,每个请求通常都有一个简单的独立内存池(例如,每个TCP连接都分配一个内存池),而在请求结束时,整个内存池会被销毁,分配的内存会归还给一次操作。系统。这种设计大大提高了模块开发的简单性,因为模块申请内存后不需要关心它的释放;并且因为减少了内存分配的次数,减少了请求执行的延迟。同时,通过减少内存碎片,提高内存的有效利用率和系统可处理的并发连接数,从而提升网络性能。