Nginx的框架设计—进程模型

在这之前,我们首先澄清几点事实:

nginx作为一个高性能server的特点。事实上这也是全部的高性能server的特点,依赖epoll系统调用的高效(高效是相对select/poll这些系统调用的,底层有一个链表和红黑树,避免了轮询,降低了用户空间和系统空间之间的数据传递等)。非堵塞(全部的操作都是非堵塞,这样)。多进程(master-slave进程模型),这些事实使得nginx成为一个高性能server的前提条件。

既然作为一个软件(httpserver),相对于一个网络库而言肯定有更完好的功能。它能够在不须要关闭的前提下实现更新系统;能够接受外部的信号,依据不同的信号做对应的处理;可定制。用户能够开发第三方的模块,依据自我须要将模块加入到7个处理阶段(HTTP请求本来是有11个阶段,可是当中的4个阶段是不支持加入用户自己定义的模块的)。它能够作为反向代理。它是能够支持高并发的。它的工作模式是基于配置文件的,一个配置文件决定了nginx的工作模式。配置文件解析完毕也就完毕了初始化的全部工作,配置文件的解析在nginx中占了举足轻重的地位。

基于上述几点事实慢慢阐述nginx的设计理念。

首选从大的框架说起。既然是多进程,那么怎样分配各个进程的任务,针对CPU的核数来开启进程数目(当然是否为多进程能够通过配置文件来配置的)。分为master-worker模型,master负责开启worker进程,master进程负责和worker进程通信,master进程负责接收外部的信号。master进程负责将某些信号(总共8个信号,可是相应着worker进程关注的三个变量。三个变量分别为ngx_quit/ngx_reopen/ngx_terminate等)传递给worker进程,所以worker进程是不须要关注外部信号的,master进程须要关注worker进程的工作情况。比方接受到了SIGCHLD信号。也就是worker进程退出。在须要避免worker进程成为僵尸进程外还须要检查worker进程是否是正常死亡,假设非正常死亡还须要重新启动这个worker进程。那么worker进程做了什么呢?进程间通信就这些么?

事实上master进程和worker进程时间是有通信,worker进程之间也是能够有通信的,仅仅只是这里没有通信。通信的方式是通过socketpair,也有共享内存。两者各有不同的作用。Worker做了什么呢!

负责监听,接受连接,接受完以后就负责和这个连接进程交互,直到这个连接终于结束。事实上进程模型到这里就已经结束了。仅仅不多worker进程怎么做就是还有一回事了。

以下从代码上来分析上面提到的一切:

在src/core/nginx.c中有入口Main函数,大体了解main函数都做了些什么。

1)、ngx_get_options函数是依据用户输入的參数来设置一些全局变量,比方用户输入了-s,那么就设置ngx_signal标志,这个标志说明用户须要给ngxin输入一个信号。诸如此类的全局变量。往下再依据全局变量再进行处理。

2)、接下来的if(ngx_show_version)就是在步骤1)来设置的。表示用户是否想看版本号信息。(当然这是第一个在ngx_get_options中被设置的全局变量)

3)ngx_time_init()函数设置了表示时间的初始化。函数中的最后一行ngx_time_update是一个非常重要的函数。是用来更新时间的函数,依据配置文件,决定了更新时间的方式。以后再讨论,因为每次调用gettimeofday()这个系统调用非常浪费时间,那么就须要一个时间缓存,更新时间的有两个, ngx_time_sigsafe_update和ngx_time_update。前者指负责err_log的时间,后者负责更新非常多时间

4)接下来就是ngx_getpid(),为master进程创建一个文件。单独保存master进程的PID.

5)接下来就是准备初始化全局变量ngx_cycle,这个一个大块头。先创建一个内存池,保存相关用户传递进来的參数ngx_save_argv,

6)接下来就是处理选择项的问题。就是看看步骤5中依据用户输入的參数都保存了什么參数。

7)ngx_add_inherited_sockets函数是处理集成的套接字,这些套接字是依据NGINX这个环境变量来设置的,假设没有这个环境变量。那么就不进行操作,这些套接字是须要保存到cycle中的listening中,作为监听套接字。

8)ngx_init_cycle是初始化全局大块头,这里做了非常多非常多的配置,尤其是当中的ngx_conf_parse()函数,这个函数解析配置文件。

