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限速.下面是我研究过程中的心得!(花了好几个小时的时间写的人生第一篇技术类 ...
随机推荐
- 反射中使用 BindingFlags.IgnoreCase
我们经常需要通过反射来调用目标对象的方法或获取/设置目标对象的属性,Type.InvokeMember 方法签名如下: public object InvokeMember(string name,B ...
- JQuery学习笔记——JQuery基础
#,JQuery避免名称冲突的方法 var jq = jQuery.noConfilct(); jq.ready( function(){ jq("p").hidden() ...
- 从0开始学Java——JSP&Servlet——HttpServletRequest相关的几个路径信息
在HttpServletRequest中有几个获取路径的接口:getRequestURI/getContextPath/getServletPath/getPathInfo 这些接口互相之间有什么区别 ...
- 如何在Ubuntu 14.04中安装最新版Eclipse
想必很多开发人员都知道,Ubuntu 软件源中提供的并不是最新版本的 Eclipse,本教程就教大家如何在 Ubuntu 14.04 中快速安装 Eclipse 官方发布的最新版本. 到目前为止,Ec ...
- 启动页面设置,icon图标设置
更多尺寸像素如何放置请看:http://chicun.jammy.cc/ 如何设置App的启动图,也就是Launch Image? 新建一个iosLaunchImage文件夹
- brew-cask 之本地更新 node
本文同步自我的个人博客:http://www.52cik.com/2015/11/04/brew-cask-local.html 今天 Node v4.2.2 (LTS) 发布,什么是 LTS 呢,百 ...
- Cordova4.0 系列 -- 常用命令(2)
一. 创建一个cordova工程 create <directory> [<id> [<name>]] 二. 列出该工程支持哪些平台 platform [ls | ...
- session放到mongo里边
为了session的共享和保存,常常把session放数据库里边,但是很多时候都放redis里边,今天看了一个放Mongo中的记录下,说不懂什么时候就用到了. app.use(session({ se ...
- NoSQL数据库之国产开源产品:SequoiaDB 分析前言
随着互联网技术的发展,面对海量数据的存储和分析,传统关系型数据库已经无法满足,由此衍生出一种与关系型数据库区别开的数据库NoSQL(Not Only SQL). 国外做的比较成熟的NoSQL有Mong ...
- angular的splitter案例学习
angular的splitter案例学习,都有注释了,作为自己的备忘. <!DOCTYPE html> <html ng-app="APP"> <he ...