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. 本地环境Django配置问题

    Django本地环境出现的问题 当你的前端出现这个问题的时候 你只需要吧setting.py 中的DEBUG 改为 True,即可 我原来是是DEBUG = False 本人亲测有用!!!

  2. Python3.7有什么新变化

    https://docs.python.org/zh-cn/3/whatsnew/3.7.html

  3. Docker下部署springboot项目

    1.背景 如何在docker容器环境下部署一个springboot项目? 2.具体步骤 第一步:准备一个springboot项目的xxxx.jar包 jar包中用于测试的一个接口如下 第二步:编写Do ...

  4. 第二十四章 IPtables防火墙

    一.iptables防火墙基本概述 1.应用场景 1.主机安全2.端口转发/ip转发3.内部共享上网 2.iptables工作流程 1.配置防火墙规则可以添加在下面,也可以添加在前面,是有顺序的2.匹 ...

  5. 【Azure云服务 Cloud Service】Cloud Service的实例(VM)中的服务描述Software Protection 与 Windows Defender, 如何设置Windows Defender Antivirus服务

    1)Software Protection 与 Windows Defender是两个独立的服务.在Windows 服务中他们的描述分别为 Software Protection Enables th ...

  6. Unity实现代码控制音频播放

    前言 很久没说过Unity了,现在说一下Unity用代码控制音频播放 准备工作 1.需要播放的音频 2.给需要加声音的对象加Audio Source组件 3.新建Play脚本,并绑定需要播放声音的对象 ...

  7. linux 查看nginx的安装路径等信息

    做个随笔,记录一下. 想查看nginx的配置文件,但不知道nginx是安装在哪个目录下? ps -ef | grep nginx Linux在启动一个进程时,系统会在/proc下创建一个以PID命名的 ...

  8. update不能直接使用select的返回结果

    update不能直接使用select的返回结果,这是会报错的,这是SQL的语法规定的,若想在update中与select结合使用,sql需要这样写: 1.其中field1,field2为表中的字段名 ...

  9. Java网关服务-AIO(二)

    Java网关服务-AIO(二) 概述 AIO的特点就是用户程序注册一个事件后就可以做其他事情,当事件被内核执行并得到结果后,我们的CompletionHandler会在I/O回调线程中被自动调用,有点 ...

  10. java数据结构-04单循环链表

    单循环链表与单链表的不同是,单循环链表尾结点的next指向第一个结点(或头结点)  代码: 无头结点: public class SingleCircleLinkedList<E> ext ...