nginx 将一个 HTTP 请求分为 11 个处理阶段,这样做让每一个 HTTP 模块可以仅仅专注于完成一个独立、简单的功能,而一个请求的完整处理过程可以由多个 HTTP 模块共同合作完成将一次 HTTP 请求划分为 11 个处理阶段,通过每个阶段内部多个 HTTP 模块流水式的处理请求

HTTP 处理阶段枚举类型 -- ngx_http_phases

  ngx_http_phases定义的11个阶段是有顺序的,必须按照其定义的顺序执行。同时也要意识到,并不是说一个用户请求最多只能经过11个
HTTP模块提供的ngx_http_handler_pt方法来处理,NGX_HTTP_POST_READ_PHASE、NGX_HTTP_SERVER_REWRITE_PHASE、NGX_HTTP_REWRITE_PHASE、
NGX_HTTP_PREACCESS_PHASE、NGX_HTTP_ACCESS_PHASE、NGX HTTP_CONTENT_PHASE、NGX_HTTP_LOG_PHASE这7个阶段可以包括任意多个处理方法
它们是可以同时作用于同一个用户请求的。而NGX_HTTP_FIND_CONFIG_PHASE、NGX_HTTP_POSTREWRITE_PHASE、NGX_HTTP_POST_ACCESS_PHASE、
NGX_HTTP_TRY_FILES_PHASE这4个阶段则不允许HTTP模块加入自己的ngx_http_handler_pt方法处理用户请求,它们仅由HTTP框架实现;

  NGX_HTTP_FIND_CONFIG_PHASE、NGX_HTTP_POSTREWRITE_PHASE、NGX_HTTP_POST_ACCESS_PHASE、NGX_HTTP_TRY_FILES_PHASE

这4个阶段则不允许HTTP模块加入自己的ngx_http_handler_pt方法处理用户请求--------------------

