Nginx 作为业界知名的高性能服务器,被广泛的应用。它的高性能正是由于其优秀的架构设计,其架构主要包括这几点:模块化设计、事件驱动架构、请求的多阶段异步处理、管理进程与多工作进程设计、内存池的设计,以下内容依次进行说明。
从redis,memcached到Nginx
实现Nginx模块开发
Nginx实现业务 Nginx连接mysq| 通过Nginx实现一个流媒体服务器

模块化设计

高度模块化的设计是 Nginx 的架构基础。在 Nginx 中,除了少量的核心代码,其他一切皆为模块。

所有模块间是分层次、分类别的,Nginx 官方共有五大类型的模块:核心模块、配置模块、事件模块、HTTP 模块、mail 模块。它们之间的关系如下:
在这 5 种模块中,配置模块和核心模块是与 Nginx 框架密切相关的。而事件模块则是 HTTP 模块和 mail 模块的基础。HTTP 模块和 mail 模块的“地位”类似,它们都是更关注于应用层面。

事件驱动架构

事件驱动架构,简单的说就是由一些事件发生源来产生事件,由事件收集器来收集、分发事件,然后由事件处理器来处理这些事件(事件处理器需要先在事件收集器里注册自己想处理的事件)。

对于 Nginx 服务器而言,一般由网卡、磁盘产生事件,Nginx 中的事件模块将负责事件的收集、分发操作;而所有的模块都可能是事件消费者,它们首先需要向事件模块注册感兴趣的事件类型,这样,在有事件产生时,事件模块会把事件分发到相应的模块中进行处理。

对于传统 web 服务器(如 Apache)而言,采用的所谓事件驱动往往局限在 TCP 连接建立、关闭事件上,一个连接建立以后,在其关闭之前的所有操作都不再是事件驱动,这时会退化成按顺序执行每个操作的批处理模式,这样每个请求在连接建立后都将始终占用着系统资源,直到关闭才会释放资源。这种请求占用着服务器资源等待处理的模式会造成服务器资源极大的浪费。如下图所示,传统 web 服务器往往把一个进程或线程作为时间消费者,当一个请求产生的事件被该进程处理时,直到这个请求处理结束时,进程资源都将被这一请求所占用。比较典型的例子如 Apache 同步阻塞的多进程模式就是这样的。

传统 web 服务器处理事件的简单模型(矩形代表进程):


Nginx 采用事件驱动架构处理业务的方式与传统的 web 服务器是不同的。它不使用进程或者线程来作为事件消费者,所谓的事件消费者只能是某个模块。只有事件收集、分发器才有资格占用进程资源,它们会在分发某个事件时调用事件消费模块使用当前占用的进程资源,如下图所示,该图中列出了 5 个不同的事件,在事件收集、分发者进程的一次处理过程中,这 5 个事件按照顺序被收集后,将开始使用当前进程分发事件,从而调用相应的事件消费者来处理事件。当然,这种分发、调用也是有序的。

Nginx 处理事件的简单模型:


由上图可以看出,处理请求事件时,Nginx 的事件消费者只是被事件分发者进程短期调用而已,这种设计使得网络性能、用户感知的请求时延都得到了提升,每个用户的请求所产生的事件会及时响应,整个服务器的网络吞吐量都会由于事件的及时响应而增大。当然,这也带来一定的要求,即每个事件消费者都不能有阻塞行为,否则将会由于长时间占用事件分发者进程而导致其他事件得不到及时响应,Nginx 的非阻塞特性就是由于它的模块都是满足这个要求的。

请求的多阶段异步处理

多阶段异步处理请求与事件驱动架构是密切相关的,也就是说,请求的多阶段异步处理只能基于事件驱动架构实现。多阶段异步处理就是把一个请求的处理过程按照事件的触发方式划分为多个阶段,每个阶段都可以由事件收集、分发器来触发。

处理获取静态文件的 HTTP 请求时切分的阶段及各阶段的触发事件如下所示:
如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。

这个例子中,该请求大致分为 7 个阶段,这些阶段是可以重复发生的,因此,一个下载静态资源请求可能会由于请求数据过大,网速不稳定等因素而被分解为成百上千个上图所列出的阶段。