9)接下来就是处理步骤1中依据用户输入的參数都设置了什么全局变量,比方ngx_test_config和ngx_signal,假设是信号就须要对应的操作ngx_signal_process.

10)假设不是信号处理,那么就须要初始化master进程须要关注的信号。

11)推断是否须要设置为daemon进程。最后进入开启worker进程的模型。

ngx_single_process_cycle和ngx_master_process_cycle。

到此为止。main函数已经分析完了,当中有三点比較重要。一个ngx_init_cycle()

Ngx_master_process_cycle和ngx_init_signals()函数。咱们从简单的来看吧

Nginx中信号的处理方式:

在ngx_init_signals函数中,遍历signals全局数组,这个数组中保存着nginx须要关注的所用信号。为每个信号赋值相应的信号处理函数。全部的信号都相应同一个信号处理函数ngx_signal_handler()函数,在这个函数有看到了前面提到的一个函数,和更新时间有关。ngx_time_sigsafe_update,这个函数是更新错误时间的,也就是说。在信号处理中有一个更新时间的操作。虽说仅仅更新错误信息的时间。看看信号处理的方式。首先依据ngx_process来推断当前的传递信号的方式,是给master进程传递的?还是给全部的进程来传的?

总之有一句话,master进程从外部接受到信号,那么master进程就会被激活。全部的信号都相应同一个信号处理函数ngx_signal_handler处理,这个处理仅仅是处理相应的全局标志位,那么master进程再依据标志位来做相应的处理,大部分信号处理就是ngx_signal_worker_process函数,也就是须要将master进程接收到的信号也给worker进程传递一份,这里仅仅有三个信号须要传递给worker进程。也就是说worker进程仅仅需关注三个信号(事实上不是三个信号。可能是好几个信号。仅仅只是有多个信号相应着同一个处理。终于worker进程仅仅须要关注ngx_reopen/ngx_quit/ngx_terminate这三个变量就可以)。传递信号的方式可能是用socketpait,也可能是用kill系统调用。

再简单点介绍信号的处理就是:既然nginx是多进程的。那么不可能全部进程都能够接受外部信号的,那么这个任务交给master进程算了。master进程就须要注冊自己关注的信号,同一时候相应的信号处理函数,那么在fork出子进程后,子进程就须要清空集成的信号(由于外部信号处理交给master进程了),父子进程的通信通过socketpair来处理,那么子进程在这个通道上的读取事件处理就是ngx_channel_handler,在这个函数中,依据master进程发送的命令来改动全局变量。注意进程被信号激活接下来的操作都是推断全局变量,那么全局变量的改动对于不同的进程又不同样。master进程是通过信号处理函数(ngx_signal_handler处理),worker进程是通过socketpair创造的套接字相应的函数(ngx_channel_handler)

父子进程再被信号激活以后,都是依据全局变量来推断做什么处理的。

那么谁来改动全局变量呢?那么对于master进程来说。改动全局变量的任务交给了ngx_signal_handler函数,对于子进程来说,这个任务就是ngx_channel_handler来处理的。并且master进程关注的信号比子进程关注的信号多,全部有的信号是不须要给子进程来传递的,所以有了ngx_process这个变量。比方在ngx_get_options函数中。假设发现了-s选项。那么说明用户是准备给nginx发送信号。假设信号是stop之类。就须要将ngx_process设置为NGX_PROCESS_SIGNALLER,说明这个信号须要给子进程发送。

Ngx_process被赋值的地方不多,在nginx.c中,ngx_cycle.c中都有被赋值的操作。Ngx_process在ngx_get_options中被赋值,假设用户输入的信号是stop之类的信号等。在main函数中。假设有master配置,那么就被赋值为NGX_PROCESS_MASTER。

