本文共 2934 字,大约阅读时间需要 9 分钟。
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;
本文介绍一下各个阶段的一些具体的工作内容。
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头。
这是重写阶段,重写http请求的URI。在Nginx里面,重写主要是通过指令完成。而且Nginx中重写指令可以在server块或者location块中出现。执行server块中的指令就是在这个阶段。执行location块的指令在NGX_HTTP_REWRITE_PHASE阶段。而指令的代码都是存储在rewrite模块的loc_conf配置结构体中。
NGX_HTTP_FIND_CONFIG_PHASE
这个阶段根据URL找到对应的匹配location块。后续的处理就可以用这个location块配置的模块来处理http请求。
这个阶段直接参考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中保存的就是具体的重写指令。可以看到,这是一种多态的实现。
NGX_HTTP_POST_REWRITE_PHASE
这是完成重写之后的一些收尾工作
NGX_HTTP_PREACCESS_PHASE
这是进入NGX_HTTP_ACCESS_PHASE阶段前的应该完成的工作
NGX_HTTP_ACCESS_PHASE
这个阶段主要是做一些访问权限相关的处理。
NGX_HTTP_POST_ACCESS_PHASE
NGX_HTTP_ACCESS_PHASE阶段之后的的工作在这里完成
NGX_HTTP_TRY_FILES_PHASE
顺序访问多个静态文件资源阶段
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; }
NGX_HTTP_LOG_PHASE
日志阶段
一般是模块在它的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介入到各个阶段的。
转载地址:http://cpqxi.baihongyu.com/