返回
Featured image of post OpenResty 模块初始化

OpenResty 模块初始化

lua-nginx-module 模块的定义及初始化

lua_nginx_module 其实就是一个 Nginx 模块,定义及实现都需要按照 Nginx 模块的要求。

这篇文章的目的是什么呢?

  • 了解 lua-nginx-module 模块相关数据结构的定义。
  • 了解 lua-nginx-module 模块大致的初始化流程,对 lua-nginx-module 模块有一个总体的概念,然后我们在后续的文章中,去细化追究相关指令的细节。
    • 总分结构

定义

  • 定义个全局的模块变量:

ngx_http_lua_module.c 此结构的详细解释可见 Nginx 数据结构 ngx_module_t

ngx_module_t ngx_http_lua_module = {
    NGX_MODULE_V1,
    &ngx_http_lua_module_ctx,   /*  module context */
    ngx_http_lua_cmds,          /*  module directives */
    NGX_HTTP_MODULE,            /*  module type */
    NULL,                       /*  init master */
    NULL,                       /*  init module */
    ngx_http_lua_init_worker,   /*  init process */
    NULL,                       /*  init thread */
    NULL,                       /*  exit thread */
    ngx_http_lua_exit_worker,   /*  exit process */
    NULL,                       /*  exit master */
    NGX_MODULE_V1_PADDING
};
  • 定义一个模块上下文
static ngx_http_module_t ngx_http_lua_module_ctx = {
    NULL,                             /*  preconfiguration */
    ngx_http_lua_init,                /*  postconfiguration */

    ngx_http_lua_create_main_conf,    /*  create main configuration */
    ngx_http_lua_init_main_conf,      /*  init main configuration */

    ngx_http_lua_create_srv_conf,     /*  create server configuration */
    ngx_http_lua_merge_srv_conf,      /*  merge server configuration */

    ngx_http_lua_create_loc_conf,     /*  create location configuration */
    ngx_http_lua_merge_loc_conf       /*  merge location configuration */
};

可以看到被定义成了一个 HTTP 模块(NGX_HTTP_MODULE, ngx_http_module_t)。

main conf 见:ngx_http_lua_main_conf_t srv_conf 见:ngx_http_lua_srv_conf_t loc_conf 见:ngx_http_lua_loc_conf_t

  • 定义指令
static ngx_command_t ngx_http_lua_cmds[] = {

    { ngx_string("lua_load_resty_core"),
      NGX_HTTP_MAIN_CONF|NGX_CONF_FLAG,
      ngx_http_lua_load_resty_core,
      NGX_HTTP_MAIN_CONF_OFFSET,
      0,
      NULL },

    ...
}

初始化

接下来,我们粗略地了解一下 模块初始化进程初始化

模块初始化

Nginx 模块的初始化流程见:Nginx 模块初始化

简而言之就是:

  • 解析到相关配置指令(ngx_http_lua_cmds 数组中定义,如 init_by_lua),就执行指令的处理函数。
    • xxx_by_lua 指令的具体处理见后续的文章。
  • 调用 ngx_http_lua_init 这个 postconfiguration 函数(详见上文的“模块上下文 ngx_http_lua_module_ctx”)
    • init_by_lua 设置的 handler 在 postconfiguration。

我们来看下 ngx_http_lua_init 这个函数做了什么。

ngx_http_lua_init 执行流程

- ngx_http_lua_init
    \- if (lmcf->requires_rewrite):判断是否需要介入 rewrite 阶段的处理
    \- if (lmcf->requires_access):判断是否需要介入 access 阶段的处理
    \- if (lmcf->requires_log):判断是否需要介入 log 阶段的处理
        \- ngx_array_push:如果需要,就设置对应的 handler。
            \- 如:ngx_array_push(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers);
    \- if (multi_http_blocks || lmcf->requires_header_filter):判断是否需要接入 header_fitler 阶段
        \- ngx_http_lua_header_filter_init:如果需要介入,则会调用此函数把相关处理函数设置到调用链中。
    \= if (multi_http_blocks || lmcf->requires_body_filter):判断是否需要接入 body_fitler 阶段
        \- ngx_http_lua_body_filter_init:如果需要介入,则会调用此函数把相关处理函数设置到调用链中。
    \- ngx_pool_cleanup_add:添加内存池清理函数
    \- ngx_http_lua_pipe_init:初始化一颗红黑树,用于管道处理,见 [pipe](015-pipe.md)。
    \- ngx_http_lua_init_vm:如果没有初始化 Lua VM,则初始化。lua_State 设置在 lmcf->lua 中。
    \- init_handler(ngx_http_lua_init_by_inline):执行 Lua 代码

可以看到,配置解析完后(postconfiguration),立即初始化 Lua VM,然后调用了 ngx_http_lua_init_by_inline。 注意:上面并没有类似于 lmcf->requires_content 相关的判断,那么是 content 阶段不需要相关标记么?

进程初始化

从前面的模块定义可以看到 OpenResty 只指定了 ngx_http_lua_init_worker 和 ngx_http_lua_exit_worker 两个 worker 进程的处理函数。 配置解析完成后,会 fork 出子进程,然后调用 ngx_http_lua_init_worker 函数,我们来具体看看。

- ngx_http_lua_init_worker
    \- ngx_http_cycle_get_module_main_conf:获取主配置
    \- ngx_http_lua_pipe_add_signal_handler:添加信号处理函数,pipe  [pipe](015-pipe.md)
    \- init_worker_handler:执行对应的 Lua 代码

init_worker_handler 从哪里来的呢?是 init_worker_by_lua 指令设置的,这个我们在后续的文章中再去验证一下。

相信美好的事情即将发生。
Built with Hugo
Theme Stack designed by Jimmy