Nginx 设计原理与技术架构
Nginx (engine x)是一个免费、开源、高性能的 HTTP 服务器和反向代理,也可用作负载均衡器 和 HTTP 缓存,以及 IMAP / POP3 代理服务器,以其高性能,稳定性,丰富的功能,简单的配置和低资源消耗而闻名。
Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambler.ru站点(俄文:Рамблер)开发的,第一个公开版本0.1.0发布于2004年10月4日。
其将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。2011年6月1日,nginx 1.0.4发布。
Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上nginx的并发能力在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。
Nginx 官网:http://nginx.org ,nginx-1.17.6.tar.gz (2019-11-19)
Nginx Github:https://github.com/nginx/nginx
Tengine 官网:http://tengine.taobao.org (淘宝)
Tengine Github:https://github.com/alibaba/tengine
Tengine (淘宝)
Tengine是由淘宝网发起的Web服务器项目,它在Nginx的基础上,针对大访问量网站的需求,添加了很多高级功能和特性。
Tengine的性能和稳定性已经在大型的网站如淘宝网,天猫商城等得到了很好的检验。它的最终目标是打造一个高效、稳定、安全、易用的Web平台。
从2011年12月开始,Tengine成为一个开源项目,Tengine团队在积极地开发和维护着它。
Tengine团队的核心成员来自于淘宝、搜狗等互联网企业。
Tengine是社区合作的成果,我们欢迎大家参与其中,贡献自己的力量。
特性
- 继承Nginx-1.17.3的所有特性,兼容Nginx的配置;
- 支持HTTP的CONNECT方法,可用于正向代理场景;
- 支持异步OpenSSL,可使用硬件如:QAT进行HTTPS的加速与卸载;
- 增强相关运维、监控能力,比如异步打印日志及回滚,本地DNS缓存,内存监控等;
- Stream模块支持server_name指令;
- 更加强大的负载均衡能力,包括一致性hash模块、会话保持模块,还可以对后端的服务器进行主动健康检查,根据服务器状态自动上线下线,以及动态解析upstream中出现的域名;
- 输入过滤器机制支持。通过使用这种机制Web应用防火墙的编写更为方便;
- 支持设置proxy、memcached、fastcgi、scgi、uwsgi在后端失败时的重试次数
- 动态脚本语言Lua支持。扩展功能非常高效简单;
- 支持按指定关键字(域名,url等)收集Tengine运行状态;
- 组合多个CSS、JavaScript文件的访问请求变成一个请求;
- 自动去除空白字符和注释从而减小页面的体积
- 自动根据CPU数目设置进程个数和绑定CPU亲缘性;
- 监控系统的负载和资源占用从而对系统进行保护;
- 显示对运维人员更友好的出错信息,便于定位出错机器;
- 更强大的防攻击(访问速度限制)模块;
- 更方便的命令行参数,如列出编译的模块列表、支持的指令等;
- 可以根据访问文件类型设置过期时间;
- ……
Nginx 优点特性
Nginx 是一个很强大的高性能Web和反向代理服务,被广泛的应用
正是由于其优秀的架构设计,它具有很多非常优越的特性:
模块化设计、事件驱动架构、请求的多阶段异步处理、管理进程与多工作进程设计、内存池的设计
Nginx 可以在大多数 UnixLinux OS 上编译运行,并有 Windows 移植版。
Nginx 的1.4.0稳定版已经于2013年4月24日发布,一般情况下,对于新建站点,建议使用最新稳定版作为生产版本,已有站点的升级急迫性不高。
在连接高并发的情况下,Nginx是Apache服务不错的替代品:Nginx在美国是做虚拟主机生意的老板们经常选择的软件平台之一。
能够支持高达 50,000 个并发连接数的响应,感谢Nginx选择了 epoll and kqueue作为开发模型。
一、Nginx 原理架构
Nginx 里有一个 master 进程和多个 worker 进程。
1)master 进程并不处理网络请求,主要负责调度工作进程:加载配置、启动工作进程、非停升级(reload)
2)worker 进程负责处理网络请求与响应,在类 unix 系统上,Nginx 可以配置多个 worker,而每个 worker 进程都可以同时处理 数以千计 的网络请求。
所以,Nginx 启动以后,查看操作系统的进程列表,我们就能看到至少有两个 Nginx 进程(master 和 worker)
master进程主要用来管理worker进程,具体包括如下4个主要功能:
1)接收来自外界的信号,包含客户端、服务端、控制端。
2)向各worker进程发送信号。
3)监控woker进程的运行状态。
4)当woker进程退出后(异常情况下),会自动重新启动新的woker进程。
woker进程主要用来处理基本的网络事件:
1)多个worker进程之间是对等且相互独立的,他们同等竞争来自客户端的请求。
2)一个请求,只可能在一个worker进程中处理,一个worker进程,不可能处理其它进程的请求。
3)worker进程的个数是可以设置的,一般会设置进程数量与机器cpu核数一致。
4)nginx为了更好的利用多核特性,具有cpu绑定选项,可以将某一个进程绑定在某一个核上,这样就不会因为进程的切换带来cache的失效。
Ngnix 实现高性能
1、事件驱动模型
基于异步及非阻塞的事件驱动模型,可以说是 Nginx 得以获得高并发、高性能的关键因素。
同时也得益于对 Linux、Solaris 及类 BSD 等操作系统内核中事件通知及 I/O 性能增强功 的采用
这一点上和 Netty 类似,底层都是使用的 BSD kqueue、Linux epoll 及 Solaris event ports。
2、多进程机制
使用多进程的好处:
1)进程之间不共享资源,不需要加锁,减少了使用锁对性能造成的影响,同时降低编程的复杂度,降低开发成本。
2)采用独立的进程,可以让进程互相之间不会影响,如果一个进程发生异常退出时,其它进程正常工作,
3)master 进程则很快启动新的 worker 进程,确保服务不会中断,从而将风险降到最低。
3、内存池
为了避免出现内存碎片,减少向操作系统申请内存的次数、降低各个模块的开发复杂度,Nginx 设计了简单的内存池,
它的作用主要是把多次向系统申请内存的操作整合成一次,这大大减少了 CPU 资源的消耗,同时减少了内存碎片。
因此,通常每一个请求都有一个简易的独立内存池(如每个 TCP 连接都分配了一个内存池),而在请求结束时则会销毁整个内存池,把曾经分配的内存一次性归还给操作系统。这种设计大大提高了模块开发的简单些,因为在模块申请内存后不用关心它的释放问题;而且因为分配内存次数的减少使得请求执行的时延得到了降低。
同时,通过减少内存碎片,提高了内存的有效利用率和系统可处理的并发连接数,从而增强了网络性能。
4、模块化设计
高度模块化的设计是 Nginx 的架构基础。
Openresty 就是在 Nginx 上引入了 lua 等第三方模块,使得扩展更加方便了。
在 Nginx 中,除了少量的核心代码,其他一切皆为模块,所有模块间是分层次、分类别的
Nginx 官方共有五大类型的模块:核心模块、配置模块、事件模块、HTTP 模块、mail 模块
在上图的 5 种模块中,配置模块和核心模块是与 Nginx 框架密切相关的。
而事件模块则是 HTTP 模块和 mail 模块的基础。HTTP 模块和 mail 模块的“地位”类似,它们都是更关注于应用层面。
Nginx 的 worker 进程,包括核心和功能性模块,核心模块负责维持一个运行循环(run-loop),执行网络请求处理的不同阶段的模块功能,
比如:网络读写、存储读写、内容传输、外出过滤,以及将请求发往上游服务器等。
而其代码的模块化设计,也使得我们可以根据需要对功能模块进行适当的选择和修改,编译成具有特定功能的服务器。
5、代理(proxy)设计
代理设计,可以说是 Nginx 深入骨髓的设计,无论是对于 HTTP,还是对于 FastCGI、Memcache、Redis 等的网络请求或响应,本质上都采用了 代理机制。
所以,Nginx 天生就是高性能的代理服务器。
二、Nginx 模块化设计
高度模块化的设计是 Nginx 的架构基础,包括核心和功能性模块。
Nginx 服务器被分解为多个模块,每个模块就是一个功能模块,只负责自身的功能,模块之间严格遵循 “高内聚,低耦合” 的原则。
1、核心模块
核心模块 是 Nginx
服务器正常运行必不可少 的模块,提供 错误日志记录、配置文件解析、事件驱动机制、进程管理 等核心功能。
2、标准HTTP模块
标准 HTTP 模块提供 HTTP 协议解析相关的功能,比如:端口配置、网页编码设置、HTTP
响应头设置 等等。
3、可选HTTP模块
可选 HTTP 模块主要用于 扩展标准的 HTTP 功能,让 Nginx 能处理一些特殊的服务,
比如:Flash 多媒体传输、解析 GeoIP 请求、网络传输压缩、安全协议 SSL 支持等。
4、邮件服务模块
邮件服务模块 主要用于支持 Nginx 的 邮件服务,包括对 POP3、IMAP 、SMTP 协议的支持。
5、第三方模块
第三方模块 是为了扩展 Nginx 服务器应用,完成开发者自定义功能,比如:Json 支持、Lua 支持等。
三、Nginx的请求方式处理
Nginx 是一个 高性能 的 Web 服务器,能够同时处理 大量的并发请求。
它结合多进程机制和异步机制,异步机制使用的是异步非阻塞方式。
1、多进程机制
服务器每当收到一个客户端时,就有服务器主进程(master process
)生成一个 子进程(worker process
)出来和客户端建立连接进行交互,直到连接断开,该子进程就结束了。
使用 进程的好处:
1)各个进程之间相互独立,不需要加锁,减少了使用锁对性能造成影响,同时降低编程的复杂度,降低开发成本。
2)采用独立的进程,可以让 进程互相之间不会影响,如果一个进程发生异常退出时,其它进程正常工作,master
进程则很快启动新的 worker
进程,确保服务不会中断,从而将风险降到最低。
缺点是操作系统生成一个 子进程需要进行 内存复制 等操作,在 资源 和 时间 上会产生一定的开销。当有 大量请求 时,会导致 系统性能下降。
2、异步非阻塞机制
每个 工作进程 使用 异步非阻塞方式,可以处理 多个客户端请求。
当某个 工作进程 接收到客户端的请求以后,调用 IO
进行处理,如果不能立即得到结果,就去 处理其他请求(即为 非阻塞);
而 客户端 在此期间也 无需等待响应,可以去处理其他事情(即为 异步)。
当 IO
返回时,就会通知此 工作进程;该进程得到通知,暂时 挂起 当前处理的事务去 响应客户端请求。
四、Nginx 事件驱动模型
在 Nginx
的 异步非阻塞机制 中,工作进程在调用 IO
后,就去处理其他的请求,当 IO
调用返回后,会 通知 该 工作进程。
对于这样的系统调用,主要使用 Nginx
服务器的 事件驱动模型 来实现。
如上图所示,Nginx
的 事件驱动模型 由 事件收集器、事件发送器、事件处理器 三部分基本单元组成。
事件收集器:负责收集 worker
进程的各种 IO
请求;
事件发送器:负责将 IO
事件发送到 事件处理器;
事件处理器:负责各种事件的 响应工作。
事件发送器 将每个请求放入一个 待处理事件列表,使用非阻塞 I/O
方式调用 事件处理器 来处理该请求。
其处理方式称为 “多路 IO 复用方法”,常见的包括以下三种:select
模型、poll
模型、epoll
模型。
五、Nginx 进程处理模型
Nginx 服务器使用 master/worker 多进程模式。多线程启动和执行的流程如下:
1)主程序 Master process
启动后,通过一个 for
循环来 接收 和 处理外部信号;
2)主进程 通过 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
实现的 管道 来实现。
1、主进程与工作进程交互
这条管道与普通的管道不同,它是由 主进程 指向 工作进程 的 单向管道,包含主进程向工作进程发出的 指令,工作进程 ID
等;
同时 主进程 与外界通过 信号通信;每个 子进程 具备 接收信号,并处理相应的事件的能力。
2、工作进程与工作进程交互
这种交互是和 主进程-工作进程 交互是基本一致的,但是会通过 主进程 间接完成。
工作进程 之间是 相互隔离 的,所以当工作进程 W1
需要向工作进程 W2
发指令时,首先找到 W2
的 进程 ID
,然后将正确的指令写入指向 W2
的 通道,W2
收到信号采取相应的措施。
总结
通过这篇文章,我们对 Nginx
服务器的 整体架构 有了一个整体的认识。
包括其 模块化的设计、多进程、异步非阻塞 的请求处理方式、事件驱动模型 等。
通过这些理论知识,才能更好地领悟 Nginx
的设计思想,对于学习 Nginx
来说有很大的帮助。
本文转自:
Nginx 原理和架构 (CSDN)
Nginx架构模型分析 (掘金)
浅谈Nginx服务器的内部核心架构设计 (掘金)
深入 Nginx 之架构篇 (segmentfault)
参考推荐:
LNMP(CentOS+Nginx+Mysql+PHP)服务器环境配置
Nginx 限制单个IP的并发连接数/速度防止恶意攻击/蜘蛛爬虫采集
Apache Rewrite 规则 RewriteCond、RewriteRule 参数配置详解
版权所有: 本文系米扑博客原创、转载、摘录,或修订后发表,最后更新于 2020-02-23 05:21:03
侵权处理: 本个人博客,不盈利,若侵犯了您的作品权,请联系博主删除,莫恶意,索钱财,感谢!
转载注明: Nginx 设计原理与技术架构 (米扑博客)