• 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。

    联系方式:rwhsysu@163.com。

    个人理解,欢迎指正。

  • 相关阅读:
    Tar命令用法详解
    一次Linux系统被攻击的分析过程
    企业系统安全管理和强化的十点建议
    中型企业的IT运维策略
    企业邮件服务器被列入RBL,申请撤销PBL指控
    Xshell远程连接Ubuntu
    LeetCode 7: Reverse Integer
    LeetCode 14: Longest Common Prefix
    LeetCode 203:Remove Linked List Elements
    数据挖掘之处理分类自变量与处理时间变量
  • 原文地址:https://www.cnblogs.com/paulweihan/p/4664784.html
Copyright © 2020-2023  润新知