Nginx入门之两种handler函数的挂载方式

请在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

接着上次的文章,今天研究《深入理解Nginx模块开发与架构解析》一书中给出的mytest的例子,发现和 /tengine.taobao.org/book/一书中的例子不甚相同,尤其是在handler函数的挂在方面。

函数的挂载分为两种方式:

一种方式就是按处理阶段挂载;另外一种挂载方式就是按需挂载。tengine.taobao.org 中使用的挂载方式是按处理阶段挂载,而深入理解一书中的挂载方式是按需求挂载。

首先看/tengine.taobao.org/book/中的例子:

由我之前 Nginx_handler模块发开(hello模块结构解析)一文,handler_init就是handler函数的挂载函数,该函数在上下文结构中的postconfiguration字段被调用,决定handler函数在哪里被挂载。

 1 static ngx_http_module_t ngx_http_hello_module_ctx = {
 2         NULL,                          /* preconfiguration */
 3         ngx_http_hello_init,           /* postconfiguration */
 4
 5         NULL,                          /* create main configuration */
 6         NULL,                          /* init main configuration */
 7
 8         NULL,                          /* create server configuration */
 9         NULL,                          /* merge server configuration */
10
11         ngx_http_hello_create_loc_conf, /* create location configuration */
12         NUL

 1 static ngx_int_t
 2 ngx_http_hello_init(ngx_conf_t *cf)
 3 {
 4         ngx_http_handler_pt        *h;
 5         ngx_http_core_main_conf_t  *cmcf;
 6
 7         cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); //取得core_module的cf
 8
 9         h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers); // 挂载函数到对应处理阶段
10         if (h == NULL) {
11                 return NGX_ERROR;
12         }
13
14         *h = ngx_http_hello_handler; //将函数指针指向handler函数
15
16         return NGX_OK;
17 }

使用这种方式挂载的handler也被称为 content phase handlers

而在《深入理解Nginx模块开发与架构解析》一书中给出的mytest的例子中,则是按需求挂载:

以这种方式挂载的handler也被称为 content handler

当一个请求进来以后,nginx从NGX_HTTP_POST_READ_PHASE阶段开始依次执行每个阶段中所有handler。执行到 NGX_HTTP_CONTENT_PHASE阶段的时候,如果这个location有一个对应的content handler模块,那么就去执行这个content handler模块真正的处理函数。否则继续依次执行NGX_HTTP_CONTENT_PHASE阶段中所有content phase handlers,直到某个函数处理返回NGX_OK或者NGX_ERROR。

换句话说,当某个location处理到NGX_HTTP_CONTENT_PHASE阶段时,如果有content handler模块,那么NGX_HTTP_CONTENT_PHASE挂载的所有content phase handlers都不会被执行了。

但是使用这个方法挂载上去的handler有一个特点是必须在NGX_HTTP_CONTENT_PHASE阶段才能执行到。如果你想自己的handler在更早的阶段执行,那就不要使用这种挂载方式。

那么在什么情况会使用这种方式来挂载呢?一般情况下,某个模块对某个location进行了处理以后,发现符合自己处理的逻辑,而且也没有必要再调用NGX_HTTP_CONTENT_PHASE阶段的其它handler进行处理的时候,就动态挂载上这个handler。

mytest这个例子在配置结构中,直接调用了content handler函数,名为ngx_http_mytest,该函数直接实现了真正的handler函数的挂载执行:

 1 static ngx_command_t ngx_http_mytest_commands[] = {
 2     {
 3         ngx_string("mytest"),
 4         NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_NOARGS,
 5         ngx_http_mytest,
 6         NGX_HTTP_LOC_CONF_OFFSET,
 7         0,
 8         NULL
 9     },
10     ngx_null_command
11 };

