写在前面Nginx是一个免费、开源、高性能的HTTP服务器和反向代理。以高性能、稳定、丰富的功能、简单的配置和低资源消耗着称。Nginx是一个Web服务器,也可以用作负载平衡器和HTTP缓存。许多知名网站都使用了Nginx,例如:Netflix、GitHub、SoundCloud、MaxCDN等。正文1.Nginx1.1的总体结构。主进程Nginx启动时,会产生两种进程,一种是主进程(master),一种(windows版本目前只有一个)或者多个工作进程(worker)。主进程不处理网络请求,主要负责调度工作进程,即图中的三项:加载配置启动工作进程不停升级因此,Nginx启动后,查看运行的进程列表system,我们可以看到至少有两个Nginx进程。1.2.工作进程服务器实际处理网络请求并响应工作进程(worker)。在类Unix系统上,Nginx可以配置多个worker,每个worker进程可以同时处理上千个网络请求。1.3.模块化设计Nginx的worker进程包括核心模块和功能模块。核心模块负责维护一个运行循环(run-loop)并在网络请求处理的不同阶段执行模块功能。例如:网络阅读和写作,存储读取和写作,内容传输,出站过滤以及向上游服务器发送请求等。其代码的模块化设计还使我们可以根据需要正确选择和修改功能模块,并编译他们进入具有特定功能的服务器。1.4.事件驱动模型是基于异步非阻塞的事件驱动模型,可以说是Nginx实现高并发和高性能的关键因素。它还受益于事件通知和采用I/O性能增强,例如kqueue、epoll和事件端口。1.5.Proxy(代理)设计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.多进程机制每当服务器接收到一个客户端,一个服务器的主进程(masterprocess)产生一个子进程(workerprocess)与客户端建立连接进行交互,直到连接断开,子进程就结束了。使用进程的好处是每个进程相互独立,不需要加锁,减少了使用锁对性能的影响,降低了编程复杂度,降低了开发成本。其次,可以使用独立的进程,使得进程之间不会相互影响。如果一个进程异常退出,其他进程正常工作,master进程会迅速启动一个新的worker进程,保证服务不会中断,从而将风险降到最低。缺点是操作系统生成子进程需要进行内存拷贝等操作,会在资源和时间上产生一定的开销。当有大量请求时,会导致系统性能下降。3.2.异步非阻塞机制每个worker进程采用异步非阻塞方式,可以处理多个客户端请求。当一个worker进程收到客户端的请求后,调用IO进行处理。如果不能立即得到结果,则处理其他请求(即非阻塞)。客户端在此期间不需要等待响应,可以处理其他请求的东西(也就是异步的),当IO返回时,会通知worker进程,通知进程暂时挂起当前正在处理的响应客户端请求的事务。4、Nginx的事件驱动模型在Nginx的异步非阻塞机制中,worker进程调用IO后,会去处理其他的请求。当IO调用返回时,将通知工作进程。对于这样的系统调用,主要是利用Nginx服务器的事件驱动模型来实现,如下图:如上图所示,Nginx的事件驱动模型由三个基本单元组成:事件收集器、事件发送器和事件处理器。事件收集器:负责收集worker进程的各种IO请求;eventsender:负责将IO事件发送给eventhandler;事件处理器:负责各种事件的响应。事件发送者将每个请求放入一个待处理事件列表中,并使用非阻塞I/O调用事件处理程序来处理请求。其处理方式称为“多路IO复用方式”,常见的有以下三种:select模型、poll模型、epoll模型。5、Nginx进程处理模型Nginx服务器采用master/worker多进程模式。多线程启动和执行的过程如下:主程序Master进程启动后,通过for循环接收并处理外部信号。主进程通过fork()函数生成Worker子进程,每个子进程执行一个for循环,实现Nginx服务器对事件的接收和处理。一般建议工作进程数与CPU核数一致,这样就不会产生大量的子进程生成和管理任务,避免进程争抢CPU资源和进程切换的开销。而且,为了更好的利用多核特性,Nginx提供了CPU亲和性的绑定选项。我们可以将某个进程绑定到某个核上,这样缓存就不会因为进程切换而失效。对于每个请求,只有一个工作进程来处理它。首先,每个工作进程都是从主进程派生出来的。在master进程中,先设置好需要监听的socket(listenfd),然后fork多个worker进程。当新连接到达时,所有工作进程的listenfd将变得可读。为确保只有一个进程处理连接,所有工作进程在注册listenfd读取事件之前抢占accept_mutex。抢到互斥锁的进程注册listenfd读事件。在事件中调用accept以接受连接。当一个工作进程接受连接后,开始读取请求,解析请求,处理请求,生成数据,然后返回给客户端,最后断开连接,一个完整的请求是这样的。我们可以看到一个请求是完全由worker进程处理的,而且只在一个worker进程中处理。如下图所示:Nginx服务器在运行过程中,主进程和worker进程需要进行进程交互。交互依赖于Socket实现的管道。5.1.主进程与工作进程交互。这条管道不同于普通的管道。是主进程到工作进程的单向管道,包括主进程发送给工作进程的指令,工作进程ID等。同时,主进程通过信号;每个子进程都有接收信号和处理相应事件的能力。5.2.Worker进程-worker进程交互这种交互与主进程-worker进程交互基本相同,只是会通过主进程间接进行,worker进程之间是相互隔离的。因此,当工作进程W1需要向工作进程W2发送指令时,首先找到W2的进程ID,然后将正确的指令写入指向W2的通道,W2收到信号后采取相应的措施。小结通过本文,我们对Nginx服务器的整体架构有了一个整体的了解。包括它的模块化设计、多进程和异步非阻塞请求处理方式、事件驱动模型等。只有通过这些理论知识,才能更好地理解Nginx的设计思想。对我们学习Nginx有很大的帮助。关注移民哥技术之路微信公众号对话回复关键字:1024即可获取最新2TB技术干货:包括系统运维、数据库、redis、MogoDB、电子书、Java基础课程、Java实战项目、架构师综合教程、架构师实战项目、大数据、Docker容器、ELKStack、机器学习、BAT面试精讲视频等。