他们的会占用cmcf->phase_engine.handlers[]数组中的一个成员,见ngx_http_init_phase_handle

  typedef enum { //各个阶段的http框架check函数见ngx_http_init_phase_handlers //所有阶段的checker在ngx_http_core_run_phases中调用
//在接收到完整的HTTP头部后处理的HTTP阶段 主要是获取客户端真实IP,因为客户端到nginx可能通过了vanish等缓存,
//ngx_http_realip_module(ngx_http_realip_init->ngx_http_realip_handler)
NGX_HTTP_POST_READ_PHASE = 0, //该阶段方法有:ngx_http_realip_handler POST有"在....后"的意思,POST_READ应该就是在解析完请求行和头部行后 /*在还没有查询到URI匹配的location前,这时rewrite重写URL也作为一个独立的HTTP阶段 Server内请求地址重写阶段
在 URI 与 location 匹配前修改请求的 URI(重定向)*/
NGX_HTTP_SERVER_REWRITE_PHASE, //该阶段handler方法有:ngx_http_rewrite_module(ngx_http_rewrite_init->ngx_http_rewrite_handler) /*根据URI寻找匹配的location,这个阶段通常由ngx_http_core_module模块实现,不建议其他HTTP模块重新定义这一阶段的行为
// 根据请求 URI 匹配 location 表达式该阶段只能由 ngx_http_core_module 模块实现*/
NGX_HTTP_FIND_CONFIG_PHASE,//该阶段handler方法有:无,不允许用户添加hander方法在该阶段 该阶段完成的是Nginx的特定任务,即进行Location定位 //在NGX_HTTP_FIND_CONFIG_PHASE阶段寻找到匹配的location之后再修改请求的URI Location内请求地址重写阶段
/*在NGX_HTTP_FIND_CONFIG_PHASE阶段之后重写URL的意义与NGX_HTTP_SERVER_REWRITE_PHASE阶段显然是不同的,
因为这两者会导致查找到不同的location块(location是与URI进行匹配的) ----匹配 location 后修改请求 URI*/
NGX_HTTP_REWRITE_PHASE,//该阶段handler方法有:ngx_http_rewrite_handler
/*这一阶段是用于在rewrite重写URL后重新跳到NGX_HTTP_FIND_CONFIG_PHASE阶段,找到与新的URI匹配的location。所以,这一阶段是无法由第三方HTTP模块处理的,而仅由ngx_http_core_module模块使用*/
/*
这一阶段是用于在rewrite重写URL后,防止错误的nginx.conf配置导致死循环(递归地修改URI),因此,这一阶段仅由ngx_http_core_module模块处理。
目前,控制死循环的方式很简单,首先检查rewrite的次数,如果一个请求超过10次重定向,扰认为进入了rewrite死循环,这时在NGX_HTTP_POSTREWRITE_PHASE
阶段就会向用户返回500,表示服务器内部错误
*/
NGX_HTTP_POST_REWRITE_PHASE,//该阶段handler方法有:无,不允许用户添加hander方法在该阶段 /*
NGXHTTPPREACCESSPHASE、NGX_HTTP_ACCESS_PHASE、NGX HTTPPOST_ACCESS_PHASE,很好理解,做访问权限检查的前期、中期、后期工作,
其中后期工作是固定的,判断前面访问权限检查的结果(状态码存故在字段r->access_code内),如果当前请求没有访问权限,那么直接返回状
态403错误,所以这个阶段也无法去挂载额外的回调函数。
*/
//处理NGX_HTTP_ACCESS_PHASE阶段前,HTTP模块可以介入的处理阶段
NGX_HTTP_PREACCESS_PHASE,//该阶段handler方法有:ngx_http_degradation_handler ngx_http_limit_conn_handler ngx_http_limit_req_handler ngx_http_realip_handler /*这个阶段用于让HTTP模块判断是否允许这个请求访问Nginx服务器*/
NGX_HTTP_ACCESS_PHASE,//该阶段handler方法有:ngx_http_access_handler ngx_http_auth_basic_handler ngx_http_auth_request_handler
/*当NGX_HTTP_ACCESS_PHASE阶段中HTTP模块的handler处理方法返回不允许访问的错误码时(实际是NGX_HTTP_FORBIDDEN或者NGX_HTTP_UNAUTHORIZED),
这个阶段将负责构造拒绝服务的用户响应。所以,这个阶段实际上用于给NGX_HTTP_ACCESS_PHASE阶段收尾*/
NGX_HTTP_POST_ACCESS_PHASE,//该阶段handler方法有:无,不允许用户添加hander方法在该阶段 /*这个阶段完全是为了try_files配置项而设立的。当HTTP请求访问静态文件资源时,try_files配置项可以使这个请求顺序地访问多个静态文件资源,
如果某一次访问失败,则继续访问try_files中指定的下一个静态资源。另外,这个功能完全是在NGX_HTTP_TRY_FILES_PHASE阶段中实现的*/
NGX_HTTP_TRY_FILES_PHASE,//该阶段handler方法有:无,不允许用户添加hander方法在该阶段 /* 其余10个阶段中各HTTP模块的处理方法都是放在全局的ngx_http_core_main_conf_t结构体中的,也就是说,它们对任何一个HTTP请求都是有效的
NGX_HTTP_CONTENT_PHASE仅仅针对某种请求唯一生效 ngx_http_handler_pt处理方法不再应用于所有的HTTP请求,仅仅当用户请求的URI匹配了location时(也就是mytest配置项所在的location)才会被调用。
这也就意味着它是一种完全不同于其他阶段的使用方式。 因此,当HTTP模块实现了某个ngx_http_handler_pt处理方法并希望介入NGX_HTTP_CONTENT_PHASE阶
段来处理用户请求时,如果希望这个ngx_http_handler_pt方法应用于所有的用户请求,则应该在ngx_http_module_t接口的postconfiguration方法中,
向ngx_http_core_main_conf_t结构体的phases[NGX_HTTP_CONTENT_PHASE]动态数组中添加ngx_http_handler_pt处理方法;反之,如果希望这个方式
仅应用于URI匹配丁某些location的用户请求,则应该在一个location下配置项的回调方法中,把ngx_http_handler_pt方法设置到ngx_http_core_loc_conf_t
结构体的handler中。
注意ngx_http_core_loc_conf_t结构体中仅有一个handler指针,它不是数组,这也就意味着如果采用上述的第二种方法添加ngx_http_handler_pt处理方法,
那么每个请求在NGX_HTTP_CONTENT PHASE阶段只能有一个ngx_http_handler_pt处理方法。而使用第一种方法时是没有这个限制的,NGX_HTTP_CONTENT_PHASE阶
段可以经由任意个HTTP模块处理。
*/
//用于处理HTTP请求内容的阶段,这是大部分HTTP模块最喜欢介入的阶段 //CONTENT_PHASE阶段的处理回调函数ngx_http_handler_pt比较特殊,见ngx_http_core_content_phase
NGX_HTTP_CONTENT_PHASE, //该阶段handler方法有:ngx_http_autoindex_handler ngx_http_dav_handler ngx_http_gzip_static_handler ngx_http_index_handler ngx_http_random_index_handler ngx_http_static_handler /*处理完请求后记录日志的阶段。例如,ngx_http_log_module模块就在这个阶段中加入了一个handler处理方法,使得每个HTTP请求处理完毕后会记录access_log日志*/
NGX_HTTP_LOG_PHASE //该阶段handler方法有: ngx_http_log_handler
} ngx_http_phases;

  在 ngx_http_core_main_conf_t 有一个 ngx_http_phase_engine_t 类型的 phase_engine 字段和一个 ngx_http_phase_t 类型的 phases[NGX_HTTP_LOG_PHASE + 1] 数组
