从技术的角度剖析Nginx框架


众所周知,nginx 性能高,而 nginx 的高性能与其架构是分不开的。

1、nginx 多进程模式架构

nginx 启动后,会有一个master 进程和多个 worker 进程。

master 进程用来管理 worker 进程,功能包含:接收来自外界的信号,向各个worker 进程发送信号,监控woker进程的运行状态。

当worker 进程退出(异常退出),会自动重启启动新的worker 进程。

worker 进程:处理基本的网络事件。多个worker 进程之间对等。同等竞争来自客户端的请求,各进程独立。每个请求只能在一个worker 进程中处理,每个进程不会处理其他进程请求。

worker的个数可以设置,一般设置为cpu核数一致。


在这里插入图片描述


2、nginx 多进程模型的优势

那么,nginx 采用这种进程模型有什么好处呢?

  • 首先,对于每个 worker 进程来说,独立的进程,不需要加锁,所以省掉了锁带来的开销,同时在编程以及问题查上时,也会方便很多。
  • 其次,采用独立的进程,可以让互相之间不会影响,一个进程退出后,其它进程还在工作,服务不会中断,master 进程则很快重新启动新的 worker 进程,降低了风险。

3、worker 进程处理请求流程

nginx 在 0.8 版本之后,引入了一系列命令行参数,来方便我们管理。

例如:

重启 nginx:

./nginx -s reload   

停止 nginx:

./nginx-s stop

我们执行命令时,启动了一个新的 nqinx 进程,新的 nginx 进程在解析到reload 参数后,就控制 nginx 重新加载配置文件,它会向 master 进程发送信号。


那么worker 进程又是如何处理请求的呢?

假如:我们提供 80 端口的 http 服务,一个连接请求过来,每个进程都有可能处理这个连接,怎么做到的呢?

首先,在 master 进程里面,先建立好需要 listen 的 socket ,然后再 fork 出多个 worker 进程。

这样每个 worker 进程都可以去 accept 这个 socket (每个进程的socket 会监控在同一个 ip 地址与端口,这个在网络协议里面是允许的)。

当一个连接进来后,所有在 accept 在这个 socket 上面的进程,都会收到通知,而只有一个进程可以accept 这个连接,其它的则 accept 失败,这是所谓的惊群现象。


nginx 是怎么来解决惊群现象呢?

nginx提供了一个 accept mutex,从名字上,我们可以知道这是一个加在 accept 上的共享锁。同一时刻,就只会有一个进程在 accpet 连接。accept mutex 是一个可控选项,默认是打开,我们可以显示地关掉。

当一个 worker 进程在 accept 这个连接之后,就开始读取请求,解析请求,处理请求,产生数据后,再返回给客户端,最后才断开连接,这就是一个完整的请求。

由此正如前面所说:一个请求,完全由 worker 进程来处理,而且只在一个 worker 进程中处理。


4、nginx如何处理事件?

上面说了很多关干的进程模型,接下来,我们来看看 nginx的是如何处理事件的。

可能有人会问:nginx 采用多 worker 的方式来处理请求,每个 worker 里面只有一个主线程,那高并发处理怎么做到的?

nginx非常高明,采用了异步非阻塞的方式来处理请求,可以同时处理成千上万个请求


nginx 异步非阻塞到底是怎么回事呢?

前面所说,请求的完整过程如下:

首先,请求过来,要建立连接,然后再接收数据,接收数据后,再发送数据。

具体到系统底层,就是读写事件,而当读写事件没有准备好时,必然不可操作。

如果不用非阻塞的方式来调用,那就得阻塞调用,事件没有准备好,那就只能等了,等事件准备好了,再继续。阻塞调用会进入内核等待,cpu 利用率自然上不去了,更别谈高并发了。在 nginx 里面,最忌讳阻寒的系统调用。不要阻塞那就非阻塞。非阻塞就是,事件没有准备好,马上返回 EAGAIN,告诉你,事件还没准备好,过会再来。过一会,再来检查一下事件,直到事件准备好了为止,在这期间,可以先去做其它事情,然后再来看看事件好了没。

虽然不阻塞了,但你得不时地过来检査一下事件的状态,你可以做更多的事情了,但带来的开销也是不小的。

所以,才会有了异步非阻塞的事件处理机制

异步非阻塞的事件处理机制,具体到系统调用就是像 selectpoll/epoll/kgueue 这样的系统调用 ,可以同时监控多个事件,调用他们是阻塞的,但可以设置超时时间,在超时时间之内,如果有事件准备好了,就返回。


这种机制正好解决了我们上面的两个问题。

以epoll 为例 ,当事件没准备好时,放到epoll 里面,事件准备好了,我们就去读写,当读写返回 EAGAIN 时,我们将它再次加入到 epoll 里面。这样,只要有事件准备好了,我们就去处理它,只有当所有事件都没准备好时,才在 epol 里面等着。这样,我们就可以并发处理大量的并发。