content handler函数 ngx_http_mytest的定义如下:

 1 static char *
 2 ngx_http_mytest(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 3 {
 4     ngx_http_core_loc_conf_t *clcf;
 5
 6     clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
 7
 8     clcf->handler = ngx_http_mytest_handler;
 9
10     return NGX_CONF_OK;
11 }

定义十分简单,主要就是一个ngx_http_conf_get_module_loc_conf函数的调用,以及一个函数指针的赋值。函数指针的赋值实现了真正的handler函数的挂载。

那么,我们来看看被调用的ngx_http_conf_get_module_loc_con函数的定义:

#define ngx_http_conf_get_module_loc_conf(cf, module)                         \
    ((ngx_http_conf_ctx_t *) cf->ctx)->loc_conf[module.ctx_index]

只是一个宏定义,主要作用是将之前存储起来的conf内容调出,赋值给clcf。

联系方式:[email protected]。

个人理解,欢迎指正。

时间: 2024-11-11 05:39:48

Nginx入门之两种handler函数的挂载方式的相关文章

js两种定义函数、继承方式及区别

一:js两种定义函数的方式及区别 1:函数声明: function sayA() { alert("i am A"); } 2:函数表达式: var sayB = function() { alert("i am B"); } 区别:code 前者会在代码执行之前提前加载到作用域中,后者则是在代码执行到那一行的时候才会有定义 二:js两种继承方式及区别 对象冒充 临时属性 call() apply() 原型链 code 继承应选哪种 code 三:实例 js两种定义

javascript两种声明函数的方式的一次深入解析

声明函数的方式 javascript有两种声明函数的方式,一个是函数表达式定义函数,也就是我们说的匿名函数方式,一个是函数语句定义函数,下面看代码: /*方式一*/ var FUNCTION_NAME = function() { /* FUNCTION_BODY */}; /*方式二*/ function FUNCTION_NAME () { /* FUNCTION_BODY */}; 区别一 方式一的声明方式是先声明后使用 方式二的声明方式可以先调用,后声明 /*方式一: *先声明后使用 *

FastCGI特点原理、nginx与php-fpm两种通信方式对比

kankacan一.FastCGI特点: 1.HTTP服务器和动态脚本语言间通信的接口或工具 2.可把动态语言解析和HTTP服务器分离I 3.Nginx.Apache.Lighttpd,以及多数动态语言 都支持FastCGI 4.FastCGI接口方式采用 C/S结构,分为客户端(HTTP服务器)和服务器端(动态语言解析服务器) 5.PHP动态语言服务器可以启动多个FastCGI的守护进程(例如php-fpm(fcgi process mangement)) 6.HTTP服务器通过 FastCG

Nginx安装的两种方法

Nginx安装的两种方法 方法一:通过操作系统的包管理器进行安装. centos操作系统,自带的包管理器就是yum,配置yum源,通过yum源安装nginx的方法很简单,这就是方法一的优点:方法一的缺点就是,我们安装nginx时,无法定义安装哪些模块.这里我们解释一下模块的概念,nginx的结构是高度的模块话的,不同的模块拥有不同的功能,所以,我们想要在使用nginx的时候可以使用某些特定的功能就必须安装对应的模块.不过,yum安装的nginx,包含了常用的基本模块,不需要我们安装模块.方法二与

(nginx|apache)+tomcat 几种常见的代理实现方式或连接类型(connector type)

简单描述一下nginx两块网卡,eth1外网,eth0内网与tomcat eth0通信,用户请求静态内容由nginx直接响应,动态内容则nginx转发至后端tomcat响应 安装nginx,tomcat不再描述. nginx的配置文件如下:/etc/nginx/nginx.conf [[email protected] ~]# pnginx worker_processes 1; events { worker_connections 1024; } http { include mime.ty

KbmMW两种查询结果集通讯方式

KbmMW本身可以用QueryService的方式进行远程数据查询,但是SmpileService同样具有很强的扩展性可以实现数据查询,下面展示两种基于SmpileService的远程数据查询方法,其原理都是利用TkbmMWSimpleService实现流的传输. 直接上代码了: 一.利用KbmMemTable: 服务端: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 3

struts2中两种validation.xml的配置方式_百度文库

在struts中,根据配置的validation.xml文件进行页面输入项目的验证已经众所周知,本文介绍在struts2中两种validation.xml的配置方式.可以根据不同的需要进行不同的配置. 以下以login页面输入firstname,lastname,和age为例进行说明.struts.xml中,成功的话转向成功页面.不成功的话转回到原页面. 首先建立userbean文件.文件名:UserBean.java包:struts2.login.bean文件内容:package struts

JS里面的两种运动函数

最新学了一个新的运动函数,与最初学习的有所不同,第一个运动是根据运动速度完成运动 ,第二个则是根据运动的时间来完成运动,而且把之前的函数都进行了一些兼容处理,在这里列出了看一下: 第一种animate1 1 function animate1(obj,data,rate,fn){//运动对象,运动数据,[运动速度],[回调函数] 2 //遍历获取样式属性 3 for(var key in data){ 4 //通过闭包将key私有化 5 (function(k){ 6 /* 7 获得样式宽高等会

两种open()函数

C语言中文件操作函数中,open()有两种形式: 一种形式是有两个参数open2: 另一种形式是有三个参数open3: 共有的参数有两个,第一个是"被打开文件的路径",第二个是"文件打开的方式": 在使用中,如果文件打开的方式中使用了O_CREAT,则使用带有三个参数的open(),第三个参数是"被打开文件的存取权限":