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()会终止循环。
网友评论