他们存储了 HTTP 处理过程中的所有回调函数,其中 phase_engine 控制运行过程中一个 HTTP 请求所要经过的 HTTP 处理阶段,
而 phase 数组则仅会在 nginx 启动过程中按照 11 个阶段的概念初始化 phase_engine 中的 handlers 数组

  通常,在任意一个ngx_http_phases阶段,都可以拥有零个或多个ngx_http_phase_handler_s结构体,其含义更接近于某个HTTP模块的处理方法。
一个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组成的数组

  ngx_http_phase_engine_t中保存了在当前nginx.conf配置下,一个用户请求可能经历的所有ngx_http_handler_pt处理方法,这是所有HTTP模块可以合作处理用户请求
的关键!这个ngx_http_phase_engine_t结构体是保存在全局的ngx_http_core_main_conf_t结构体中的

  在HTTP框架的初始化过程中,任何HTTP模块都可以在ngx_http_module_t接口的postconfiguration方法中将自定义的方法添加到handler动态数组中,这样,这个方法就会最
终添加到ngx_http_core_main_conf_t->phase_engine中

//空间创建及赋值参考ngx_http_init_phase_handlers
typedef struct { //ngx_http_phase_engine_t结构体是保存在全局的ngx_http_core_main_conf_t结构体中的
/* handlers是由ngx_http_phase_handler_t构成的数组首地址,它表示一个请求可能经历的所有ngx_http_handler_pt处理方法,
配合ngx_http_request_t结构体中的phase_handler成员使用(phase_handler指定了当前请求应当执行哪一个HTTP阶段)*/
ngx_http_phase_handler_t *handlers; /* 表示NGX_HTTP_SERVER_REWRITE_PHASE阶段第1个ngx_http_phase_handler_t处理方法在handlers数组中的序号,用于在执行HTTP请求
的任何阶段中快速跳转到NGX_HTTP_SERVER_REWRITE_PHASE阶段处理请求 */
ngx_uint_t server_rewrite_index; //赋值参考ngx_http_init_phase_handlers
/*
表示NGX_HTTP_REWRITE_PHASE阶段第1个ngx_http_phase_handler_t处理方法在handlers数组中的序号,用于在执行HTTP请求的任何阶段中
快速跳转到NGX_HTTP_REWRITE_PHASE阶段处理请求
*/
ngx_uint_t location_rewrite_index; //赋值参考ngx_http_init_phase_handlers
} ngx_http_phase_engine_t;

  一般来说,各个 HTTP 模块都是在 postconfiguration 方法中将自定义方法添加到 handler 动态数组中的,这样这个方法在 HTTP 框架初始化过程中最终会被添加到 phase_engine 中所有 postconfiguration 回调函数调用前,nginx 执行了 ngx_http_init_phases 初始化 phase 结构,然后在调用所有的 postconfiguration 回调函数以后执行了 ngx_http_init_phase_handlers 为 phase_engine 字段赋值;

