调用HTTP模块的流程:nginx
Worker进程会在一个for循环语句中反复调用事件模块检测网络事件。当事件模块检测到某个客户端发起的TCP请求时(接收到SYN包),将会为它创建TCP链接,成功创建链接后根据nginx.conf文件中的配置会交由HTTP框架处理。HTTP框架会试图接收完整的HTTP头部,并在接受到完整的HTTP头部后将请求分发到具体的HTTP模块中处理。这种分发策略是多样化的,最多见的是根据请求的URI和nginx.conf里location配置项的匹配度来决定如何分发。HTTP模块在处理请求的结束时,大多会向客户端发送响应,此时会自动地依次调用全部的HTTP过滤模块,每一个过滤模块能够根据配置文件决定本身的行为。web
事件类型的模块主要处理I/O事件相关的功能,HTTP类型的模块主要处理HTTP应用层的功能。数组
Nginx在解析配置文件中的一个配置项时首先会遍历全部的模块,对于每个模块而言,即经过遍历commands数组进行,另外,在数组中检查到ngx_null_command时,会中止使用当前模块解析该配置项。=>个人理解:若是在某模块中找到该配置项名称,则调用该模块中commands数组的set方法来解析该配置项。Set方法中会调用ngx_http_mytest_handler函数服务器
1、Nginx的架构设计网络
1)优秀的模块化设计数据结构
1)高度抽象的模块接口架构
全部的模块都遵循着一样的ngx_module_t接口设计规范,ngx_module_t是全部模块的通用接口并发
2)模块接口很是简单,具备很高的灵活性负载均衡
模块的基本接口ngx_module_t足够简单,只涉及模块的初始化、退出以及对配置项的处理框架
3)配置模块的设计
配置模块的类型是NGX_CONF_MODULE,它仅有的模块为ngx_conf_module,这是Nginx最底层的模块,它指导着全部模块以配置项为核心来提供功能
4)核心模块接口的简单化
基础类型的模块:核心模块,它的模块类型为NGX_CORE_MODULE,目前官方的核心类型模块中共有6个具体模块,分别是ngx_core_module,ngx_errlog_module,ngx_events_module,ngx_openssl_module,ngx_http_module,ngx_mail_module模块。定义核心模块是为了让非模块化的框架代码只关注于如何调用6个核心模块
核心模块的接口以下,它将ctx上下文进一步实例化为ngx_core_module_t结构体:
typedef struct{
//核心模块名称
ngx_str_t name;
void *(*create_conf)(ngx_cycle_t *cycle);
char *(*init_conf)(ngx_cycle_t *cycle,void *conf);
}ngx_core_module_t;
ngx_core_module_t上下文是以配置项的解析做为基础的,它提供了create_conf回调方法来建立存储配置项的数据结构,在读取nginx.conf配置文件时,会根据模块中的ngx_command_t把解析出的配置项存放在这个数据结构中;它还提供了init_conf回调方法,用于在解析完配置文件后,使用解析出的配置项初始化核心模块功能。
上述设计使得每一个核心模块均可以自由地定义全新的模块类型,新定义的模块由核心模块管理。
5)多层次、多类别的模块设计
官方Nginx共有五大类型的模块:核心模块、配置模块、事件模块、HTTP模块、mail模块。
配置模块和核心模块由Nginx的框架代码定义,其余3种模块都不会和框架产生直接关系。
事件模块、HTTP模块、mail模块这三种模块在核心模块中各有一个模块做为本身的代言人,并在同类模块中有一个做为核心业务与管理功能的模块
在这5中模块中,配置模块与核心模块都是与Nginx框架密切相关的,是其余模块的基础。而事件模块则是HTTP模块和mail模块的基础。在事件模块中,ngx_event_core_module事件模块是其余全部事件模块的基础;在http模块中,ngx_http_core_module模块是其余全部HTTP模块的基础;在mail模块中,ngx_mail_core_module模块是其余全部mail模块的基础。
2)事件驱动架构
事件驱动架构是指由一些事件发生源来产生事件,由一个或多个事件收集器来收集、分发事件,而后许多事件处理器会注册本身感兴趣的事件,同时会消费这些事件。
对于Nginx而言,通常会由网卡、磁盘产生事件,事件模块将负责事件的收集、分发操做,而全部的模块均可能是事件消费者。
Nginx采用彻底的事件驱动架构来处理业务。对于传统web服务器而言,事件驱动每每局限在TCP连接创建、关闭事件上,一个链接创建之后,在其关闭以前的全部操做逗再也不是事件驱动,这时会退化成按序执行每一个操做的批处理模式,这样每一个请求在连接创建后都将始终占用着系统资源,知道链接关闭才会释放资源。传统web服务器每每把进程或线程做为事件消费者,当一个请求产生的事件被该进程处理时,知道这个请求处理结束时进程资源都将被这个请求所占用。
Nginx只有事件收集、分发器才有资格占用进程资源,它们会在分发某个事件时调用事件消费模块使用当前占用的进程资源。
3)请求的多阶段异步处理
即把一个请求的处理过程按照事件的触发方式分为多个阶段,每一个阶段均可以由事件收集、分发器来触发。
关键在于划分请求的阶段,通常是找到请求处理流程中的阻塞方法(或者形成阻塞的代码段),在阻塞代码段上按照下面4种方式来划分阶段:
1.将阻塞进程的方法按照相关的触发事件分解为两个阶段
大部分状况下,一个阻塞进程的方法调用时能够划分为两个阶段:阻塞方法改成非阻塞方法调用,这个调用非阻塞方法并将进程归还给事件分发器的阶段就是第一阶段;增长新的处理阶段用于处理非阻塞方法最终返回的结果,这里的结果返回事件就是第二阶段的触发事件
2.将阻塞方法调用按照时间分解为多个阶段的方法调用
系统中的事件收集、分发者并不是能够处理任何事件,若是按照前一种方式试图划分某个方法时,那么可能会发现找出的触发事件不可以被事件收集、分发器所处理,这时只能按照执行时间来拆分这个方法。
例如读取10MB的文件(ngx_epoll_module模块主要是针对网络事件),能够这样来分解读取文件调用:每次只读取10kb,这样该事件接收器占用进程的时间不会过久,整个进程能够及时地处理其余请求。
在读取0-10kb后,为了进入10kb-20kb阶段,能够用能被事件收集器处理的事件来触发,或者设置一个定时器。
3.在无所事事且必须等待系统的响应,从而致使进程空转时,使用定时器划分阶段
当定时器事件发生时就会检查标志,若是标志位不知足,就马上归还进程控制权,同时继续加入指望的下一个定时器事件
4.若是阻塞方法彻底没法继续划分,则必须使用独立的进程执行这个阻塞方法
4)管理进程、多工做进程设计
Nginx采用一个master管理进程、多个worker工做进程的设计方式。
优势:
1.利用多核系统的并发处理能力。
Nginx中全部的worker工做进程都是彻底平等的。
2.负载均衡
多个worker工做进程间经过进程间通讯来实现负载均衡,当一个请求到来时更容易被分配到负载较轻的worker工做进程中处理。
3.管理进程会负责监控工做进程的状态,并负责管理其行为。
5)内存池的设计
优势:把屡次向系统申请内存的操做整合成一次,大大减小了cpu资源的消耗,同时减小了内存碎片,提升了内存的有效利用率和系统可处理的并发链接数。
2、Nginx框架中的核心结构体ngx_cycle_t
ngx_listening_t结构体
ngx_cycle_t对象中有一个动态数组成员叫作listening,它的每一个数组元素都是ngx_listening_t结构体,而每一个ngx_listening_t结构体表明着Nginx服务器监听的一个端口。
ngx_cycle_t结构体
Nginx框架是围绕着ngx_cycle_t结构体来控制进程运行的。ngx_cycle_t结构体的prefix,conf_prefix,conf_file等字符串类型成员保存着Nginx配置文件的路径。
3、Nginx启动时框架的处理流程
4、worker进程工做流程
5、master进程工做流程
参考:
http://blog.csdn.net/xifeijian/article/details/17385831