Nginx在web开发者眼中就是高并发高性能的代名词,其基于事件的架构也被众多开发者效仿。我从Nginx的网站找到一篇技术文章将Nginx是怎样实现的,文章是Nginx的产品老大Owen

Garrett在加入公司22个月时写的,深入简出。这篇博客后面的内容尽量保证是对原文的翻译,如果有个人理解或者延伸阅读我会加标“译注”。原文地址Inside NGINX: How We Designed for Performance & Scale(https://www.nginx.com/blog/inside-nginx-how-we-designed-for-performance-scale/)

Nginx强劲的高性能表现来自其合理的软件设计。传统的web服务器和应用服务器架构设计上采用多进程或线程作为其处理业务的基本单位,而Nginx更多的使用了事件驱动的架构。正是这种架构使得Nginx可以轻松支持数十万的并发链接。【译注:Nginx相比其他的web服务器使用了更少的进程,将IO事件集中在固定的进程内处理,减少了很多系统开销,可以从下文理解到。】

The Inside NGINX infographic 较为清晰的讲诉了Nginx如何在一个进程内处理并发链接,下面我们深入看一下细节。

Nginx进程模型

在讲设计实现之前,有必要先看一下Ngxin如何在linux之上运行的。Nginx启动会创建一个主进程(主管进程,负责读取配置、绑定端口、管理其他子进程)和一些worker进程和辅助进程。

这个示例运行在4核的server上,Nginx主进程创建4个worker进程和2个cahce辅助进程。

为什么架构很重要?

Unix应用程序的基本要素是进程或者线程。(Linux OS调度不区分进程还是线程,二者的最大区别在于它们对于memory的共享程度。)进程或线程是一个自包含的可以独立运行的任务,OS可以调度它到某个CPU核上执行。有很多复杂的应用程序运行在多进程或线程模式下是基于以下两点考虑:

可以使用更多CPU资源。【译注:还有memory、IO等其他资源】

可以轻松做到并行处理(比如,同时处理多个链接)。

进程和线程都会消耗资源,需要占用memory和其他OS资源,并且在运行时还有context switch的系统开销。一般的server可以负担几百数量级的进程或者线程,当进程或线程数量继续上升到更高的数量级,memory消耗和IO阻塞引起的系统负荷会很高,使得应用程序运行比较低效。

在设计网络程序时,开发者会很自然的设计成每个进程或线程处理一个网络连接。这种架构比较简单容易实现,但是比较难以扩展,尤其是当网络连接增长到上千以后。

Nginx怎样工作的?

Nginx可配置数量的进程,推荐配置数量和CPU的核数量相当:

主进程读配置,绑定端口,然后启动一定数量的子进程。

cache loader子进程在启动的时候运行,负责把硬盘上的数据搬进内存,然后就退出了。因为它是一次性的任务,系统开销很小。

cahce manager子进程启动后监控维护cache区。

worker子进程是真正处理业务的进程,负责处理网络连接,读写硬盘,跟上游server交互等等。

Nginx推荐配置worker的数量跟CPU核数量线性关系,每个CPU核运行一个worker进程。可以通过配置 worker_processes auto来使用该推荐设置。

当Nginx server处理业务时,worker进程们是最繁忙的,每个worker通过非阻塞的IO复用方式处理很多连接,尽量减少不必要的上下文切换。

每个worker进程都是单线程的进程,接收连接上的request并处理后回应。进程间可以通过共享内存的方式进行进程间通信。

Nginx worker进程

每个Nginx worker进程由主进程读取配置创建,通过accept_mutex竞争获得要listen的socket并加入自己的IO监听列表中。

每来一个新的连接都会触发新的事件,这些事件送给worker内的状态机来处理。(Nginx支持各种类型的状态机,如http/tcp/SMTP/IMAP/POP3等)。大部分的web server逻辑上都有这样的状态机,只是实现方式不一样。

状态机调度

我们可以想象类比状态机是象棋游戏的规则。每个HTTP transaction(译注:一组的Http请求,可以对应成某个socket上发生的所有http请求)就是一个象棋游戏。对弈的一方是web server,可以类比为象棋大师。另一方为client,类比为象棋爱好者。

游戏的规则可以很复杂,比如web server需要跟其他application沟通协作完成业务处理,第三方的nginx模块甚至可以扩展规则。

阻塞式状态机

大多数的web服务器和应用程序使用每个连接对应一个进程或线程的模式来玩象棋游戏。每个进程或线程给一个client完成对弈直到游戏结束。在整个过程中,进程大部分时间都是处在阻塞状态--等待client完成下一步走棋。

web服务器主进程在服务端口上监听新的连接(客户端发起的新游戏的请求)。

有新的游戏请求时,主进程创建子进程负责完成跟客户端的对弈。主进程继续监听服务端口。

当游戏结束时,子进程要么等待client开始新游戏(通过keepalive机制保活一段时间连接)要么退出(keepalive超时后)。

这种模型每玩一局server都要创建一个对应的进程来完成对弈。这种架构简单并且容易容易扩展新功能,但有些大炮打蚊子,杀鸡用牛刀的感觉。进程是个重器,系统开销比较大,而解决的问题是个轻量级的问题。容易编程实现但是浪费比较大。

Nginx才是真正的并发大师

你可能听说过一人同时对战多人的象棋大赛

这就是Nginx worker进程的工作方式。每个worker进程(一般每个CPU核有一个worker进程)都是一个象棋大师,可以同时对弈数十万对手。

worker进程等待listen和connection sockets的事件。(译注:listen socket就是server用来监听新建连接的socket,connection socket是accept系统调用返回的新建socket,详细可参加accept的手册)

事件发生后,worker进程来处理这些事件:

listen socket的事件表示有新的客户端要开始新的游戏。worker通过accept()创建新的connection socket,并加入监听列表。

connection socket的事件表示客户端走了一步棋,worker进程可以做下一步应对。

worker进程从不会在网络IO上阻塞,当它应对完客户端的走棋走出自己的一步后,可以马上应对下一个客户端的走棋或接收新的连接请求。

为什么这样做比阻塞式的多进程架构更快?

Nginx的worker进程很容易扩展支持数十万并发连接。每个新接入的连接只需要创建新的socket消耗少量的内存,每个连接的系统开销相对要比进程开销小很多。另外通过Nginx worker进程绑定CPU技术可以进一步减少上下文切换和cache失效等系统开销。

而阻塞式每个进程服务一个连接的方式,每个连接都会消耗很多资源,而且进程切换比较频繁导致系统开销比较大。

更详细的解释,可以参考这篇文章--Nginx架构,作者是Ngxin的VP和共同创始人,Andrew Alexeev.

更新配置和升级Nginx

Nginx的这种少量进程的架构使得更新配置和升级Nginx版本很容易。

更新Ngxin配置是一件非常容易事情而且非常可靠。很简单的nginx -s reload就搞定了。运行这个命令实际上是给Nginx主进程发送了一个SIGHUP的信号,主进程收到该信号后做了两件事情:

重新加载配置并且根据新的配置创建一组新的worker进程,这些新的进程可以马上开始干活。

通知老的worker进程优雅地退出。

重新装载的过程会引起短暂的CPU和内存的使用高峰,但这种影响总体来说比较微小,你甚至可以每秒多次做这个操作。

Nginx程序的升级就更加漂亮了,根本不会影响正在处理的连接,轻轻松松升级完成用户根本没有感觉。

Ngxin程序升级跟更新配置相似。启动新的Nginx主进程,它会跟旧的主进程共享listen sockets。新的进程起来后,你可以发送信号给旧的进程退出。详细过程可以参看Controlling Nginx(http://nginx.org/en/docs/control.html).

总结

The Inside NGINX infographic描述了Nginx的整体功能,其实它概括性描述的背后是Nginx开发人员十几年的创新和优化。如果你想了解更多,可以参看这些材料:

Installing and Tuning Nginx for Performance(https://www.nginx.com/resources/webinars/installing-tuning-nginx/)

Tuning Nginx for Performance(https://www.nginx.com/blog/tuning-nginx/)

The Architecture of Open Source Applications – NGINX(http://www.aosabook.org/en/nginx.html)

Socket Sharding in NGINX Release 1.9.1 (using the SO_REUSEPORT socket option)(https://www.nginx.com/blog/socket-sharding-nginx-release-1-9-1/)

原文地址:https://www.nginx.com/blog/inside-nginx-how-we-designed-for-performance-scale/

译文来源:SegmentFault

Nginx实现内参:为什么架构很重要?的更多相关文章

  1. 浅谈 Nginx 的内部核心架构设计

    一.前言 Nginx---Ngine X,是一款免费的.自由的.开源的.高性能HTTP服务器和反向代理服务器:也是一个IMAP.POP3.SMTP代理服务器:Nginx以其高性能.稳定性.丰富的功能. ...

  2. 初探Nginx服务器的整体架构

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

  3. 从 Nginx 优秀的核心架构设计,揭秘其为何能支持高并发?

    目录: 1. Nginx的整体架构 2. Nginx的模块化设计 3. Nginx的请求方式处理 4. Nginx事件驱动模型 5. Nginx进程处理模型 写在前面 Nginx 是一个 免费的,开源 ...

  4. 企业Nginx+Keepalived双主架构案例实战

    通过上一次课程的学习,我们知道Nginx+keepalived主从配置,始终有一台服务器处于空余状态,那如何更好的利用起来呢,我们需要借助Nginx+keepalived双主架构来实现,如下图通过改装 ...

  5. 构建企业级Nginx+Keepalived集群架构

    随着Nginx在国内的发展潮流,越来越多的互联网公司都在使用Nginx. Nginx高性能.稳定性成为IT人士青睐的http和反向代理服务器,今天我们来实战构建Nginx+Keepalived高可用架 ...

  6. LVS和nginx反向代理网站架构

    LVS和nginx反向代理网站架构 nginx反向代理和lvs的dr都存在单点,要keepalived做高可用,但是成本高了 f

  7. Ansible实战之Nginx代理Tomcat主机架构

    author:JevonWei 版权声明:原创作品 实验架构:一台nginx主机为后端两台tomcat主机的代理,并使用Ansible主机配置 实验环境 Nginx 172.16.252.82 Tom ...

  8. 企业级Nginx服务基础到架构优化详解

    1.隐藏nginx header版本号 2.更改源码隐藏软件名称 3.更改nginx默认用户及用户组 4.配置nginx worker进程个数 5.根据CPU核数进行nginx进程优化 6.nginx ...

  9. Azure环境中Nginx高可用性和部署架构设计

    前几篇文章介绍了Nginx的应用.动态路由.配置.在实际生产环境部署时,我们需要同时考虑Nginx的高可用性和部署架构. Nginx自身不支持集群以保证自身的高可用性,商业版本的Nginx+推荐: T ...

随机推荐

  1. 谈 IIS7.5 Asp.Net模拟用户

    IIS  Asp.模拟用户官方的解释是: 如果要在非默认安全上下文中运行 ASP.NET 应用程序,请使用 ASP.NET 模拟身份验证. 如果您对某个 ASP.NET 应用程序启用了模拟,那么该应用 ...

  2. css在各浏览器中的兼容问题

    CSS对浏览器的兼容性有时让人很头疼,或许当你了解当中的技巧跟原理,就会觉得也不是难事,从网上收集了IE7,6与Fireofx的兼容性处理方法并 整理了一下.对于web2.0的过度,请尽量用xhtml ...

  3. ui学习笔记---第十五天数据库

    数据库的使用 常见的数据库有MySQL       SQL Server       SQLite      Oralce等 在iOS开发中通常使用SQLite数据库,这是一个轻量级的数据库,可以在火 ...

  4. 腾讯优测干货精选| 安卓开发新技能Get -常用必备小工具汇总

    文/腾讯公司 陈江峰 优测小优有话说: 移动研发及测试干货哪里找?腾讯优测-优社区你值得拥有~ 开发同学们都知道,安卓开发路上会碰到很多艰难险阻,一不小心就被KO.这时候,没有新技能傍身怎么行?今天我 ...

  5. ZOJ 1047 Image Perimeters

    原题链接 题目大意:鼠标点击一块,求与之联通的所有区域的边长之和. 解法:广度优先搜索.从选中的这个点开始,往周围8个点依次搜索,访问过的点做上标记.如果该点上下左右的一个或多个方向没有相邻的点,边长 ...

  6. CSS控制文本自动换行

    1.你定死表格的宽度,即给表格一个宽度值(是数值,不是百分比) 2.强制不换行 div{ //white-space:不换行;normal 默认;nowrap强制在同一行内显示所有文本,直到文本结束或 ...

  7. Apache使用mod_deflate模块压缩页面优化传输速度

    可以写为一行,也可以写多行,默认为gzip SetOutputFilter DEFLATE # Restrict compression to these MIME types AddOutputFi ...

  8. 全国信息学奥林匹克联赛(NOIP2014)复赛 模拟题Day2 长乐一中

    题目名称 改造二叉树 数字对 交换 英文名称 binary pair swap 输入文件名 binary.in pair.in swap.in 输出文件名 binary.out pair.out sw ...

  9. FZU-2216 The Longest Straight (二分枚举)

    题目大意:给n个0~m之间的数,如果是0,那么0可以变为任意的一个1~m之间的一个数.从中选出若干个数,使构成一个连续的序列.问能构成的最长序列的长度为多少? 题目分析:枚举连续序列的起点,二分枚举二 ...

  10. [luogu P2170] 选学霸(并查集+dp)

    题目传送门:https://www.luogu.org/problem/show?pid=2170 题目描述 老师想从N名学生中选M人当学霸,但有K对人实力相当,如果实力相当的人中,一部分被选上,另一 ...