/*
有7个HTTP阶段(NGX_HTTP_POST_READ_PHASE、NGX_HTTP_SERVER_REWRITE_PHASE、NGX_HTTP_REWRITE_PHASE、NGX_HTTP_PREACCESS_PHASE、
NGX_HTTP_ACCESS_PHASE、NGX_HTTP_CONTENT_PHASE、NGX_HTTP_LOG_PHASE)是允许任何一个HTTP模块实现自己的ngx_http_handler_pt处
理方法,并将其加入到这7个阶段中去的。在调用HTTP模块的postconfiguration方法向这7个阶段中添加处理方法前,需要先将phases数
组中这7个阶段里的handlers动态数组初始化(ngx_array_t类型需要执行ngx_array_init方法初始化),在这一步骤中,遁过调
用ngx_http_init_phases方法来初始化这7个动态数组。 通过调用所有HTTP模块的postconfiguration方法。HTTP模块可以在这一步骤中将自己的ngx_http_handler_pt处理方法添加到以上7个HTTP阶段中。
这样在具体的每个阶段就可以执行到我们的handler回调
*/
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;
}
/*
在各个HTTP模块能够介入的7个阶段中,实际上共享了4个checker方法:ngx_http_core_generic_phase、ngx_http_core_rewrite_phase、
ngx_http_core_access_phase、ngx_http_core_content_phase。这4个checker方法的主要任务在于,根据phase_handler执行某个HTTP模块实现的
回调方法,并根据方法的返回值决定下一步执行动作
*/
//cmcf->phases[]数组各个阶段的ngx_http_handler_pt节点信息全部赋值给cmcf->phase_engine.handlers数组队列
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) { //所有阶段的checker在ngx_http_core_run_phases中调用
/*
NGX_HTTP_SERVERREWRITEPHASE阶段,和第3阶段NGXHTTPREWRITE_PHASE都属于地址重写,也都是针对rewrite模块而设定的阶段,前
者用于server上下文里的地址重写,而后者用于location上下文里的地址重写。为什么要设置两个地址重写阶段,原因在于rewrite模块
的相关指令(比如rewrite、if、set等)既可用于server上下文.又可用于location上下文。在客户端请求被Nginx接收后,首先做server
查找与定位,在定位到server(如果没查找到就是默认server)后执行NGXHTTP_SERVER_REWRITEPHASE阶段上的回调函数,然后再进入到下
一个阶段:NGX_HTTP_FIND_CONFIG_PHASE阶段。
*/
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; /*
NGX_HTTP_FIND_CONFIG_PHASE、NGX_HTTP_POSTREWRITE_PHASE、NGX_HTTP_POST_ACCESS_PHASE、NGX_HTTP_TRY_FILES_PHASE这4个阶段则
不允许HTTP模块加入自己的ngx_http_handler_pt方法处理用户请求,但是他们的会占用cmcf->phase_engine.handlers[]数组中的一个成员 NGX_HTTP_FIND_CONFIG_PHASE阶段上不能挂载任何回调函数,因为它们永远也不 会被执行,该阶段完成的是Nginx的特定任务,即进行
Location定位。只有把当前请求的对应location找到了,才能以该location上下文中取出更多精确的用户配置值,做后续的进一步请求处理。
*/
case NGX_HTTP_FIND_CONFIG_PHASE: //该阶段则不允许HTTP模块加入自己的ngx_http_handler_pt方法处理用户请求方法,
//直接把http框架方法加入到cmcf->phase_engine.handlers数组中
find_config_index = n; ph->checker = ngx_http_core_find_config_phase; //
ph->phase = i;
n++; //所有处理方法数增加一次
ph++; //指向cmcf->phase_engine.handlers数组中下一个未用的ngx_http_phase_handler_t节点位置 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://该阶段则不允许HTTP模块加入自己的ngx_http_handler_pt方法处理用户请求方法,
//直接把http框架方法加入到cmcf->phase_engine.handlers数组中
if (use_rewrite) {
ph->checker = ngx_http_core_post_rewrite_phase;
ph->next = find_config_index;//注意:NGX_HTTP_POST_REWRITE_PHASE的下一阶段是NGX_HTTP_FIND_CONFIG_PHASE
ph->phase = i;
n++;
ph++;
}
continue; case NGX_HTTP_ACCESS_PHASE:
checker = ngx_http_core_access_phase;
n++;
break; case NGX_HTTP_POST_ACCESS_PHASE://该阶段则不允许HTTP模块加入自己的ngx_http_handler_pt方法处理用户请求方法,
//直接把http框架方法加入到cmcf->phase_engine.handlers数组中
if (use_access) {//只有配置了try_files aaa bbb后才会在 cmcf->phase_engine.handlers添加节点pt,
//见ngx_http_init_phase_handlers,如果没有配置,则直接跳过try_files阶段
ph->checker = ngx_http_core_post_access_phase;
ph->next = n;
ph->phase = i;
ph++;
} continue; case NGX_HTTP_TRY_FILES_PHASE://该阶段则不允许HTTP模块加入自己的ngx_http_handler_pt方法处理用户请求方法,
//直接把http框架方法加入到cmcf->phase_engine.handlers数组中
if (cmcf->try_files) {
ph->checker = ngx_http_core_try_files_phase;
ph->phase = i;
n++;
ph++;
} continue; case NGX_HTTP_CONTENT_PHASE:
checker = ngx_http_core_content_phase;
break; default: //NGX_HTTP_POST_READ_PHASE NGX_HTTP_PREACCESS_PHASE NGX_HTTP_LOG_PHASE默认都是该函数
checker = ngx_http_core_generic_phase;
} //计算i阶段的ngx_http_handler_pt处理方法在所有阶段处理方法中的位置,也就是计算i阶段的处理方法应该存放在cmcf->phase_engine.handlers数组中的具体位置
n += cmcf->phases[i].handlers.nelts; //注意:每一个阶段中最后加入到handlers[]中的会首先添加到cmcf->phase_engine.handlers
for (j = cmcf->phases[i].handlers.nelts - 1; j >=0; j--) {
ph->checker = checker; //每个阶段对应的checker,例如:NGX_HTTP_SERVER_REWRITE_PHASE阶段为ngx_http_core_rewrite_phase
//i阶段的所有ngx_http_handler_pt处理方法通过ph连接起来,也就是全部添加到cmcf->phase_engine.handlers数组中,各个成员通过ph->next连接在一起
ph->handler = h[j];
ph->phase = i;
ph->next = n;//下一阶段的第一个ngx_http_handler_pt处理方法在数组中的位置
ph++; //指向cmcf->phase_engine.handlers数组中下一个未用的ngx_http_phase_handler_t节点位置
}
} return NGX_OK;
}

