Nginx Http框架的理解
Nginx Http框架的理解
HTTP框架是Nginx基础框架的一部分,Nginx的其它底层框架如master-worker进程模型、event模块、mail 模块等。
HTTP框架代码主要有2个模块组成:ngx_http_module和ngx_http_core_module;
我们编写的HTTP模块需要注册到HTTP框架上,才能融入HTTP请求的处理流程中。
当在nginx.conf中存在一个http{...}的配置时,即启用了HTTP框架代码,在nginx配置解析时,就已经为框架建立好了各种数据结构(尤其是HTTP模块的挂载);
当nginx收到请求时,请求完全按照HTTP框架建立好的这种逻辑进行处理。
一、HTTP模块开发基础
开发一个HTTP模块,需要下面几个数据结构:
用于存储从配置文件读进来的相关指令参数;
ngx_str_t name; // 指令名称
ngx_uint_t type; // 指令所在的context和包含的参数个数
char *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); // 解析配置,并将参数存入模块配置结构体中
ngx_uint_t conf; // 指令参数的存储位置
ngx_uint_t offset; // 指令参数的存储偏移量
void *post;
};
b. 指向结构体 ngx_command_t 的指针
c. 指向模块自定义配置结构体的指针
静态的ngx_http_module_t结构体,用来创建和合并三段context (main,server,location),
ngx_int_t (*preconfiguration)(ngx_conf_t *cf); // 在读入配置前调用
ngx_int_t (*postconfiguration)(ngx_conf_t *cf); // 在读入配置后调用,用于挂载handler
void *(*create_main_conf)(ngx_conf_t *cf); // 在创建main配置时调用(比如,用来分配空间和设置默认值)
char *(*init_main_conf)(ngx_conf_t *cf, void *conf); // 在初始化main配置时调用(比如,把原来的默认值用nginx.conf读到的值来覆盖)
void *(*create_srv_conf)(ngx_conf_t *cf); // 在创建server配置时调用
char *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, void *conf); // 合并server和main配置时调用
void *(*create_loc_conf)(ngx_conf_t *cf); // 创建location配置时调用,用于为指令参数结构体分配内存和初始化
char *(*merge_loc_conf)(ngx_conf_t *cf, void *prev, void *conf); // 合并location和server配置时调用
} ngx_http_module_t;
这些回调是在ngx_http_block()解析http{...}配置时完成的:
当遇到一个 http{...} 时,HTTP框架会调用所有HTTP模块可能实现的create_main_conf、create_srv_conf、create_loc_conf生成存储main级别配置参数结构体;
当遇到一个server{...}时,HTTP框架会调用所有HTTP模块可能实现的create_srv_conf、create_loc_conf生成存储server级别配置参数结构体;
当遇到一个location{...}时,HTTP框架会调用所有HTTP模块可能实现的create_loc_conf生成存储location级别配置参数结构体;
因此,我们开发的HTTP模块中create_loc_conf方法被调用的次数等于http{...}、server{...}、location{...}在nginx.conf出现的次数之和;
create_srv_conf方法被调用的次数等于server{...}、location{...}在nginx.conf出现的次数之和;
由于只有一个http{...},所以create_main_conf方法只会被调用一次;
HTTP创建了如此多的结构体来存放配置项,是为了解决同名配置项的合并问题。
struct ngx_module_s {
ngx_uint_t ctx_index; // 在所有的HTTP模块中的序列号
ngx_uint_t index; // 在所有模块中的序列号
ngx_uint_t spare0;
ngx_uint_t spare1;
ngx_uint_t spare2;
ngx_uint_t spare3;
ngx_uint_t version;
void *ctx; // 模块上下文
ngx_command_t *commands; // 模块配置指令
ngx_uint_t type; // 模块类型,HTTP模块应为NGX_HTTP_MODULE
ngx_int_t (*init_master)(ngx_log_t *log);
ngx_int_t (*init_module)(ngx_cycle_t *cycle);
ngx_int_t (*init_process)(ngx_cycle_t *cycle);
ngx_int_t (*init_thread)(ngx_cycle_t *cycle);
void (*exit_thread)(ngx_cycle_t *cycle);
void (*exit_process)(ngx_cycle_t *cycle);
void (*exit_master)(ngx_cycle_t *cycle);
uintptr_t spare_hook0;
uintptr_t spare_hook1;
uintptr_t spare_hook2;
uintptr_t spare_hook3;
uintptr_t spare_hook4;
uintptr_t spare_hook5;
uintptr_t spare_hook6;
uintptr_t spare_hook7;
};
注意:在configure之后生成的文件 objs/ngx_modules.c 中包含了模块的编译顺序。
1、解析HTTP配置的流程
首先要理解 ngx_conf_parse() 的递归解析流程;
nginx在解析nginx.conf的时候,没读取一行配置项,就执行该配置项的解析回调(handler);
Nginx Http框架的理解的更多相关文章
- Nginx:HTTP框架是如何介入请求
参考资料 <深入理解Nginx>(陶辉) Nginx事件模块博客地址:http://www.cnblogs.com/runnyu/p/4914698.html Nginx是一个事件驱动构架 ...
- iOS10通知框架UserNotification理解与应用
iOS10通知框架UserNotification理解与应用 一.引言 关于通知,无论与远程Push还是本地通知,以往的iOS系统暴漏给开发者的接口都是十分有限的,开发者只能对标题和内容进行简单的定义 ...
- Java面试之五大框架的理解
五大框架(springMVC,struts2,spring,mybatis,hibernate) 说说你对springMVC框架的理解? 简要口述(如果感觉说的少可以在完整答案里面挑几条说) Spri ...
- 对SSH三大框架的理解
SSH框架一般指的是Struts.Spring.Hibernate,后来Struts2代替了Struts.最近5年,Struts2已经被Spring MVC代替,而Hibernate基本也被iBati ...
- Nginx学习之十一-Nginx启动框架处理流程
Nginx启动过程流程图 下面首先给出Nginx启动过程的流程图: ngx_cycle_t结构体 Nginx的启动初始化在src/core/nginx.c的main函数中完成,当然main函数是整个N ...
- nginx配置之深入理解
继上一篇<debian+nginx配置初探--php环境.反向代理和负载均衡>成功之后,有点小兴奋,终于不用整lvs那么复杂来搞定负载,但还是有很多概念没弄清楚. 什么是CGI.FastC ...
- Django_web框架的理解
web框架的本质 import socket sk = socket.socket() sk.bind(("127.0.0.1", 80)) sk.listen() while T ...
- 对spring框架的理解
spring框架的两大核心理念就是IOC和AOP,在面试的时候经常会被问到你对spring的理解.下面大致的说一下我对spring的理解. 一.IoC 1.1.什么是IoC 众所周知,IoC就是控制反 ...
- nginx 限速最容易理解的说明
nginx 限速研究汇报 写在前面 这两天服务器带宽爆了,情况如下图: 出于降低带宽峰值的原因,我开始各种疯狂的研究nginx限速.下面是我研究过程中的心得!(花了好几个小时的时间写的人生第一篇技术类 ...
随机推荐
- C语言 数组类型与数组指针类型
//数组类型与数组指针类型 #include<stdio.h> #include<stdlib.h> #include<string.h> void main(){ ...
- Matlab中reshape函数的使用
reshape把指定的矩阵改变形状,但是元素个数不变, 例如,行向量: a = [1 2 3 4 5 6] 执行下面语句把它变成3行2列: b = reshape(a,3,2) 执行结果: b = 1 ...
- 对于JAVA课程的期望
对于JAVA课程的期望 我对于JAVA这门课程最初的了解可能来自于学长学姐的描述,或者是选课指南上简单的课程名称,那个时候的JAVA,对我来说遥远而又陌生,显得那么高大上,但是一转眼自己马上就要结束大 ...
- 【iOS功能实现】之利用UIDocumentInteractionController打开和预览文档
iOS提供了使用其他app预览文件的支持,这就是Document Interaction Controller.此外,iOS也支持文件关联,允许其他程序调用你的app打开某种文件.而且,从4.2开始, ...
- Orchard创建自定义表单
本文链接:http://www.cnblogs.com/souther/p/4520130.html 主目录 自定义表单模块可以用来获取网站前台用户的信息.自定义表单需要与一个内容类型结合使用.它可以 ...
- OSX 上安装 Scrapy 的那些坑
Scrapy 这个爬网框架真心不错,但在OSX上安装总是会出现各种的问题,在这里就作一个收集汇总.我的系统环境是 OS X El Capitan (10.11.1) 首先要保证 pip , virtu ...
- Java并发编程-ReentrantLock
代码示例: Lock lock = new ReentrantLock(); lock.lock(); try { // update object state } finally { lock.un ...
- openwrt的路由器重置root密码
家里路由器刷了openwrt,结果长期没登录,忘了root密码. 很容易就找到了这里介绍的办法 http://www.openwrt.org.cn/bbs/thread-12327-1-1.html ...
- C# 6.0部分新特性
Struct的默认构造函数和属性赋值 我看C# 6 introduce 提到这个功能.但vs2015搭载的NET4.6貌似还不支持这个.所以也不好判断. 属性赋值 /// <summary> ...
- Javascript基础系列之(二)变量
javascript 中变量通过var关键字(variable)来声明的. var school = "beijingyizhong" 也可以通过var 关键字给变量多个值. va ...