异步处理和多阶段是相辅相成的,只有把请求分为多个阶段,才有所谓的异步处理。当一个时间被分发到事件消费者中进行处理时,事件消费者处理完这个事件只相当于处理完 1 个请求的阶段。什么时候可以处理下一个阶段呢?这只能等待内核的通知,即当下一次事件出现时,epoll 等事件分发器将会获取到通知,然后去调用事件消费者进行处理。

管理进程、多工作进程设计

Nginx 在启动后,会有一个 master 进程和多个 worker 进程。master 进程主要用来管理worker 进程,包括接收来自外界的信号,向各 worker 进程发送信号,监控 worker 进程的运行状态以及启动 worker 进程。 worker 进程是用来处理来自客户端的请求事件。多个 worker 进程之间是对等的,它们同等竞争来自客户端的请求,各进程互相独立,一个请求只能在一个 worker 进程中处理。worker 进程的个数是可以设置的,一般会设置与机器 CPU 核数一致,这里面的原因与事件处理模型有关。Nginx 的进程模型,可由下图来表示:
在服务器上查看 Nginx 进程:
这种设计带来以下优点:

1) 利用多核系统的并发处理能力

现代操作系统已经支持多核 CPU 架构,这使得多个进程可以分别占用不同的 CPU 核心来工作。Nginx 中所有的 worker 工作进程都是完全平等的。这提高了网络性能、降低了请求的时延。

2) 负载均衡

多个 worker 工作进程通过进程间通信来实现负载均衡,即一个请求到来时更容易被分配到负载较轻的 worker 工作进程中处理。这也在一定程度上提高了网络性能、降低了请求的时延。

3) 管理进程会负责监控工作进程的状态,并负责管理其行为

管理进程不会占用多少系统资源,它只是用来启动、停止、监控或使用其他行为来控制工作进程。首先,这提高了系统的可靠性,当 worker 进程出现问题时,管理进程可以启动新的工作进程来避免系统性能的下降。其次,管理进程支持 Nginx 服务运行中的程序升级、配置项修改等操作,这种设计使得动态可扩展性、动态定制性较容易实现。

内存池的设计

为了避免出现内存碎片,减少向操作系统申请内存的次数、降低各个模块的开发复杂度,Nginx 设计了简单的内存池,它的作用主要是把多次向系统申请内存的操作整合成一次,这大大减少了 CPU 资源的消耗,同时减少了内存碎片。

因此,通常每一个请求都有一个简易的独立内存池(如每个 TCP 连接都分配了一个内存池),而在请求结束时则会销毁整个内存池,把曾经分配的内存一次性归还给操作系统。这种设计大大提高了模块开发的简单些,因为在模块申请内存后不用关心它的释放问题;而且因为分配内存次数的减少使得请求执行的时延得到了降低。同时,通过减少内存碎片,提高了内存的有效利用率和系统可处理的并发连接数,从而增强了网络性能。

技术交流群:【960994558】整理了一些个人觉得比较好的学习书籍、大厂面试题、和热门技术教学视频资料共享在里面(包括C/C++,Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等等.),有需要的可以自行添加哦!~

