深度学习Nginx第三章:Nginx请求流程和进程结构

        学习这方面知识主要解决问题:Nginx一般部署在内网边缘节点,它处理的流量一般比其他应用服务器流量数倍或者数个流量级别,所以在Nginx处理问题,所有问题都会被放大,所以我们要了解为什么要使用master和worker这种架构模型,并且worker必须要和cpu的核数所匹配,当我们在多个worker进程之间共享数据时,为什么在tls或者说限流、限速这些场景共享方式是有所不同的

 

Nginx请求处理流程

   

     当流量进入nginx,主要有三种状态机,第一个是处理tcp、udp的四层传输层的,还有处理http应用层的,以及处理邮件的,因为ningx是使用非阻塞的事件驱动处理引擎,为什么叫状态机,是因为这个绿色的框是使用非阻塞的事件驱动处理引擎(epoll),一旦我们使用异步的这种处理,都是使用状态机识别和处理的

    另外当我们进行静态资源磁盘缓存的时候,如果整个文件不足以缓存住的时候,像 sendfile这种调用,或者AIO会退化成阻塞的磁盘调用,所以使用线程池来进行处理磁盘阻塞调用,处理完成的请求记录access日志或者错误日志

Nginx结构

    nginx有两种进程结构,单进程结构和多进程结构,前者不适用生产环境,无法用到多核的特性,默认配置打开多进程。会有一个master进程,会有很多子进程,一类是worker进程,一类是cache相关进程,master进程设计出来是主要对worker进程进行监控管理的,看需不需要热部署,是否需要重新载入配置文件,worker进程是真正对请求进行处理的,缓存是要在多个worker进程间进行共享的,而且缓存不仅被worker进程使用还要被cache manager和cache loader所使用,这两个也是为反向代理时,后端发出的动态请求做缓存进行处理的,前者是缓存的管理,后者是缓存的载入,这些进程间的通信使用共享内存来使用的,父子进程间是使用信号进行管理的

为什么Nginx采用的是多进程结构,而不是多线程结构?

 这是根据Nginx最核心的一个目的,nginx要保证它的高可用性和高可靠性,当Nginx采用多线程的时候,因为线程之间共享同一个地址空间的,当某一个第三方模块导致地址空间段错误时,可能会导致Nginx的线程全部挂掉,而我们采用多进程的时候,进程间不会共享地址空间就不会出现这个事情

为什么worker进程会很多?

这是因为Nginx采用事件驱动模型,一个worker进程从头到尾占用一个cpu,我们不仅配置worker和cpu数量进行一致外还需要把worker和cpu绑定在一起,这样可以更好使用cpu核上的cpu缓存,这样减少缓存失效的命中率

使用信号管理Nginx的父子进程:通常进程间的通信使用共享内存和信号,而进程间的管理是使用的是信号

   其中能够发送和处理信号的有Master进程、Worker进程、Nginx命令行,其中master进程进行对worker进行监控和管理,当worker因为一些模块bug等意外挂掉的时候会给master进程发送CHLD信号,然后master进程进行拉起一个新的worker进程,master进程还可以通过接受信号来进行管理worker进程,其中USR1是重新打开日志文件做日志文件切割、HUP重新载入等等,其中前四个是可以通过Nginx命令行加特定的命令来实现的,而后两个做日志的热部署,是通过使用kill直接向master进程进行发送信号,通过对pid来执行USR2和WINCH,主要是对热部署进行执行,worker也可以进行接收信号,但是平常不是对worker进程直接发送信号,而是对master进程进行发送信号来管理worker进程

   当我们启动Nginx的时候,通常我们会把pid记录到默认目录下,Nginx安装目录下的文件中,那个Pid文件会记录master进程的pid,这个时候我们执行nginx -s 这样的命令时候,nginx会读取master进程的pid,根据pid像master进程发送HUP、等信号,这些信号对应我们命令,所以我们调用nginx命令和直接kill 使用他们的信号是一样的 SIGHUP等 例如:kill -SIGHUP 进程号 、kill -SIGTERM woker进程pid

reload重载配置文件

在不停止服务的情况下,平滑的把Nginx旧的config更新到新的config

 说明:从第二步我们可以知道不一定非要在nginx -reload之前执行 - t 检验一下语法是否正确,因为在第二部的时候一定会做这件事,情,master会打开新的端口是因为我们如果在nginx,config中引入了新的端口比如443等,所有woker进程是master进程的子进程,所有的子进程会继承父进程打开的端口,这个是nginx操作系统所定义的,因为平滑,所以要新起子进程然后在给老的worker子进程发送QUIT信号

如果有些请求出问题,客户端长时间没有处理,长时间占用在worker进程上面,因为新的连接是跑在黄色worker进程上面,所以影响不大,唯一导致绿色子进程长时间存在,解决办法是nginx新的版本中存在一个配置项,woker_shutdown_timeout最长等多长时间,定时器,到了时间强制退出

热升级完整流程

     在进行升级过程中还存在很多问题,比如老的worker进程退不掉,新的worker升级后出现新的问题,需要回滚,我们升级后可能存在指向的配置文件出现问题,具体操作

在第二步的时候没有直接执行命令是因为nginx目前没有这样的信号,master进程执行 3、4。新的master进程是老的master进程的子进程,怎么找到老的master进程发送信号,我们通过ps -ef找到老的master进程,然后发送QUIT信号,但是老的master进程一直保存下来,就是方便我们回滚

 worker进程:如何优雅的关闭

     优雅的关闭时只对worker进程的,因为处理的请求的是worker进程,如果直接关闭woker进程,可能导致用户请求的时候返回一个错误。worker进程可以识别出当前是否有连接请求,这个时候把连接关闭,nginx对于有些请求是做不到这一点的,比如nginx代理 1、 websockt协议的时候,在websocket的数据帧的时候(WebSocket真正麻烦的地方是在数据的传输上!为了环保,它使用了特定格式的数据帧,这个数据帧需要自己去解析,当然也有别人编写好的库可以用。虽然官方文档描述的很详细,但是看起来还是蛋疼),nginx是不解析的,2、nginx作为tcp层或者udp层的反向代理时候是无法分辨出一个请求是需要经历多少报文才算结束,但是对于http请求是可以做到。

    关闭流程1、设置定时器(worker_shutdown_timeout)、2、关闭监听句柄(保证woker进程不会处理新的连接了)、3、关闭空闲连接(先去看连接处,因为nginx为了保证自己的对资源利用是最大化的,经常保存一些空闲的链接,但是没有断开)、4、再循环中等待全部链接关闭(时间较长,可能超过worker_shutdown_timeout,如果超过,直接关闭)、5、退出进程

发布了83 篇原创文章 · 获赞 87 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/ligupeng7929/article/details/99288841