nginx的十一个阶段处理

原创 2014年04月19日 00:46:47

   nginx的源码确实比较难读,怎么说呢, 一大堆的函数回调指针,没有理清脉络,看源码就很费劲。

首先要弄清楚的就是要理顺nginx调用的主框架,nginx是以配置为中心的处理架构,想读懂,先了解配置。

   言归正传,这里说nginx处理的是一个阶段,

       

typedef enum {
    NGX_HTTP_POST_READ_PHASE = 0,   //读取请求头

    NGX_HTTP_SERVER_REWRITE_PHASE,   //执行rewrite

    NGX_HTTP_FIND_CONFIG_PHASE,  //根据uri替换location
    NGX_HTTP_REWRITE_PHASE,      //根据替换结果继续执行rewrite
    NGX_HTTP_POST_REWRITE_PHASE, //执行rewrite后处理

    NGX_HTTP_PREACCESS_PHASE,    //认证预处理   请求限制,连接限制

    NGX_HTTP_ACCESS_PHASE,       //认证处理
    NGX_HTTP_POST_ACCESS_PHASE,  //认证后处理, 认证不通过, 丢包

    NGX_HTTP_TRY_FILES_PHASE,    //尝试try标签
    NGX_HTTP_CONTENT_PHASE,      //内容处理

    NGX_HTTP_LOG_PHASE           //日志处理
} ngx_http_phases;

以上每个阶段的处理都是一个数组回调。数据的初始化如下:

static ngx_int_t
ngx_http_init_phases(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
{
    if (ngx_array_init(&cmcf->phases[NGX_HTTP_POST_READ_PHASE].handlers,
                       cf->pool, 1, sizeof(ngx_http_handler_pt))
        != NGX_OK)
    {
        return NGX_ERROR;
    }

    if (ngx_array_init(&cmcf->phases[NGX_HTTP_SERVER_REWRITE_PHASE].handlers,
                       cf->pool, 1, sizeof(ngx_http_handler_pt))
        != NGX_OK)
    {
        return NGX_ERROR;
    }

    if (ngx_array_init(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers,
                       cf->pool, 1, sizeof(ngx_http_handler_pt))
        != NGX_OK)
    {
        return NGX_ERROR;
    }

    if (ngx_array_init(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers,
                       cf->pool, 1, sizeof(ngx_http_handler_pt))
        != NGX_OK)
    {
        return NGX_ERROR;
    }

    if (ngx_array_init(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers,
                       cf->pool, 2, sizeof(ngx_http_handler_pt))
        != NGX_OK)
    {
        return NGX_ERROR;
    }

    if (ngx_array_init(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers,
                       cf->pool, 4, sizeof(ngx_http_handler_pt))
        != NGX_OK)
    {
        return NGX_ERROR;
    }

    if (ngx_array_init(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers,
                       cf->pool, 1, sizeof(ngx_http_handler_pt))
        != NGX_OK)
    {
        return NGX_ERROR;
    }

    return NGX_OK;
}

可以看到

 NGX_HTTP_FIND_CONFIG_PHASE,  //根据uri替换location
 NGX_HTTP_POST_REWRITE_PHASE, //执行rewrite后处理
 NGX_HTTP_POST_ACCESS_PHASE,  //认证后处理, 认证不通过, 丢包

以上几个阶段都没有做数组的初始化化。

还要说一点的是,真正执行的时候,并不是调用cmcf->phases处理的, 而是调用cmcf->phase_engine.handlers
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不为NGX_OK就继续执行。
            return;
        }
    }
}