当然,这里的并发请求,是指未处理完的请求,线程只有一个,所以同时能处理的请求只有一个,只是在请求间进行不断地切换而已,切换也是因为异步事件未准备好,而主动让出。这里的切换是没有任何代价,可以理解为循环处理多个准备好的事件。

与多线程相比,这种事件处理方式是有很大的优势的,不需要创建线程,每个请求占用的内存也很少,没有上下文切换,事件处理非常的轻量级。并发数再多也不会导致无谓的资源浪费(上下文切换)。更多的并发数,只是会占用更多的内存而已。


有人对连接数进行过测试,在 24G 内存的机器上,处理的并发请求数达到过 200万。

这也是 nginx 性能高效的主要原因。


我们之前说过,推荐设置 worker 的个数为 cpu 的核数,在这里就很容易理解了,过多的 worker 数,只会导致进程来竞争 cpu 资源,从而带来不必要的上下文切换。


而且,nginx为了更好的利用多核特性,提供了cpu 亲缘性的绑定选项,我们可以将某一个进程绑定在某一个核上,这样就不会因为进程的切换带来 cache 的失效。


像这种小的优化在 nginx 中非常常见,同时也说明了 nginx 作者在性能优化上的深厚造诣。比如,nginx 在做 4个字节的字符串比较时,会将 4个字符转换成一个 int 型,再作比较,以减少 cpu 的指令数等等。

至此,相信大家应该都清楚 nginx 什么会选择这样的进程模型与事件模型了吧~


5、nginx如何处理信号与定时器?


对于一个 web 服务器来说,事件通常有三种类型,网络事件、信号、定时器。通过上面的讲解,网络事件通过异步非阻塞事件机制可以很好的解决掉。


(1)、nginx如何处理信号

首先,信号的处理。对nginx 来说,有一些特定的信号,代表着特定的意义。信号会中断掉程序当前的运行在改变状态后,继续执行。如果是系统调用,则可能会导致系统调用的失败,需要重入。

对于 nginx来说,如果nginx 正在等待事件(epoll wait 时),如果程序收到信号,在信号处理函数处理完后,epoll wait 会返回错误,然后程序可再次进入 epoll wait 调用。


(2)、nginx如何处理定时器

我们再来看看定时器。

由于 epoll wait 等函数在调用的时候,可以设置一个超时时间,所以 nginx 借助这个超时时间来实现定时器。

nginx里面的定时器事件是放在一个最小堆里面,每次在进入 epoll wait 前,先从最小堆里面拿到所有定时器事件的最小时间,在计算出 epoll wait 的超时时间后进入 epoll wait。

所以,当没有事件产生,也没有中断信号时,epoll wait 会超时,也就是说,定时器事件到了。这时,nginx 会检查所有的超时事件,将他们的状态设置为超时,然后再去处理网络事件。

由此可以看出,当我们写 nginx 代码时,在处理网络事件的回调函数时,通常做的第一个事情就是判断超时,然后再去处理网络事件。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/654407.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

智能跳绳的产品体验与思考(一)

我,虽称不上跳绳高手,却对这项运动怀有深厚的热爱,也曾在某电商平台上选购过一款智能跳绳,希望能借此提升我的跳绳技巧。今天,咱们就来聊聊我和这条绳子的发生的一些故事,外加我的一些思考。 此刻&#xf…

如何利用 Selenium 对已打开的浏览器进行爬虫

大家好! 在对某些网站进行爬虫时,如果该网站做了限制,必须完成登录才能展示数据,而且只能通过短信验证码才能登录 这时候,我们可以通过一个已经开启的浏览器完成登录,然后利用程序继续操作这个浏览器&…

K8s集群中的Pod调度约束亲和性与反亲和性

前言 在 K8s 集群管理中,Pod 的调度约束——亲和性(Affinity)与反亲和性(Anti-Affinity)这两种机制允许管理员精细控制 Pod 在集群内的分布方式,以适应多样化的业务需求和运维策略。本篇将介绍 K8s 集群中…

BookxNote Pro 宝藏 PDF 笔记软件

一、简介 1、BookxNote Pro 是一款专为电子书阅读和学习笔记设计的软件,支持多种电子书格式,如PDF和EPUB,能够帮助用户高效地管理和阅读电子书籍,同时具备强大的笔记功能,允许用户对书籍内容进行标注、摘录和思维导图绘…

Shell编程中的循环语句和函数

一、for循环语句 当面对各种列表重复任务时,使用简单的if语句已经难以满足需求,这时就需要for循环语句。for语句的结构为: for 变量 in 取值列表 do 命令序列 done 使用for循环语句时,需要指定一个变量及取值列表,针对…

【经验分享】可视化的项目管理,轻松解决资源冲突和协作困难

在数字化时代,高效协同逐步成为提升组织效能的重要着力点,同时也是企业保持竞争力、实现持续发展的关键要素。一方面可以打破部门壁垒,促进信息流通,从而提升整体工作效率;另一方面还能帮助企业优化资源配置和管理流程…

快团团帮卖团长怎么对供货大团长进行评分?

