Nginx基础. HTTP多阶段处理大致分析

本文深入探讨了Nginx HTTP请求的11个处理阶段,重点分析了哪些阶段允许HTTP模块添加自定义handler方法,并详细阐述了同一阶段内处理方法的checker逻辑及其返回值对框架行为的影响。
摘要由CSDN通过智能技术生成
HTTP处理阶段的规则:
对于每个HTTP阶段, 它都包括checker检查方法和handler处理方法
typedef struct ngx_http_phase_handler_s ngx_http_phase_handler_t;

//一个HTTP处理阶段中的checker方法, 仅可以由HTTP框架实现, 以此控制HTTP请求的处理流程.
typedef ngx_int_t (*ngx_http_phase_handler_pt)(ngx_http_request_t *r, ngx_http_phase_handler_t *ph);

//由HTTP模块实现的handler处理方法
typedef ngx_int_t (*ngx_http_handler_pt)(ngx_http_request_t *r);

//要注意的是, ngx_http_phase_handler_t结构体仅表示处理阶段中的一个处理方法
struct ngx_http_phase_handler_s{
          //在处理到某个HTTP处理阶段时, HTTP框架将会在checker方法已实现的前提下首先调用checker方法来处理请求. 而不会
          //直接调用任何阶段中的handler方法, 只有在checker方法中才会去调用handler方法
          //因此, 事实上所有的checker方法都是由框架中的ngx_http_core_module模块实现的
          //且普通的http模块无法重定义checker方法
        ngx_http_phase_handler_pt checker;
          //除ngx_http_core_Module模块之外的HTTP模块, 只能通过定义handler方法才能介入某个HTTP处理阶段以处理请求.
        ngx_http_handler_pt handler;
          //将要执行的下一个HTTP处理阶段的序号
          //使用来next就使得处理阶段不必按顺序依次执行了, 既可以向后跳跃多个阶段执行, 也可以跳到之前执行过的阶段重新执行
          //通常, next表示下一个处理阶段中第一个ngx_http_phase_handler_t处理方法
        ngx_uint_t next;
};

在任意一个ngx_http_phase阶段, 都可以拥有零个或多个ngx_http_phase_handler_t结构体.
一个http{}块解析完后, 就会根据nginx.conf中的配置产生由ngx_http_phase_handler_t组成的数组, 在处理HTTP请求时, 一般情况下这些阶段是顺序向后执行的, 但ngx_http_phase_handler_t结构体中的next成员使得他们可以非顺序执行. ngx_http_phase_engine_t结构体就是所有ngx_http_phase_handler_t组成的数组.
typedef struct {
          //这里的handlers表示由ngx_http_phase_handler_t组成的数组, 它表示一个请求可能经历的所有ngx_http_handler_pt处理方法
        ngx_http_phase_handler_t *handlers;
          //表示NGX_HTTP_SERVER_REWRITE_PHASE阶段第一个ngx_http_phase_handler_t处理方法在handlers中的序号, 用于在执行HTTP请求的任何阶段中快速跳转到NGX_HTTP_SERVER_REWRITE_PHASE阶段处理请求
        ngx_uint_t server_rewrite_index;
          //表示NGX_HTTP_REWRITE_PHASE阶段第一个ngx_http_phase_handler_t处理方法在handlers中的序号, 用于在执行HTTP请求的任何阶段中快速跳转到NGX_HTTP_REWRITE_PHASE阶段处理请求
        ngx_uint_t location_rewrite_index;
}ngx_http_phase_engine_t;
可见, 此结构体中保存来在当前nginx.conf下一个用户请求可能经历的所有ngx_http_handler_pt处理方法, 这个结构体是保存在全局的ngx_http_core_main_conf_t结构体中的
typedef struct  {
        ngx_http_phase_engine_t phase_engine;
        ngx_http_phase_t phase[NGX_HTTP_LOG_PHASE+1];
          ...
}ngx_http_core_main_conf_t;
这里的phase_engine成员控制运行过程中一个HTTP请求所要经过的HTTP处理阶段, 它将配合ngx_http_request_t结构体中的phase_handler成员使用(该成员指定了当前请求应当执行哪一个HTTP阶段)
在HTTP框架初始化的过程中, 任何HTTP模块都可以在ngx_http_module_t中的postconfiguration方法中将自定义的方法添加到handler动态数组中, 这样这个方法就会被最终添加到phase_engine中.


各阶段checker方法分析

下面先看一下各个阶段. 在11个阶段中有7个阶段是允许各个HTTP模块向阶段中任意添加自己实现的handler方法的.同一个阶段的所有handler方法都拥有相同的checker方法. 且每个阶段中的处理方法的返回值都会以不同的方式影响HTTP框架的行为. 下面是HTTP框架在首次从业务上处理请求方法中调用的ngx_http_core_run_phases方法.

void
ngx_http_core_run_phases(ngx_http_request_t *r)
{
    ngx_int_t                   rc;
    ngx_http_phase_handler_t   *ph;
    ngx_http_core_main_conf_t  *cmcf;

    cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);

    ph = cmcf->phase_engine.handlers;

    while (ph[r->phase_handler].checker) {

        rc = ph[r->phase_handler].checker(r, &ph[r->phase_handler]);

        if (rc == NGX_OK) {
            return;
        }
    }
}
(此方法在上面对各个结构体的介绍过后显得十分容易理解. 就是循环调用每个阶段的checker方法, 因此没作注释)
从该方法中可以看出, 方法只会调用每个处理阶段的checker方法, 而不会亲自执行每个阶段中的handler方法. 这是因为handler方法仅在checker方法中被执行, checker方法则由HTTP框架提供, 这样就可以控制各个HTTP模块实现的处理方法在不同的阶段采用不同的调用行为.
还可以看出的是, 如果checker方法返回NGX_OK, 那么整个循环就会结束. 这是因为在接收完HTTP头部后, 是很难在一次NGINX框架的调度中处理完成一个请求的. 在第一次接收完HTTP头部后, HTTP框架就调度ngx_http_process_request方法来对请求进行首次业务处理. ngx_http_core_run_phases方法中就是从中摘取出的. 当某个阶段的某个HTTP模块无法在这一次框架调度中完成任务时(对应的checker方法中的ngx_http_handler_pt可能返回NGX_AGAIN, 即表示需要读取更多的数据才能完成), 就不再继续调用HTTP模块的handler进行处理. 继而把控制权交还给NGINX框架, 当这个请求上对应的事件再次触发时, HTTP框架将执行ngx_http_request_handler方法开始继续处理请求而不是首次调用的ngx_http_process_request方法. 在ngx_http_request_handler方法中, 会从ngx_http_process_request方法断开的地方继续处理请求. 这里只是简单的描述, 更详细的以后会有.
下面就针对每个阶段进行了解.


1. NGX_HTTP_POST_READ_PHASE阶段.(可添加HTTP模块)
在接收到完整的HTTP头部后处理的阶段. 任意想要在NGX_HTTP_POST_READ_PHASE阶段处理请求的HTTP模块, 必须首先在ngx_http_core_main_conf_t中的phase[NGX_HTTP_POST_READ_PHASE]动态数组中添加自己实现的ngx_http_handler_pt方法.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值