phase_engine的初始化如下
static ngx_int_t
ngx_http_init_phase_handlers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
{
    ngx_int_t                   j;
    ngx_uint_t                  i, n;
    ngx_uint_t                  find_config_index, use_rewrite, use_access;
    ngx_http_handler_pt        *h;
    ngx_http_phase_handler_t   *ph;
    ngx_http_phase_handler_pt   checker;

    cmcf->phase_engine.server_rewrite_index = (ngx_uint_t) -1;
    cmcf->phase_engine.location_rewrite_index = (ngx_uint_t) -1;
    find_config_index = 0;
    use_rewrite = cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers.nelts ? 1 : 0;
    use_access = cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers.nelts ? 1 : 0;

    n = use_rewrite + use_access + cmcf->try_files + 1 /* find config phase */;

    for (i = 0; i < NGX_HTTP_LOG_PHASE; i++) {
        n += cmcf->phases[i].handlers.nelts;
    }

    ph = ngx_pcalloc(cf->pool,
                     n * sizeof(ngx_http_phase_handler_t) + sizeof(void *));
    if (ph == NULL) {
        return NGX_ERROR;
    }

    cmcf->phase_engine.handlers = ph;
    n = 0;

    for (i = 0; i < NGX_HTTP_LOG_PHASE; i++) {
        h = cmcf->phases[i].handlers.elts;

        switch (i) {

        case NGX_HTTP_SERVER_REWRITE_PHASE:
            if (cmcf->phase_engine.server_rewrite_index == (ngx_uint_t) -1) {
                cmcf->phase_engine.server_rewrite_index = n;
            }
            checker = ngx_http_core_rewrite_phase;

            break;

        case NGX_HTTP_FIND_CONFIG_PHASE:
            find_config_index = n;

            ph->checker = ngx_http_core_find_config_phase;
            n++;
            ph++;

            continue;

        case NGX_HTTP_REWRITE_PHASE:
            if (cmcf->phase_engine.location_rewrite_index == (ngx_uint_t) -1) {
                cmcf->phase_engine.location_rewrite_index = n;
            }
            checker = ngx_http_core_rewrite_phase;

            break;

        case NGX_HTTP_POST_REWRITE_PHASE:
            if (use_rewrite) {
                ph->checker = ngx_http_core_post_rewrite_phase;
                ph->next = find_config_index;
                n++;
                ph++;
            }

            continue;

        case NGX_HTTP_ACCESS_PHASE:
            checker = ngx_http_core_access_phase;
            n++;
            break;

        case NGX_HTTP_POST_ACCESS_PHASE:
            if (use_access) {
                ph->checker = ngx_http_core_post_access_phase;
                ph->next = n;
                ph++;
            }

            continue;

        case NGX_HTTP_TRY_FILES_PHASE:
            if (cmcf->try_files) {
                ph->checker = ngx_http_core_try_files_phase;
                n++;
                ph++;
            }

            continue;

        case NGX_HTTP_CONTENT_PHASE:
            checker = ngx_http_core_content_phase;
            break;

        default:
            checker = ngx_http_core_generic_phase;
        }

        n += cmcf->phases[i].handlers.nelts;

        for (j = cmcf->phases[i].handlers.nelts - 1; j >=0; j--) {
            ph->checker = checker;
            ph->handler = h[j];  //数组是反向赋值的,刚好对应了数组操作的顺序
            ph->next = n;        //next永远执行下一个阶段的执行索引
            ph++;
        }
    }

    return NGX_OK;
}

从上面可以看到,nginx把所有阶段的回调函数组成了一个串行的执行函数数组。
cheker指针指向检测调用函数指针,hander指向该阶段的函数调用指针,next则指向下一阶段的ph索引。
当执行某一阶段到一半的时候,想跳到下一个阶段,只需要r->phase_handler = ph->next;

ph的返回值为NGX_OK时, 函数会跳出阶段的执行,但是在阶段执行的hander中却不是这样的。

NGX_DECLINED:   会直接执行下一个ph调用。
NGX_AGAIN:  会重复调用本ph
NGX_DOWN:终止阶段函数回调调用。

相关文章推荐

nginx 11个处理阶段 && nginx lua 8个处理阶段

nginx 11个处理阶段 nginx lua 8个处理阶段

nginx的多阶段请求处理

读取完请求头后,nginx进入请求的处理阶段。简单的情况下,客户端发送过的统一资源定位符(url)对应服务器上某一路径上的资源,web服务器需要做的仅仅是将url映射到本地文件系统的路径,然后读取相应...
  • fengmo_q
  • fengmo_q
  • 2013年02月21日 17:43
  • 11647

nginx http请求的PHASE深度解析

原文出处:http://www.xuebuyuan.com/1722415.html 当客户端的一个request到达服务器的时候,可以想象一下,一个服务器应该怎么处理这个请求呢?nginx又是怎么处...

Nginx的phase初始化

在前面的文章,我们知道当Nginx获取到连接后,会首先对连接的请求进行处理,例如读取请求的uri,参数等,然后会调用ngx_http_core_run_phases函数对于该请求跑一遍phase,当所...

【Nginx】HTTP请求的11个处理阶段

Nginx将一个HTTP请求分成多个阶段,以模块为单位进行处理。这样做的好处是使处理过程更加灵活、降低耦合度。HTTP框架将处理分成了11个阶段,各个阶段以流水线的方式处理请求。这11个HTTP阶段如...

NGINX中HTTP请求的11个处理阶段

Nginx的模块化设计使得每一个HTTP模块可以仅专注于完成一个独立的、简单的功能,而一个请求的完整处理过程可以由无数个HTTP模块共同合作完成。这种设计有非常好的简单性、可测试性、可扩展性,然而,当...

《深入理解Nginx》笔记之 HTTP请求的11个处理阶段

HTTP请求的11个处理阶段typedef enum { // 接收到完整的HTTP头部后处理阶段 NGX_HTTP_POST_READ_PHASE = 0, // 将请求URI...
  • yzt33
  • yzt33
  • 2015年08月05日 09:19
  • 638

nginx-lua 运行阶段

Nginx 处理请求的过程一共划分为 11 个阶段,按照执行顺序依次是{ post-read、[Nginx 读取并解析完请求头(request headers)之后就立即开始运行 server-re...

nginx-lua 运行阶段

Nginx 处理请求的过程一共划分为 11 个阶段,按照执行顺序依次是
  • uisoul
  • uisoul
  • 2017年03月15日 18:46
  • 360

Nginx中http请求的处理过程

1.补充点: 如果不指定ngx_http_core_loc_conf_t ->handler,那么请求转发到默认的content phase中的handler(如ngx_http_ind...
  • eric_za
  • eric_za
  • 2014年12月25日 17:22
  • 2284
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:nginx的十一个阶段处理
举报原因:
原因补充:

(最多只允许输入30个字)