深入理解 Nginx 之架构篇相关推荐

  1. 深入 Nginx 之架构篇

    前言 最近在读 Nginx 相关的书籍,做一下读书笔记. Nginx 作为业界知名的高性能服务器,被广泛的应用.它的高性能正是由于其优秀的架构设计,其架构主要包括这几点:模块化设计.事件驱动架构.请求 ...

  2. Nginx架构篇(一)动态网站架构、LNMP、FastCGI、nginx+fastcgi运行原理

    一.动态网站架构 资源文件识别 语言识别 框架识别 index.php 开源的php Window/Linux+nginx+php+mysql index.py 开源的python Window/Li ...

  3. 推荐我的新书《深入理解Nginx:模块开发与架构解析》

    http://www.china-pub.com/STATIC/zt_mb/zt_huodong_2013_3.asp?filename=2013_jsj_nginx_20130401 目录 < ...

  4. 《深入理解Nginx》阅读与实践(一):Nginx安装配置与HelloWorld

    最近在读陶辉的<深入理解Nginx:模块开发与架构解析>,一是想跟着大牛练练阅读和编写开源代码的能力,二是想学学Nginx优秀的架构设计,三是想找一个点深入下Linux下网络编程的细节.侯 ...

  5. 安排,谷粒商城java分布式开发基础篇高级篇与高可用集群架构篇2020

    来源: 来自网络,如侵权请告知博主删除????. 仅学习使用,请勿用于其他- 最近有小伙伴管我要分布式这类的项目,还有一些要商城的,还有要springboot,springcloud,k8s等,几乎涵 ...

  6. 趣味理解:三层架构与养猪—《.NET深入体验与实战精要》

    为了更好地让初学者轻松入门,这里仍然采用趣味性的方式聊一些常用技术点,致力于.NET新手们的快速提高!知识都是普通的,关键是学习的思路.技术源于生活,技术原来可以这样学.抛砖引玉而已.  层次结构在现 ...

  7. 《深入理解Nginx》阅读与实践(四):简单的HTTP过滤模块

    一.Nginx的HTTP过滤模块特征 一个请求可以被任意个HTTP模块处理: 在普通HTTP模块处理请求完毕并调用ngx_http_send_header()发送HTTP头部或调用ngx_http_o ...

  8. 一文理解Netty模型架构

    转载自  一文理解Netty模型架构 本文基于Netty4.1展开介绍相关理论模型,使用场景,基本组件.整体架构,知其然且知其所以然,希望给读者提供学习实践参考. 1 Netty简介 Netty是 一 ...

  9. MySQL性能调优与架构设计-架构篇

    架构篇(1) 读书笔记 1.Scale(扩展):从数据库来看,就是让数据库能够提供更强的服务能力 ScaleOut: 是通过增加处理节点的方式来提高整体处理能力 ScaleUp: 是通过增加当前处理节 ...

  10. 全解MySQL之架构篇:自顶向下深入剖析MySQL整体架构

    二.MySQL整体结构浅析 本章作为MySQL系列的开篇之作,当然也有一定的原因,毕竟只有先对MySQL的整体架构有了一个宏观的认知,才能更好的理解每个细节点的知识. MySQL与我们开发项目时相同, ...

最新文章

  1. 由SELECT *引发的多个生产故障,问题藏太深了吧……
  2. 45. Jump Game II
  3. 烙铁使用规范】—— 烙铁头使用及保养
  4. spring boot实现导出数据到excel
  5. tp5模板 使用php代码,thinkPHP的Html模板标签使用方法
  6. 神经网络如何学习的?
  7. Intersection - POJ 1410(线段与矩形是否相交)
  8. Oracle触发器6-管理触发器
  9. 熬夜整理出40张可视化大屏模板,不敲一个代码就能直接套用
  10. python发送邮件的模块_python Email 邮件发送模块
  11. 原生新版仿微信 即时通讯聊天源码(附教程)
  12. 计算机怎么接入外接键盘,如何在笔记本电脑上设置外接键盘? [详细信息]
  13. 《Excel 小技巧》之 一个单元格换行显示日期和星期
  14. 关于图片或者文件在数据库的存储方式归纳
  15. 用Aria2来替换迅雷
  16. 等保三全面安全检查表_全面的安全方法
  17. 今日恐慌与贪婪指数为23,恐慌程度有所下降
  18. 职场历练【管理学之三】
  19. VC6 SP6下载地址
  20. 人工智能在自动驾驶深度学习中的应用

热门文章

  1. 凯撒密码matlab转换,教你如何简单使用凯撒密码 详细始末
  2. 商汤物语:全球最大AI独角兽的雄心与优雅
  3. 主流强化学习算法论文综述:DQN、DDPG、TRPO、A3C、PPO、SAC、TD3
  4. OrCAD设计原理图
  5. 2、认识常见网络设备
  6. 浅谈计算机辅助数学教学论文,数学教师论文,关于计算机辅助数学教学的原则方式相关参考文献资料-免费论文范文...
  7. python java爬虫_java爬虫与python爬虫对比
  8. JDBC Java数据库编程
  9. 宋森安——CHARLS中国健康与养老调查数据清洗(一)
  10. python大数据基础学习环境变量_《Python大数据基础与实战》[56M]百度网盘pdf下载...