美文网首页
nginx 源代码分析 (五)

nginx 源代码分析 (五)

作者: RonZheng2010 | 来源:发表于2021-06-20 11:13 被阅读0次

    1. phases

    nginx将数据处理过程划分为几个阶段(phase)。

    2. ngx_http_phase_handler_pt 与 ngx_http_handler_pt

    每个阶段可以挂接若干处理函数,ngx_http_core_run_phase() 按阶段调用这些函数。不管是Nginx自身的nginx_module,还是使用者的ngx_module,都可以挂接自己的处理函数。这个处理函数的原型定义是ngx_http_handler_pt。

    typedef ngx_int_t (*ngx_http_handler_pt)(ngx_http_request_t *r);
    

    挂接的位置是ngx_http_core_main_conf_t.phases[]数组,保存ngx_http_phase_t结构。Ngx_http_phase_t.handlers[]是一个ngx_http_phase_t数组,每个phase一个元素。Ngx_http_phase_t的成员handlers也是一个数组,该阶段的处理函数ngx_http_handler_pt都注册在这里。

    实际上处理http请求时,并不是使用ngx_http_core_main_conf_t.phases[],而是ngx_http_core_main_conf_t.phase_engine。Ngx_http_phase_engint_t.handlers是一个ngx_http_phase_handler_t。

    ngx_http_handler_pt只是ngx_module挂接的处理函数。Ngx_http_phase_handler_pt则是每个phase指定的校验函数。如果校验通过,校验函数才会调用处理函数。

    typedef ngx_int_t (*ngx_http_phase_handler_pt)(ngx_http_request_t *r, 
    ngx_http_phase_handler_t *ph);
    

    ngx_http_phase_handler_t包括了校验函数和处理函数。

    • 成员checker是phase校验函数。
    • 成员handler是处理函数。
    • 成员next指定每个ngx_http_phase_handler_t实例在http请求处理过程中的“下一站”。

    3. ngx_http_init_phases()

    ngx_http_init_phases() 初始化ngx_http_core_main_conf.phases[]中的处理函数数组。

    4. ngx_http_module_t::postconfiguration()

    在ngx_http_module_t::postconfiguration()中,nginx模块向ngx_http_core_main_conf_t.phases中,加入自己的的处理函数。对于ngx_http_auth_basic_module模块,就是ngx_http_auth_basic_init()。

    • 调用ngx_array_push(),向NGX_HTTP_ACCESS_PHASE阶段,加入处理函数ngx_http_auth_basic_handler。

    5. ngx_http_init_phase_handlers()

    ngx_http_init_phase_handlers()初始化ngx_core_main_conf_t.phase_engine.handlers[]。

    • 遍历ngx_http_core_main_conf_t.phases[],计算其中的处理函数数量。
    • 调用ngx_pcalloc()分配对应的ngx_http_phase_handler_t数组,也就是ngx_core_main_conf_t.phase_engine.handlers[]。
    • 遍历ngx_http_core_main_conf_t.phases[]数组,将其中的处理函数,一一复制到ngx_http_core_main_conf_t.phase_engine.handlers[]中,同时补充相应phase的校验函数。同时每个ngx_http_phase_handler_t的下一站,也就是它的成员next。

    这个过程的大致情形如下图。

    • 图左边的每个阶段为一个实线框, 每个阶段指定一个校验函数ngx_http_phase_handler_pt,一组处理函数ngx_http_handler_t。
    • 图右边,所有的ngx_http_phase_handler_t实际上是保存在同一个数组中。虚线框是为了使复制的关系看得更清楚。

    6. ngx_http_block()

    在ngx_http_block()中调用以上函数。

    如下是缺省情况(不定制或拓展nginx的功能)下,最后ngx_http_core_main_conf_t.phase_engine.handlers[]的布局。

    7. ngx_http_core_run_phases()

    ngx_http_core_run_phases() 在一个循环中访问ngx_http_core_main_conf_t.phase_engine.handlers[],调用其中的校验函数和处理函数。

    访问位置由ngx_http_request_t.phase_handler指定,这个值一开始为0,后来校验函数会改变它,所以ngx_http_core_run_phase()会在ngx_http_core_main_conf_t.phase_engine.handlers[]中跳转。

    校验函数和处理函数的一个例子是ngx_http_core_access_phase()和ngx_http_auth_basic_handler()。

    7.1 ngx_http_phase_handler_t::handler()

    在ngx_http_auth_basic_handler()中,

    • 调用ngx_http_auth_basic_user(),得到用户数据。
    • 调用ngx_open_file(),打开用户数据文件。
    • 在一个循环中调用ngx_read_file(),读取用户数据文件的记录。将请求中的用户信息与记录比较,看是否匹配。

    7.2 ngx_http_phase_handler_t::checker()

    在ngx_http_core_access_phase()中,

    • 调用当前ngx_http_phase_handler_t实例的handler函数,这里是ngx_http_auth_basic_handler()。

    • 根据handler函数的返回结果跳转,一般有三种情况。

      • 一是handler函数的结果不能确定怎么处理请求,所以ngx_http_request_t.phase_handler递增1。这样ngx_http_core_run_phases()的下一次循环,将跳转到数组phase_engine.handlers[]的下一个元素去执行。
      • 二是handler函数的结果确定本阶段的任务已经完成,所以请求ngx_http_request_t.phase_handler设置为当前ngx_http_phase_handler_t.next的值。这样ngx_http_core_run_phases()的下一次循环,将跳到该值指向的位置。这个值在ngx_http_init_phase_handlers()确定。
      • 三是handler函数的结果确定所有任务已经结束(比如请求失败),所以返回NGX_OK。这时ngx_http_core_run_phases()会终止循环。

    相关文章

      网友评论

          本文标题:nginx 源代码分析 (五)

          本文链接:https://www.haomeiwen.com/subject/sqiryltx.html