都说帮卖“躺赚”? 一旦遇团不淑,惨遭不靠谱团长挖坑,售后拖延、发货慢、产品瑕疵…… 加上顾客夺命连环催,双面夹击,夹缝生存。供货团长靠不靠谱太重要了! 快团团供货团长评分系统上线! 帮卖团…

什么是erp仓储管理系统?ERP系统的价值体现在哪些方面?

ERP仓储管理系统是一个帮助企业管理仓库的工具。想象一下,如果你是一个仓库管理员,里面堆满了各种各样的产品和货物,如何确保这些产品数量准确、摆放有序,以及快速找到自己需要的产品呢? 这时,如果企业引用…

GitLab项目中添加用户,并设置其角色权限等

注意:创建用户(new user),创建完用户然后再项目邀请用户,选择创建过的用户 一、以管理员身份登录GitLab的WebUI并创建用户 1>.使用管理员登录GitLab 使用管理员(root)用户登录成功后,点击如下图所示的小扳手,点击…

NameSilo + Cloudflare 给网站加个域名(附 NameSilo 购买域名优惠码)

网站做好了之后,下一步就是买域名 在国内买域名的话,还需要备案,个人名下备案好像是还有限制,我就去 NameSilo 上面买的 在买之前,对比过几家 比如: godaddy/namecheap/cloudflare 本来是倾向于在 godaddy 上面买的,因为它支持支付宝支付,但是在详细看的时候,发现如果购买一年…

CLIP 源码分析:simple_tokenizer.py

tokenizer的含义 from .clip import *引入头文件时为什么有个. 正文 import gzip import html import os from functools import lru_cacheimport ftfy import regex as re# 上面的都是头文件# 这段代码定义了一个函数 default_bpe(),它使用了装饰器 lru_cache()。…

vue 笔记02

目录 01 事件修饰符 02 按键修饰符 03 v-bind属性 04 vue-axios的基本使用 05 vue的生命周期 06 vue生命周期涉及到的其他的知识点 01 事件修饰符 vue的事件修饰符 事件名称.修饰符1.修饰符2...事件驱动函数 stop 阻止冒泡修饰符 prevent 阻止默认行为 once 当前事件只触…

嵌入式学习记录5.18(多点通信)

一、套接字属性设置相关函数 #include <sys/types.h> /* See NOTES */#include <sys/socket.h>int getsockopt(int sockfd, int level, int optname,void *optval, socklen_t *optlen);int setsockopt(int sockfd, int level, int optname,const void *op…

vue3学习(三)

前言 继续接上一篇笔记&#xff0c;继续学习的vue的组件化知识&#xff0c;可能需要分2个小节记录。前端大佬请忽略&#xff0c;也可以留下大家的鼓励&#xff0c;感恩&#xff01; 一、理解组件化 二、组件化知识 1、先上知识点&#xff1a; 2、示例代码 App.vue (主页面) …

人类和小鼠转录组上游分析

基础软件 conda install cutadapt, trimmomatic, samtools, hisat2, subread, deeptools -y人类转录组上游分析 # 样本名称 sample_namesample# 线程 threads4# 双端测序原始fastq1和fastq2路径 fastq1_path/path/${sample_name}_1.fq.gz fastq2_path/path/${sample_name}_2.…

SRS视频服务器应用研究

1.SRS尝试从源码编译启动 1.1.安装ubuntu 下载镜像文件 使用VMWare安装&#xff0c;过程中出现蓝屏&#xff0c;后将VM的软件版本从15.5升级到17&#xff0c;就正常了。

WPS PPT学习笔记 2 结构页的制作

制作PPT结构页 制作封面页、目录页、封底页。它们都属于结构页。而时间轴页&#xff0c;流程图页&#xff0c;框架图页这些属于内容页。 做一份PPT 讲一个故事 封面页 开头&#xff0c; 目录页 脉络&#xff0c; 各式内容页 详情&#xff0c; 封底页 结尾。 所有的结构页…

Linux系统编程学习笔记

1 前言 1.1 环境 平台&#xff1a;uabntu20.04 工具&#xff1a;vim,gcc,make 1.2 GCC Linux系统下的GCC&#xff08;GNU Compiler Collection&#xff09;是GNU推出的功能强大、性能优越的多平台编译器&#xff0c;是GNU的代表作品之一。gcc是可以在多种硬体平台上编译出可执…

【自用题库】2024/华三/H3CNE安全GB0-510

【网工必备】华三H3CNE-安全-510 题库覆盖百分百&#xff0c;题库有291道总结汇总 还有vce加vce文件模拟真实考试环境 到手文件夹5样东西&#xff01;&#xff01;&#xff01; 认证简介&#xff1a;H3CNE-Security&#xff08;H3C Certified Network Engineer For Security&am…

Dubbo生态之深度分析sentinel的流量控制

1. 深度了解sentinel限流规则参数的含义 博客Dubbo生态之sentinel限流-CSDN博客中有dubbo集成sentinel的demo演示 在sentinel中&#xff0c;限流的直接表现形式就是&#xff0c;在执行Entry nodeA SphU.entry(resourceName)的时候抛出FlowException异常&#xff0c;FlowExce…