nginx&http 第三章 ngx HTTP 请求的 11 个处理阶段的更多相关文章

  1. nginx&http 第三章 ngx 请求处理的 11 个阶段 --ngx_http_process_request& ngx_http_handler

    ngx_http_process_request如果设置了定时器则删除,既然所有的请求已经接收完毕,就不会再发生超时了 重设连接的读写回调函数 重设请求读事件回调函数 调用 ngx_http_hand ...

  2. nginx&http 第三章 ngx http ngx_http_process_request_line读取和处理HTTP头部的行

    在 ngx_http_wait_request_handler 的最后调用了 ngx_http_process_request_line 函数用来处理和解析这次请求的全文 在读事件被触发时,内核套接字 ...

  3. nginx&http 第三章 ngx 1-http ngx_http_wait_request_handler

    对于活跃的 HTTP 连接,在执行连接建立回调函数 ngx_http_init_connection 的过程中会执行 ngx_http_wait_request_handler 回调函数, 负责 HT ...

  4. nginx&http 第三章 ngx http 框架处理流程

    1. nginx 连接结构 ngx_connection_t 这个连接表示是客户端主动发起的.Nginx服务器被动接受的TCP连接,我们可以简单称其为被动连接.同时,在有些请求的处理过程中,Nginx ...

  5. nginx&http 第三章 ngx http ngx_http_process_request_headers

    HTTP 请求行正确处理完成后,针对 HTTP/1.0 及以上版本紧接着要做的就是请求 HEADER 的处理与解析了 /** * 用于处理http的header数据 * 请求头: * Host: lo ...

  6. nginx&http 第三章 ngx 事件http 初始化1

    在 http 配置块中,我们配置了 http 连接相关的信息,HTTP 框架也正是从这里启动的 在 nginx 初始化的过程中,执行了 ngx_init_cycle 函数,其中进行了配置文件解析,调用 ...

  7. nginx&http 第三章 ngx 事件event accept epoll /init

    tcp 三次握手成功后,listen fd  可读,在process_event_timer 中调用rev->handler(rev)处理: 其回调函数为: ngx_event_accept / ...

  8. nginx&http 第三章 ngx 事件event epoll 处理

    1. epoll模块命令集 ngx_epoll_commands  epoll模块上下文 ngx_epoll_module_ctx  epoll模块配置 ngx_epoll_module static ...

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

    Nginx将一个HTTP请求分成多个阶段.以模块为单位进行处理.这样做的优点是使处理过程更加灵活.减少耦合度.HTTP框架将处理分成了11个阶段,各个阶段能够包括随意多个HTTP模块并以流水线的方式处 ...

随机推荐

  1. Java 合并Word文档

    合并文档可以是将两个包含一定逻辑关系的文档合并成一个完整的文档,也可以是出于方便文档存储.管理的目的合并多个文档为一个文档.下面,就将以上文档操作需求,通过Java程序来实现Word文档合并.合并文档 ...

  2. 多测师讲解unittest介绍及自动化测试实现流程_高级讲师肖sir

    unittest框架介绍 unittest框架是python中一个标准的库中的一个模块,该模块包括许多的类如 test case类.test suit类.texttest runner类.textte ...

  3. 多测师讲解接口测试_F12中network里headers各项属性的含义——高级讲师肖sir

    General部分: Request URL:资源的请求url # Request Method:HTTP方法  Status Code:响应状态码  200(状态码) OK 301 - 资源(网页等 ...

  4. 多测师讲解自动化测试_rf节课内容_高级讲师肖sir

    *** Settings ***Library Selenium2LibraryLibrary OperatingSystem *** Variables ***${name} zhangsan@{l ...

  5. CentOS 7的安装与部署 01

    01 虚拟软件的安装与配置 虚拟机(Virtual Machine)指通过软件模拟的具有完整硬件系统功能的.运行在一个完全隔离环境中的完整计算机系统.在实体计算机中能够完成的工作在虚拟机中都能够实现. ...

  6. js 如何获取浏览器的高度?

    <SCRIPT LANGUAGE="JavaScript"><!--var s = ""; s += " 网页可见区域宽:" ...

  7. html中object标签

    首先将这个强大web页面打印例子(pintTest.html)贴上来. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional ...

  8. 【抽五分钟】使用VuePress创建在线文档中心

    内容目录 安装初始化核心配置导航栏配置侧边栏配置静态资源配置nginx部署typora编写 安装初始化 全局安装  npm install -g vuepress 创建目录 mkdir vurepre ...

  9. C# indexof和indexofany区别(转)

    定位子串是指在一个字符串中寻找其中包含的子串或者某个字符.在String类中,常用的定位子串和字符的方法包括IndexOf/LastIndexOf及IndexOfAny/LastIndexOfAny, ...

  10. SQL DELETE语句如何让表使用别名的方法

    DELETE 别名 FROM 表名称 别名 WHERE 列名称 = 值