nginx源代码分析--框架设计 & master-worker进程模型的更多相关文章

  1. 菜鸟nginx源代码剖析 框架篇(一) 从main函数看nginx启动流程

    菜鸟nginx源代码剖析 框架篇(一) 从main函数看nginx启动流程 Author:Echo Chen(陈斌) Email:chenb19870707@gmail.com Blog:Blog.c ...

  2. nginx源代码分析--进程间通信机制 & 同步机制

    Nginx源代码分析-进程间通信机制 从nginx的进程模型能够知道.master进程和worker进程须要通信,nginx中通信的方式有套接字.共享内存.信号.对于master进程,从外部接受信号, ...

  3. 新秀nginx源代码分析数据结构篇(两) 双链表ngx_queue_t

    nginx源代码分析数据结构篇(两) 双链表ngx_queue_t Author:Echo Chen(陈斌) Email:chenb19870707@gmail.com Blog:Blog.csdn. ...

  4. Nginx源代码分析—业务流程

    Nginx源代码分析-业务流程 到此为止,我们如果ngx_init_cycle已经结束.我们临时无论他做了什么,我们从他做的效果进入. 从常理上来讲,假设一个请求到达,那么我们须要接受这个请求,那么就 ...

  5. 新秀nginx源代码分析数据结构篇(四)红黑树ngx_rbtree_t

    新秀nginx源代码分析数据结构篇(四)红黑树ngx_rbtree_t Author:Echo Chen(陈斌) Email:chenb19870707@gmail.com Blog:Blog.csd ...

  6. nginx源代码分析--从源代码看nginx框架总结

    nginx源代码总结: 1)代码中没有特别绕特别别扭的编码实现.从变量的定义调用函数的实现封装,都非常恰当.比方从函数命名或者变量命名就能够看出来定义的大体意义,函数的基本功能,再好的架构实如今编码习 ...

  7. nginx源代码分析--高性能server开发 常见的流程模型

    1.高性能server 对于高性能server对于.处理速度和占用空间小是典型特性.特别是当server经验C10K问题的时候(网络server在处理数以万计的client连接时.往往出现效率低下甚至 ...

  8. nginx源代码分析--事件模块 & 琐碎

    通过HUP信息使得NGINX实现又一次读取配置文件,使用USR2信号使得NGINX实现平滑升级. 在nginx中有模块这么一说,对外全部的模块都是ngx_module_t类型,这个结构体作为全部模块的 ...

  9. nginx源代码分析--event事件驱动初始化

    1.在nginx.c中设置每一个核心模块的index ngx_max_module = 0; for (i = 0; ngx_modules[i]; i++) { ngx_modules[i]-> ...

随机推荐

  1. jsp学习笔记 - 内置对象 session

    1.session 主要用来用户的登录和注销 设置用户名,获取用户名 session.setAttribute("username","johnson"); s ...

  2. ERwin 正向工程

    1.物理模型带字段备注 COMMENT ON 将模型切换至 physical 模式选择 Model ---> Domain Dictionary , 在 tab 标签中,切换至comment 然 ...

  3. Java Servlet DAO实践(二)

    Java Servlet DAO实践(二) DAO连接类 package com.seller.servlets.dao; import java.sql.*; public class DataBa ...

  4. 【笔记JS/HTML/CSS】CSS3实现鼠标滑动显示动画(transition、transform)

    内容中包含 base64string 图片造成字符过多,拒绝显示

  5. RocketMQ学习笔记(14)----RocketMQ的去重策略

    1. Exactly Only Once (1). 发送消息阶段,不允许发送重复的消息 (2). 消费消息阶段,不允许消费重复的消息. 只有以上两个条件都满足情况下,才能认为消息是“Exactly O ...

  6. WINVER WIN32 WINNT

    WINVER 和 _WIN32_WINNT 请在WINDOWS.H前定义 从 Visual C++ 2008 开始,Visual C++ 不支持面向 Windows 95.Windows 98.Win ...

  7. vue+webpack+npm搭建的纯前端项目

    转载来源:https://www.cnblogs.com/shenyf/p/8341641.html 搭建node环境 下载 1.进入node.js官方网站下载页,点击下图中框出位置,进行下载即可,当 ...

  8. 反片语(Ananagrams,Uva 156)

    输入一些单词,找出所有满足如下条件的单词:该单词不能通过字母重排,得到输入文 本中的另外一个单词.在判断是否满足条件时,字母不分大小写,但在输出时应保留输入中 的大小写,按字典序进行排列(所有大写字母 ...

  9. Git安装使用指南

    Git安装使用指南 Git原理示意图 1. 安装git Linux服务器版本为Redhat6.2-64,其他版本可能有些许不同 1.1 安装依赖包 在安装git前首先安装依赖包,包括的依赖包有: cv ...

  10. Win10中创建Hyper-V虚拟机

    Win10虚拟机创建方法方法 1 开始菜单->所有应用->Windows系统->控制面板,程序->启用或关闭Windows功能,勾选Hyper-V下所有选项 如果Hyper-V ...