Nginx源码剖析--HTTP请求各阶段的具体作用

来源:互联网 发布:qq邮箱smtp设置 端口25 编辑:程序博客网 时间:2024/05/18 09:48

前言

Nginx将HTTP请求分为11各阶段进行处理。每个阶段包含零到多个handler处理函数。分阶段处理的目的是增加灵活性,方便模块介入。HTTP请求处理主要分为一下11个阶段:

typedef enum {    NGX_HTTP_POST_READ_PHASE = 0,    NGX_HTTP_SERVER_REWRITE_PHASE, //对server对应的uri的转换    NGX_HTTP_FIND_CONFIG_PHASE,     NGX_HTTP_REWRITE_PHASE,       //locations对应的URI的转换    NGX_HTTP_POST_REWRITE_PHASE,    NGX_HTTP_PREACCESS_PHASE,    NGX_HTTP_ACCESS_PHASE,    NGX_HTTP_POST_ACCESS_PHASE,    NGX_HTTP_TRY_FILES_PHASE,    NGX_HTTP_CONTENT_PHASE,    NGX_HTTP_LOG_PHASE} ngx_http_phases;

本文介绍一下各个阶段的一些具体的工作内容。

各个阶段的工作内容

  1. NGX_HTTP_POST_READ_PHASE

    这个阶段是在完整接收到HTTP请求之后的第一个处理阶段。目前Nginx的ngx_http_realip_module模块介入这个阶段,当然它是允许用户模块介入的。ngx_http_realip_module模块在postconfiguration函数中将它的ngx_http_realip_handler作为handler注入到流程当中。这个handler函数的主要作用是找到http请求的真是IP。具体可以参考HTTP请求的X-Forwarded-For头。

  2. NGX_HTTP_SERVER_REWRITE_PHASE

    这是重写阶段,重写http请求的URI。在Nginx里面,重写主要是通过指令完成。而且Nginx中重写指令可以在server块或者location块中出现。执行server块中的指令就是在这个阶段。执行location块的指令在NGX_HTTP_REWRITE_PHASE阶段。而指令的代码都是存储在rewrite模块的loc_conf配置结构体中。

  3. NGX_HTTP_FIND_CONFIG_PHASE

    这个阶段根据URL找到对应的匹配location块。后续的处理就可以用这个location块配置的模块来处理http请求。

  4. NGX_HTTP_REWRITE_PHASE

    这个阶段直接参考NGX_HTTP_SERVER_REWRITE_PHASE就可以了。 不过这里需要提一下的是,Nginx对这两个重写阶段的入口都是一样的,都是ngx_http_rewrite_handler,那是具体执行的时候是怎么区分这两个阶段的呢。其实不用区分,因为经过NGX_HTTP_FIND_CONFIG_PHASE和不经过NGX_HTTP_FIND_CONFIG_PHASE的请求对应的r->loc是不一样的。而r->loc数组中的rewrite模块对应的loc_conf中保存的就是具体的重写指令。可以看到,这是一种多态的实现。

  5. NGX_HTTP_POST_REWRITE_PHASE

    这是完成重写之后的一些收尾工作

  6. NGX_HTTP_PREACCESS_PHASE

    这是进入NGX_HTTP_ACCESS_PHASE阶段前的应该完成的工作

  7. NGX_HTTP_ACCESS_PHASE

    这个阶段主要是做一些访问权限相关的处理。

  8. NGX_HTTP_POST_ACCESS_PHASE

    NGX_HTTP_ACCESS_PHASE阶段之后的的工作在这里完成

  9. NGX_HTTP_TRY_FILES_PHASE

    顺序访问多个静态文件资源阶段

  10. NGX_HTTP_CONTENT_PHASE

    这个阶段一般是处理http请求的内容。另外需要说一下的是,这个阶段有两种介入方式:

   // ngx_http_core_content_phase    if (r->content_handler) {  // 这就是第一种介入方式        r->write_event_handler = ngx_http_request_empty_handler;        ngx_http_finalize_request(r, r->content_handler(r));        return NGX_OK;    }// 下面是后一种介入方式    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,                   "content phase: %ui", r->phase_handler);    rc = ph->handler(r);    if (rc != NGX_DECLINED) {        ngx_http_finalize_request(r, rc);        return NGX_OK;    }
  1. NGX_HTTP_LOG_PHASE

    日志阶段

http请求处理阶段的介入方式

一般是模块在它的postconfiguration函数中介入。介入方式就是将handler函数加入到ngx_http_core_module模块的main_conf的phases数组中,因为后面主要是根据这个数组初始化phase_engine.handlers。具体地可以参考下面这段代码:

ngx_http_rewrite_init(ngx_conf_t *cf){    ngx_http_handler_pt        *h;    ngx_http_core_main_conf_t  *cmcf;    cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);    h = ngx_array_push(&cmcf->phases[NGX_HTTP_SERVER_REWRITE_PHASE].handlers);    if (h == NULL) {        return NGX_ERROR;    }    *h = ngx_http_rewrite_handler;    h = ngx_array_push(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers);    if (h == NULL) {        return NGX_ERROR;    }    *h = ngx_http_rewrite_handler;    return NGX_OK;}

ngx_http_rewrite_init是rewrite模块的postconfiguration函数。

总结

这篇文章主要介绍了http请求处理过程中,各个阶段完成的工作。最后介绍了一下模块是如何将handler介入到各个阶段的。

原创粉丝点击