专栏首页程序员的碎碎念简明入门讲义——NGINX 为何这么快

简明入门讲义——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[1])棋圣在棋盘落子后就可以马上跟另一位棋手对弈了。上图的棋圣 Kiril Georgiev[2] 在 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[3]2.Simultaneous exhibition - Wikipedia[4]3.Inside NGINX: How We Designed for Performance & Scale[5]4.Gunicorn - Signal Handling[6]

References

[1] Simultaneous Exhibition: https://en.wikipedia.org/wiki/Simultaneous_exhibition [2] Kiril Georgiev: https://gambit.blogs.nytimes.com/2009/03/03/in-chess-records-were-made-to-be-broken/ [3] Controlling nginx: https://nginx.org/en/docs/control.html [4] Simultaneous exhibition - Wikipedia: https://en.wikipedia.org/wiki/Simultaneous_exhibition [5] Inside NGINX: How We Designed for Performance & Scale: https://www.nginx.com/blog/inside-nginx-how-we-designed-for-performance-scale/ [6] Gunicorn - Signal Handling: https://docs.gunicorn.org/en/latest/signals.html

本文分享自微信公众号 - 程序员的碎碎念(gh_53e607dd4782),作者:FesonX

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2021-06-06

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

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

    可扩展的应用服务器(Application Server)集群藏身于负载均衡器(Load balance,LB)背后,LB 将负载(即用户请求)平均地分配到各个...

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

    可扩展的应用服务器(Application Server)集群藏身于负载均衡器(Load balance,LB)背后,LB 将负载(即用户请求)平均地分配到各个...

    FesonX
  • Spring Boot入门系列(十)如何使用拦截器,一学就会!

    前面介绍了Spring Boot 如何整合定时任务已经Spring Boot 如何创建异步任务,不清楚的朋友可以看看之前的文章。

    架构师精进
  • 零基础到精通Linux,从这篇文章开始

    正好在最近,看到了一篇不错的资料,其中对于Linux入门学习的描述极其详尽,因此特别摘抄其中段落,制作成思维导图分享给大家。

    马哥linux运维
  • 八问WebSocket协议:为你快速解答WebSocket热门疑问

    WebSocket是一种比较新的协议,它是伴随着html5规范而生的,虽然还比较年轻,但大多主流浏览器都已经支持。它使用方面、应用广泛,已经渗透到前后端开发的各...

    JackJiang
  • 零基础到精通Linux,从这篇文章开始

    正好在最近,看到了一篇不错的资料,其中对于Linux入门学习的描述极其详尽,因此特别摘抄其中段落,制作成思维导图分享给大家。

    马哥教育
  • 自动化运维实践 | Ansible playbook重用

    playbook支持两种重用机制,一种是重用静态的单个playbook脚本,另外一种是重用实现特定功能的文件夹,类似于python等编程语言中的包。

    小土豆Yuki
  • Redis从入门到精通(三)Redis如何实现的主从架构

    接着上一篇,前面两篇我总结了Redis安装和C#中如何使用redis 。接下来讲讲Redis 的主从复制以及主从复制的架构下C#中如何调用。

    架构师精进
  • 八问WebSocket协议:为你快速解答WebSocket热门疑问

    WebSocket是一种比较新的协议,它是伴随着html5规范而生的,虽然还比较年轻,但大多主流浏览器都已经支持。它使用方面、应用广泛,已经渗透到前后端开发的各...

    JackJiang

扫码关注云+社区

领取腾讯云代金券