简明入门讲义——NGINX 为何这么快

Posted FesonX

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了简明入门讲义——NGINX 为何这么快相关的知识,希望对你有一定的参考价值。

概览

NGINX 是战斗民族主导的一个服务端软件,主要充当负载均衡器和反向代理

nginx 进程角色

一个 NGINX 主要由 Master 进程和一系列子进程组成,主进程负责配置读取和重新加载、绑定端口以及子进程的管理
子进程有三种角色

  • **缓存加载器(Cache loader)**负责将磁盘缓存加载到共享内存。此进程按计划执行,用完即销毁,占用资源较少
  • **缓存管理器(Cache Manager)**负责清除磁盘缓存条目,保证缓存在配置的大小范围内。此进程定期执行。
  • Worker,真正负责处理请求的进程。默认情况下,每个 CPU 核心一个 Worker,Worker 以非阻塞式(Non-Blocking)、事件驱动(Event-Driven)式单线程独立运行,通过共享内存共享缓存数据、持久会话(Persistent Session)和其他资源。

Worker 有一系列的 socket 监听,由用户的连接所实例化,连接会被分配到 HTTP 状态机或 TCP 流状态机、SMTP 状态机。

Worker 如何做到单线程以一敌百

NGINX 将 Worker 处理请求的过程比作棋手对弈,Web 服务器是棋圣,需要和很多连接请求菜鸡博弈,中间的 IP 拦截、认证、限流等属于本次对弈的规则或者称为一次落子,可以扩展其他规则,这些规则可能来自上游服务器。

传统的阻塞式多进程 Web 服务器,一个进程即一个 Worker,一次只能处理一个连接,工作流简单,易于扩展第三方模块。然而,带来了资源的极大不平衡——轻量的 HTTP 连接在系统中不过是一个内存占用极低的文件描述符,却独占整个线程或进程。
这与传统的一对一博弈并无二致,作为棋圣的你也不得不等待菜鸡漫长的思考落子,才可以执行下一步。极大地影响你升级打怪的速度,一天也战胜不了几个人。

棋圣们也意识到以这种方式跟段位不匹配的棋手对弈效率太低,于是就有了车轮战或者多面打Simultaneous Exhibition)棋圣在棋盘落子后就可以马上跟另一位棋手对弈了。上图的棋圣 Kiril Georgiev 在 09 年同时与 360 位棋手对弈,他的最终成绩是284胜70平6负。

没错,NGINX 的 Worker 就是这么玩的,多面打中的棋圣还要自己走过去跟棋手博弈,而 NGINX 则更高效,只需要在连接进场的时候开一个 socket 监听器,连接的每个状态都会触发事件,Worker 根据事件处理即可,这就是所谓的事件驱动

由于是单线程,少了传统阻塞式多进程服务器切换进程和线程的上下文开销,如此便实现了一个 Worker 同时处理多达上百个连接的能力。如果你对单线程并发处理感兴趣,还可以看看 javascript 的 Promise。

热修改配置是如何实现的

nginx -s reload 这个热重载配置命令相应后端开发工程师都不会陌生。回顾前文的 NGINX 进程模型,有这样一个充当管理者角色的 Master 进程。当 nginx -s reload 命令执行时,程序先检查磁盘上的配置是否有效,然后向 Master 进程发送 SIGHUP (Signal Hang up 的缩写,即挂断信号,Linux 上的 nohup 命令会忽略这个信号)

Master 收到 SIGUP 后会重新读取配置,并 Fork 出一系列新的 worker 进程,新的 Worker 进程随即读取新的配置接收连接处理请求。Master 进程随后发送 TERM 信号给旧的进程通知优雅退出(Gracefully exit)—— 即让旧进程处理完剩余的请求后就关闭连接,一旦所有连接关闭,旧 Worker 随之退出。

这个设计并非独有,例如 Python 的 WSGI 服务器 Gunicorn,它的 Master 进程也是通过 SIGUP 这个信号量重载配置的,当你对比二者的其他信号量处理,例如 USR1 重新打开日志文件、USR2 在线升级等等,那更是惊人的雷同…这里不是在批评抄袭,而是想表达信号量处理这种方式已经广受验证,你也可以考虑在自己的软件上加上这种设计!

参考文档

  1. Controlling nginx
  2. Simultaneous exhibition - Wikipedia
  3. Inside NGINX: How We Designed for Performance & Scale
  4. Gunicorn - Signal Handling

WeChat Official Account: 程序员的碎碎念

以上是关于简明入门讲义——NGINX 为何这么快的主要内容,如果未能解决你的问题,请参考以下文章

简明入门讲义——NGINX 为何这么快

简明入门讲义——一文理清负载均衡和反向代理

简明入门讲义——DNS架构是如何发展的

简明入门讲义——如何实现可扩展的 Web 服务

简明入门讲义——一文理清负载均衡和反向代理

简明入门讲义——一文理清负载均衡和反向代理