`

解剖Nginx·模块开发篇(2)ngx_http_hello_world_module 模块基本结构定义

 
阅读更多

解剖Nginx·模块开发篇(2)ngx_http_hello_world_module 基本结构定义

  • 作者:柳大·Poechant(钟超)
  • 邮箱:zhongchao.ustc#gmail.com(# -> @)
  • 博客:Blog.CSDN.net/Poechant
  • 日期:June 2nd, 2012

HelloWorld 是一个典型的 location 模块。什么是 location 模块?在 Nginx 中,根据作用域,有 main 模块、server 模块、location 模块。

1 模块定义

在 HelloWorld 模块中有一个 ngx_http_hello_world_module 变量,用于定义模块。它是 ngx_module_t 类型。ngx_module_t 是 ngx_module_s 的别名,其定义如下:

struct ngx_module_s {
    ngx_uint_t            ctx_index; 
    ngx_uint_t            index; 

    ngx_uint_t            spare0;
    ngx_uint_t            spare1;
    ngx_uint_t            spare2;
    ngx_uint_t            spare3;

    ngx_uint_t            version; // Nginx模块版本

    void                 *ctx; // 上下文定义的地址
    ngx_command_t        *commands; // 命令定义地址
    ngx_uint_t            type; // 模块类型

    ngx_int_t           (*init_master)(ngx_log_t *log); // 初始化 master 时执行

    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); // 退出 master 时执行

    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;
};

在 HelloWorld 例子中:

// Structure for the HelloWorld module, the most important thing
ngx_module_t ngx_http_hello_world_module = {
    NGX_MODULE_V1,
    &ngx_http_hello_world_module_ctx,
    ngx_http_hello_world_commands,
    NGX_HTTP_MODULE,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NGX_MODULE_V1_PADDING
};

1.1 NGX_MODULE_V1

看它的定义你就知道,它是用来填充前 7 个 fields 的。

NGX_MODULE_V1          0, 0, 0, 0, 0, 0, 1

1.2 模块类型

我们的模块是 HTTP 模块,还可以开发 CORE 模块,或者 CONF 模块等等。

// ngx_http_config.h
#define NGX_HTTP_MODULE      0x50545448   /* "HTTP" */

// ngx_conf_file.h
#define NGX_CORE_MODULE      0x45524F43  /* "CORE" */
#define NGX_CONF_MODULE      0x464E4F43  /* "CONF" */

1.3 NGX_MODULE_V1_PADDING

这个还是用来填充字段的,或者叫 padding、补白。

#define NGX_MODULE_V1_PADDING  0, 0, 0, 0, 0, 0, 0, 0

2 命令定义

命令定义用到如下数据结构:

struct ngx_command_s {
    ngx_str_t             name;
    ngx_uint_t            type;
    char               *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
    ngx_uint_t            conf;
    ngx_uint_t            offset;
    void                 *post;
};

一般类说会定义很多命令,但是在 HelloWorld 中只有一个命令。

static ngx_command_t ngx_http_hello_world_commands[] = {
    {
        ngx_string("hello_world"), // The command name
        NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1,
        ngx_http_hello_world, // The command handler
        NGX_HTTP_LOC_CONF_OFFSET,
        offsetof(ngx_http_hello_world_loc_conf_t, output_words),
        NULL
    },
    ngx_null_command
};

我们一个一个来看。

2.1 命令名称

name 成员表示命令名称

2.2 命令类型

type 是命令类型。它可以取如下的一个或多个值的“或”:

  • NGX_HTTP_MAIN_CONF:可出现在 http 的主作用域;
  • NGX_HTTP_SRV_CONF:可出现在 http 的 server 作用域;
  • NGX_HTTP_LOC_CONF:可出现在 http 的 location 作用域;
  • NGX_HTTP_UPS_CONF:可出现在 http 的 upstream 作用域;
  • NGX_HTTP_SIF_CONF:which will allow the directive to be included in if statements at the server level. [参考]
  • NGX_CONF_NOARGS:指令没有参数;
  • NGX_CONF_TAKE1:指令读入1个参数;
  • NGX_CONF_TAKE2:指令读入2个参数;
  • NGX_CONF_TAKE7:指令读入7个参数;
  • NGX_CONF_FLAG:指令读入1个布尔型数据(“on”或“off”);
  • NGX_CONF_1MORE:指令至少读入1个参数;
  • NGX_CONF_2MORE:指令至少读入2个参数;

      // ngx_http_config.h
      #define NGX_HTTP_MAIN_CONF        0x02000000
      #define NGX_HTTP_SRV_CONF         0x04000000
      #define NGX_HTTP_LOC_CONF         0x08000000
      #define NGX_HTTP_UPS_CONF         0x10000000
      #define NGX_HTTP_SIF_CONF         0x20000000
      #define NGX_HTTP_LIF_CONF         0x40000000
      #define NGX_HTTP_LMT_CONF         0x80000000
    
      // ngx_conf_file.h
      #define NGX_CONF_NOARGS      0x00000001
      #define NGX_CONF_TAKE1       0x00000002
      #define NGX_CONF_TAKE2       0x00000004
      #define NGX_CONF_TAKE3       0x00000008
      #define NGX_CONF_TAKE4       0x00000010
      #define NGX_CONF_TAKE5       0x00000020
      #define NGX_CONF_TAKE6       0x00000040
      #define NGX_CONF_TAKE7       0x00000080
    
      // ngx_conf_file.h      
      #define NGX_CONF_TAKE12      (NGX_CONF_TAKE1|NGX_CONF_TAKE2)
      #define NGX_CONF_TAKE13      (NGX_CONF_TAKE1|NGX_CONF_TAKE3)
      #define NGX_CONF_TAKE23      (NGX_CONF_TAKE2|NGX_CONF_TAKE3)
      #define NGX_CONF_TAKE123     (NGX_CONF_TAKE1|NGX_CONF_TAKE2|NGX_CONF_TAKE3)
      #define NGX_CONF_TAKE1234    (NGX_CONF_TAKE1|NGX_CONF_TAKE2|NGX_CONF_TAKE3|NGX_CONF_TAKE4)
    
      // ngx_conf_file.h
      #define NGX_CONF_ARGS_NUMBER 0x000000ff
      #define NGX_CONF_BLOCK       0x00000100
      #define NGX_CONF_FLAG        0x00000200
      #define NGX_CONF_ANY         0x00000400
      #define NGX_CONF_1MORE       0x00000800
      #define NGX_CONF_2MORE       0x00001000
      #define NGX_CONF_MULTI       0x00002000
    

2.3 命令回调函数

这里我们使用的是自己定义的回调函数,还可以使用 Nginx 提供的回调函数,比如:

  • ngx_conf_set_flag_slot:将“on”或者“off”转换成1或0;
  • ngx_conf_set_str_slot:将字符串保存为ngx_str_t;
  • ngx_conf_set_num_slot:解析一个数字并保存为ngx_int_t;
  • ngx_conf_set_size_slot:解析一个数据大小(如:“8k”,“1m”),并保存为size_t;
  • ngx_conf_set_enum_slot:根据枚举定义将字符串翻译成ngx_int_t;
  • ngx_http_set_complex_value_slot:解析一个包含nginx变量的字符串并保存为ngx_http_complex_value_t;

2.4 存储位置

conf 参数它有三个可能的取值,分别如下:

NGX_HTTP_MAIN_CONF_OFFSET
NGX_HTTP_SRV_CONF_OFFSET
NGX_HTTP_LOC_CONF_OFFSET

这可不是随意指定的,如果你的type参数设置了NGX_HTTP_MAIN_CONF,那么这里就要设置为NGX_HTTP_MAIN_CONF_OFFSET。相应的,如果是NGX_HTTP_SRV_CONFNGX_HTTP_LOC_CONF,那么这里就要设置为NGX_HTTP_SRV_CONF_OFFSETNGX_HTTP_LOC_CONF_OFFSET

2.5 offset

表示数据具体保存在main_conf、srv_conf、loc_conf指向的结构体的哪个位置(offset偏移)。大家可能会问,这个main_conf等等怎么来的,nginx给我们挖的坑长得是个什么样子,这个我们在介绍ngx_http_hello_world_module_ctx会说到。

2.6 post

一个补充字段,一般不用的,填入NULL。只是对于某些特殊的处理函数,比如ngx_conf_set_enum_slot,会用这个指针来指向enum定义表。

最后不要忘了加上 ngx_null_command,以表示命令集合定义完成。

3 上下文定义

用到了 HTTP 模块,定义如下:

typedef struct {
    ngx_int_t   (*preconfiguration)(ngx_conf_t *cf); 
    ngx_int_t   (*postconfiguration)(ngx_conf_t *cf);

    void       *(*create_main_conf)(ngx_conf_t *cf);
    char       *(*init_main_conf)(ngx_conf_t *cf, void *conf);

    void       *(*create_srv_conf)(ngx_conf_t *cf);
    char       *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, void *conf);

    void       *(*create_loc_conf)(ngx_conf_t *cf);
    char       *(*merge_loc_conf)(ngx_conf_t *cf, void *prev, void *conf);
} ngx_http_module_t;

可看到有以下几个部分:

  • Pre configuration
  • Post configuration
  • create main configuration
  • init main configuration
  • create server configuration
  • merge server configuration
  • create location configuration
  • merge location configuration

它们都是函数指针,都可以为 NULL,不过我们的模块里用到的是:

// Structure for the HelloWorld context
static ngx_http_module_t ngx_http_hello_world_module_ctx = {
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    ngx_http_hello_world_create_loc_conf,
    ngx_http_hello_world_merge_loc_conf
};

这两个函数会在下一篇文章中介绍。

4 Reference

  1. http://forum.nginx.org/read.php?2,243
  2. http://blog.sina.com.cn/s/blog_7303a1dc0100x70t.html

-

转载请注明来自柳大的CSDN博客:Blog.CSDN.net/Poechant

-

分享到:
评论

相关推荐

    ngx_http_proxy_connect_module.zip

    ngx_http_proxy_connect_module是一个针对Nginx服务器的第三方模块,主要功能是支持HTTP代理的"CONNECT"方法。在默认情况下,Nginx仅处理HTTP和HTTPS请求,但不支持通过HTTP代理进行TCP连接,比如SSL/TLS隧道。这个...

    nginx限制连接数ngx_http_limit_conn_module模块1

    【Nginx 限制连接数 ngx_http_limit_conn_module 模块详解】 在互联网服务中,服务器经常面临流量异常、负载过大的情况,尤其在遭受大流量恶意攻击时,带宽的浪费、服务器压力的增大都会对业务造成严重影响。为了...

    lua-upstream-nginx-module, Nginx C 模块将Lua向ngx_lua公开,用于 Nginx upstreams.zip

    lua-upstream-nginx-module, Nginx C 模块将Lua向ngx_lua公开,用于 Nginx upstreams 电子邮件名称ngx_http_lua_upstream - Nginx MODULE,用于向 Nginx upstreams公开Lua到 ngx_lua目录NAME状态概要说明函数get_...

    ngx_lua_module-windows-1.1.2.0

    ngx_lua_module是一款强大的扩展模块,专为Nginx服务器设计,允许在Nginx配置文件中直接嵌入Lua脚本,极大地增强了Nginx的功能和灵活性。这个"ngx_lua_module-windows-1.1.2.0"是该模块的一个Windows版本,适应于...

    ngx_http_mytest_module.zip_nginx_world

    在本文中,我们将深入探讨如何进行Nginx的模块二次开发,特别关注“ngx_http_mytest_module.zip_nginx_world”这个示例项目。这个压缩包包含了一个基础的Nginx自定义模块,可以视为模块开发的"Hello, World!"级别...

    ngx_http_dav_ext_module.so

    ngx_http_dav_ext_module.so centos7 nginx 1.18 可以作为模块加载

    使用nginx作为http/https正向代理ipm包,包含ngx_http_proxy_connect_module 模块,第三方图片代理,带有缓存

    使用nginx作为http/https正向代理ipm包,包含ngx_http_proxy_connect_module 模块,附带了第三方图片代理配置,带有缓存,可直接做图片服务器 下载后执行:rpm -ivh nginx-1.12.2-1.el7_4.ngx.x86_64.rpm 打包教程:...

    ngx_devel_kit-0.3.0

    ngx_devel_kit(通常缩写为 NDK)是一个针对Nginx的模块开发工具集,它为构建自定义Nginx模块提供了便利。在Nginx生态系统中,NDK是一个重要的扩展工具,允许开发者利用C语言直接操作Nginx的内部结构,以实现更高级...

    ngx_stream_ssl_preread_module调研.docx

    NGX_STREAM_SSL_PREREAD_MODULE 是一个基于流媒体(Stream)实现的 SSL/TLS 协议 ClientHello 消息提取模块,主要用于提取 SNI(Server Name Indicate)或者 ALPN(Application Layer Protocol Negotiation,应用层...

    ngx_http_proxy_connect_module-master (2).zip

    用于nginx的http正向代理https使用的模块

    nginx-1.25.4-x86-64-ngx-http-proxy-connect-module

    增加了ngx_http_proxy_connect_module模块的,已经编译好的windows exe文件。 可以正向代理https请求。来源地址:https://github.com/dyq94310/nginx-build-msys2/releases 使用方法,放到从官网下的nginx windows...

    Nginx模块ngx_req_status

    ngx_req_status用来展示nginx请求状态信息,类似于apache的status,nginx自带的模块只能显示连接数等等信息,我们并不能知道到底有哪些请求、以及各url域名所消耗的带宽是多少。ngx_req_status提供了这些功能. 1、按...

    ngx_http_consistent_hash-master.zip

    "ngx_http_consistent_hash-master.zip" 是一个与 Nginx Web服务器相关的压缩包文件,其中包含了一个名为 "ngx_http_consistent_hash" 的第三方模块的源代码。"master" 指示这可能是该模块的主分支或最新版本。 **...

    Nginx的SQLite模块ngx_sqlite.zip

    ngx_sqlite 是嵌入 sqlite 数据库的 nginx 模块。通过强大的nginx server,可以使用http协议访问sqlite数据库。环境- sqlite 3- nginx-1.6.3 安装```sh $ git clone https://github.com/rryqszq4/ngx_sqlite.git...

    nginx缓存清除插件ngx_cache_purge.zip

    ngx_cache_purge 是 nginx 模块,此模块可以清理 nginx 的 FastCGI、proxy、 SCGI 和 uWSGI 的缓存。配置指令(相同位置语法)fastcgi_cache_purgesyntax: fastcgi_cache_purge on|off|<method> [from all|<ip> [.....

    ngx_stream_module.so

    nginx1.20.2

    ngx_http_captcha_module:用于生成验证码和验证验证码的Nginx模块

    此nginx模块可直接生成验证码和验证验证码,可在nginx配置中自定义验证码大小、长度、字体、过期时间等。此项目无需版权,可自由下载使用或二次开发。 安装方法: 1. $ cp ngx_...

    nginx_upstream_check_module-master.zip

    nginx自带是没有针对负载均衡后端节点的健康检查的,但是可以通过默认自带的ngx_http_proxy_module 模块和ngx_http_upstream_module模块中的相关指令来完成当后端节点出现故障时,自动切换到健康节点来提供访问。

    ngx_kafka_module, Nginx Kafka 模块,将日志日志数据发送到 Kafka 群集.zip

    ngx_kafka_module, Nginx Kafka 模块,将日志日志数据发送到 Kafka 群集 Nginx Kafka 模块 Nginx Kafka MODULE 用于接收 HTTP POST 数据并向 Kafka 传递消息。如果使用这里 MODULE 时存在任何问题,请随时向我发送...

Global site tag (gtag.js) - Google Analytics