nginx的十一个阶段处理
2014-04-19 00:46
661 查看
nginx的源码确实比较难读,怎么说呢, 一大堆的函数回调指针,没有理清脉络,看源码就很费劲。
首先要弄清楚的就是要理顺nginx调用的主框架,nginx是以配置为中心的处理架构,想读懂,先了解配置。
言归正传,这里说nginx处理的是一个阶段,
以上每个阶段的处理都是一个数组回调。数据的初始化如下:
可以看到
以上几个阶段都没有做数组的初始化化。
还要说一点的是,真正执行的时候,并不是调用cmcf->phases处理的, 而是调用cmcf->phase_engine.handlers
phase_engine的初始化如下
从上面可以看到,nginx把所有阶段的回调函数组成了一个串行的执行函数数组。
cheker指针指向检测调用函数指针,hander指向该阶段的函数调用指针,next则指向下一阶段的ph索引。
当执行某一阶段到一半的时候,想跳到下一个阶段,只需要r->phase_handler = ph->next;
ph的返回值为NGX_OK时, 函数会跳出阶段的执行,但是在阶段执行的hander中却不是这样的。
NGX_DECLINED: 会直接执行下一个ph调用。
NGX_AGAIN: 会重复调用本ph
NGX_DOWN:终止阶段函数回调调用。
首先要弄清楚的就是要理顺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源码分析——http多阶段处理
- nginx 处理请求原理和每个阶段的意思
- Nginx基础. HTTP多阶段处理大致分析
- Nginx处理请求的11个阶段(agentzh的Nginx 教程学习记录)
- nginx的请求处理阶段 (90%)
- Nginx多阶段处理HTTP请求
- NGINX多阶段处理
- nginx的多阶段请求处理
- nginx 11个处理阶段 && nginx lua 8个处理阶段
- 文章13:Nginx多阶段处理HTTP请求
- 【Nginx】HTTP请求的11个处理阶段
- Nginx 请求处理阶段
- nginx的多阶段请求处理
- Nginx源码分析 - 实战篇 - 编写一个挂载到阶段处理的模块
- NGINX中HTTP请求的11个处理阶段
- Nginx源码剖析--HTTP请求的分阶段处理的初始化
- nginx源码分析--多阶段请求处理
- Nginx 事件驱动模块连接处理
- Nginx学习笔记--Nginx图片缩略图,水印处理模块
- Nginx 错误处理方法: bind() to 0.0.0.0:80 failed