- 浏览: 1400232 次
- 性别:
- 来自: 火星
文章分类
最新评论
-
aidd:
内核处理time_wait状态详解 -
ahtest:
赞一下~~
一个简单的ruby Metaprogram的例子 -
itiProCareer:
简直胡说八道,误人子弟啊。。。。谁告诉你 Ruby 1.9 ...
ruby中的类变量与类实例变量 -
dear531:
还得补充一句,惊群了之后,数据打印显示,只有一个子线程继续接受 ...
linux已经不存在惊群现象 -
dear531:
我用select试验了,用的ubuntu12.10,内核3.5 ...
linux已经不存在惊群现象
这次我们来看各个phase的checker的处理。
首先我们要弄明白一个事情,那就是在nginx中,一般来说,都是在NGX_HTTP_CONTENT_PHASE中调用outputfilter的,也就是说filter是在handler中调用的,这样看来只能有一个handler能够执行outputfiler.所以说在写nginx的handler模块的话,要注意不同的phase的返回值代表的不同意思。
而当ngx_http_core_run_phases返回,也就是某个phase的checker返回了NGX_OK的话,那么也就代表当前的请求已经处理结束。
按照顺序来。
首先是ngx_http_core_generic_phase,他主要是处理下面几个phase:
这些phase的含义就不介绍了,前一篇blog已经有详细说明了。
在这几个phase的checker中,它将所要执行的handler的返回值分为4种类型。
1 NGX_OK 此时返回NGX_AGAIN,这里我们知道如果checker返回ok的话,整个handler的处理就会直接返回,也就是这次处理结束。并且这里phase_handler被赋值为ph->next,也就是下一个phase的索引。也就是说下次将会调用它的下一个phase的checker。
2 NGX_DECLINED 此时也返回NGX_AGAIN,而这个和上面有所不同,那就是phase_handler的赋值,这里这个值只是简单的++,也就是说会紧接着处理当前phase的下一个phase,只有当前的phase的handelr处理完毕了,才可能会处理下一个phase的handler
3 NGX_AGAIN 或者NGX_DONE,这个的话直接返回OK,也就是会结束handler的处理。
4 剩余的情况,主要是处理NGX_ERROR,以及NGX_HTTP_(也就是返回一些http的状态码)的处理。
这里我们会发现有一个ngx_http_finalize_request函数,顾名思义,这个函数就是用来释放request的,比如request相关的内存池,比如需要返回的一些状态码,比如需要断开连接等等操作,这个函数我们会在后面的专门分析nginx关闭request(包括handler以及filter)时会详细分析。
接着来看NGX_HTTP_FIND_CONFIG_PHASE这个phase的checker。
这个phase对应的checker是ngx_http_core_find_config_phase.
由于nginx中location的处理还是一个很复杂的过程,而这里我们主要来看phase的处理,因此这里就介绍下location这个phase的处理,后面会有更详细的分析location。
这个checker主要作用是讲url和对应得location关联起来,其实也就是讲对应的location的命令关联起来,nginx这里location的实现是用一个tree来做得,这里就不详细分析location的实现了。主要来看这个phase的处理。
这个checker有可能会被调用多次的。因为每次url的改变都会改变对应的location,因此在前一篇里面,我们能看到专门有个find_config_index的索引,来供其他的phase调用。
注意这个phase只会有一个handler也就是ngx_http_core_find_location,checker中调用这个handler来挂载对应的location。
然后通过find_location的返回值来进行不同的操作,比如当返回error的时候,就需要调用ngx_http_finalize_request来回收请求。
接下来我们来看NGX_HTTP_POST_REWRITE_PHASE这个phase的checker,ngx_http_core_post_rewrite_phase。
这个rewrite phase主要是用来进行一些校验,比如rewrite的最大次数,如果大于这个次数,则会直接finalize request。
这里有几个变量需要注意:
uri_changed:表示当前的uri是否有改变,也就是是否有被重定向。
uri_changes:这个的初始值是11,它的意思就是最多的rewrite次数是10次。
然后是NGX_HTTP_ACCESS_PHASE这个phase的checker,ngx_http_core_access_phase。
这个chekcer的主要逻辑也是比较简单,就是通过handler的返回值来进行不同的操作。不过这里她还有一些自己特殊处理的部分,先来看相关的两个域:
1 satisfy 这个域对应于命令satisfy_any(这个已经被deprecated)和satisfy(建议使用这个)。其中它的默认值就是NGX_HTTP_SATISFY_ALL.这个命令的意思是如果值为all,则必须满足所有的验证,为any,则只满足一个就可以通过。
2 access_code 这个主要是传递给下一个phase,post_access phase进行处理的。
然后来看它的返回值。
1 NGX_DECLINED 表示由于一些原因,access没有进行,此时则直接返回again,然后继续下面的access。
2 NGX_AGAIN 和NGX_DONE 找了下貌似access模块没有返回这两个的情况,不过我们只要知道如果要handler直接终止的话,返回这两个就ok了。
3 NGX_OK 表示通过access验证。
4 其他,比如error 以及一些http的错误吗等, 就交给ngx_http_finalize_request处理。
access phase主要是用来验证当前的请求是否允许通过。来看代码
然后是NGX_HTTP_ACCESS_PHASE这个phase的checker,ngx_http_core_post_access_phase。这里要注意,只有use_access才会调用这个checker的,不然的话,checker链中就没有这个phase的。
这个phase比较简单,主要是处理access_code,也就是access phase中设置的access_code.
然后就是NGX_HTTP_TRY_FILES_PHASE这个phase的checker,ngx_http_core_try_files_phase。
这个phase的代码有点小多,不过逻辑还是比较简单的,那就是如果请求文件不在的话,则会打开try_file定义的location然后调用对应的文件,最后正常返回,也就是返回AGAIN.
最后就是NGX_HTTP_CONTENT_PHASE的checker,ngx_http_core_content_phase。
这个phase一般来说,我们编写的大部分handler都是属于这个phase的,他就是用来生成内容。
不过这里要注意一个域content_handler,如果这个handler存在的话,整个content phase就会只执行这一个handler,然后返回NGX_OK.
然后来分析handler返回值。
1 NGX_DONE 此时说明handler执行成功。
2 NGX_DECLINED 此时表示需要执行本phase的下一个handler
3 其他,此时需要finalize request。
来看代码
首先我们要弄明白一个事情,那就是在nginx中,一般来说,都是在NGX_HTTP_CONTENT_PHASE中调用outputfilter的,也就是说filter是在handler中调用的,这样看来只能有一个handler能够执行outputfiler.所以说在写nginx的handler模块的话,要注意不同的phase的返回值代表的不同意思。
而当ngx_http_core_run_phases返回,也就是某个phase的checker返回了NGX_OK的话,那么也就代表当前的请求已经处理结束。
按照顺序来。
首先是ngx_http_core_generic_phase,他主要是处理下面几个phase:
引用
post read, server rewrite, rewrite, and pre-access phases
这些phase的含义就不介绍了,前一篇blog已经有详细说明了。
在这几个phase的checker中,它将所要执行的handler的返回值分为4种类型。
1 NGX_OK 此时返回NGX_AGAIN,这里我们知道如果checker返回ok的话,整个handler的处理就会直接返回,也就是这次处理结束。并且这里phase_handler被赋值为ph->next,也就是下一个phase的索引。也就是说下次将会调用它的下一个phase的checker。
2 NGX_DECLINED 此时也返回NGX_AGAIN,而这个和上面有所不同,那就是phase_handler的赋值,这里这个值只是简单的++,也就是说会紧接着处理当前phase的下一个phase,只有当前的phase的handelr处理完毕了,才可能会处理下一个phase的handler
3 NGX_AGAIN 或者NGX_DONE,这个的话直接返回OK,也就是会结束handler的处理。
4 剩余的情况,主要是处理NGX_ERROR,以及NGX_HTTP_(也就是返回一些http的状态码)的处理。
ngx_int_t ngx_http_core_generic_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph) { ngx_int_t rc; //调用handler rc = ph->handler(r); //处理NGX_OK if (rc == NGX_OK) { //下一个phase的索引 r->phase_handler = ph->next; return NGX_AGAIN; } //处理NGX_DECLINED if (rc == NGX_DECLINED) { //处理本phase的下一个handler r->phase_handler++; return NGX_AGAIN; } //直接返回OK if (rc == NGX_AGAIN || rc == NGX_DONE) { return NGX_OK; } /* rc == NGX_ERROR || rc == NGX_HTTP_... */ //剩余的情况。 ngx_http_finalize_request(r, rc); return NGX_OK; }
这里我们会发现有一个ngx_http_finalize_request函数,顾名思义,这个函数就是用来释放request的,比如request相关的内存池,比如需要返回的一些状态码,比如需要断开连接等等操作,这个函数我们会在后面的专门分析nginx关闭request(包括handler以及filter)时会详细分析。
接着来看NGX_HTTP_FIND_CONFIG_PHASE这个phase的checker。
这个phase对应的checker是ngx_http_core_find_config_phase.
由于nginx中location的处理还是一个很复杂的过程,而这里我们主要来看phase的处理,因此这里就介绍下location这个phase的处理,后面会有更详细的分析location。
这个checker主要作用是讲url和对应得location关联起来,其实也就是讲对应的location的命令关联起来,nginx这里location的实现是用一个tree来做得,这里就不详细分析location的实现了。主要来看这个phase的处理。
这个checker有可能会被调用多次的。因为每次url的改变都会改变对应的location,因此在前一篇里面,我们能看到专门有个find_config_index的索引,来供其他的phase调用。
注意这个phase只会有一个handler也就是ngx_http_core_find_location,checker中调用这个handler来挂载对应的location。
然后通过find_location的返回值来进行不同的操作,比如当返回error的时候,就需要调用ngx_http_finalize_request来回收请求。
ngx_int_t ngx_http_core_find_config_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph) { u_char *p; size_t len; ngx_int_t rc; ngx_http_core_loc_conf_t *clcf; r->content_handler = NULL; r->uri_changed = 0; //find location rc = ngx_http_core_find_location(r); if (rc == NGX_ERROR) { //回收request,然后返回OK,也就是停止handler的处理。 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NGX_OK; } clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); //如果当前的请求不是internal,可是location却是内部请求,此时和error处理一样。 if (!r->internal && clcf->internal) { ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND); return NGX_OK; } ..................................................... }
接下来我们来看NGX_HTTP_POST_REWRITE_PHASE这个phase的checker,ngx_http_core_post_rewrite_phase。
这个rewrite phase主要是用来进行一些校验,比如rewrite的最大次数,如果大于这个次数,则会直接finalize request。
这里有几个变量需要注意:
uri_changed:表示当前的uri是否有改变,也就是是否有被重定向。
uri_changes:这个的初始值是11,它的意思就是最多的rewrite次数是10次。
ngx_int_t ngx_http_core_post_rewrite_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph) { ngx_http_core_srv_conf_t *cscf; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "post rewrite phase: %ui", r->phase_handler); //如果没有rewrite的话,直接返回again,继续接下来的handler处理。 if (!r->uri_changed) { r->phase_handler++; return NGX_AGAIN; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "uri changes: %d", r->uri_changes); //changes减减。 r->uri_changes--; //如果为0,则说明rewrite太多次数,此时就直接finalize request if (r->uri_changes == 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "rewrite or internal redirection cycle " "while processing \"%V\"", &r->uri); ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NGX_OK; } //否则进入下一个phase的处理,这里我们知道如果有use_rewrite,它的下一个phase是NGX_HTTP_FIND_CONFIG_PHASE。 r->phase_handler = ph->next; cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); //重新给loc conf赋值 r->loc_conf = cscf->ctx->loc_conf; //然后返回again,继续下面的handler处理。 return NGX_AGAIN; }
然后是NGX_HTTP_ACCESS_PHASE这个phase的checker,ngx_http_core_access_phase。
这个chekcer的主要逻辑也是比较简单,就是通过handler的返回值来进行不同的操作。不过这里她还有一些自己特殊处理的部分,先来看相关的两个域:
1 satisfy 这个域对应于命令satisfy_any(这个已经被deprecated)和satisfy(建议使用这个)。其中它的默认值就是NGX_HTTP_SATISFY_ALL.这个命令的意思是如果值为all,则必须满足所有的验证,为any,则只满足一个就可以通过。
2 access_code 这个主要是传递给下一个phase,post_access phase进行处理的。
然后来看它的返回值。
1 NGX_DECLINED 表示由于一些原因,access没有进行,此时则直接返回again,然后继续下面的access。
2 NGX_AGAIN 和NGX_DONE 找了下貌似access模块没有返回这两个的情况,不过我们只要知道如果要handler直接终止的话,返回这两个就ok了。
3 NGX_OK 表示通过access验证。
4 其他,比如error 以及一些http的错误吗等, 就交给ngx_http_finalize_request处理。
access phase主要是用来验证当前的请求是否允许通过。来看代码
ngx_int_t ngx_http_core_access_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph) { ngx_int_t rc; ngx_http_core_loc_conf_t *clcf; //r->main不等于r则表示是子请求。 if (r != r->main) { r->phase_handler = ph->next; return NGX_AGAIN; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "access phase: %ui", r->phase_handler); //调用handler rc = ph->handler(r); //如果返回declined,则会接下来的handler处理。 if (rc == NGX_DECLINED) { r->phase_handler++; return NGX_AGAIN; } //返回ok,终止handler的处理。 if (rc == NGX_AGAIN || rc == NGX_DONE) { return NGX_OK; } clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); //如果为all,则说明必须全部的access满足。 if (clcf->satisfy == NGX_HTTP_SATISFY_ALL) { //如果通过一个则继续本phase的下一个handler验证。 if (rc == NGX_OK) { r->phase_handler++; return NGX_AGAIN; } } else { if (rc == NGX_OK) { //清零access_code码。 r->access_code = 0; if (r->headers_out.www_authenticate) { r->headers_out.www_authenticate->hash = 0; } //否则满足一个access就可以通过,所以下一个handler为下一个phase的handler。 r->phase_handler = ph->next; return NGX_AGAIN; } //如果没有通过 if (rc == NGX_HTTP_FORBIDDEN || rc == NGX_HTTP_UNAUTHORIZED) { //则设置access_code,这里可以看到如果多个handler都没通过,则access_code为最后一个 r->access_code = rc; //本phase的下一个handler r->phase_handler++; return NGX_AGAIN; } } /* rc == NGX_ERROR || rc == NGX_HTTP_... */ //最后清理request ngx_http_finalize_request(r, rc); return NGX_OK; }
然后是NGX_HTTP_ACCESS_PHASE这个phase的checker,ngx_http_core_post_access_phase。这里要注意,只有use_access才会调用这个checker的,不然的话,checker链中就没有这个phase的。
这个phase比较简单,主要是处理access_code,也就是access phase中设置的access_code.
ngx_int_t ngx_http_core_post_access_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "post access phase: %ui", r->phase_handler); //如果有access_code if (r->access_code) { //打印error if (r->access_code == NGX_HTTP_FORBIDDEN) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "access forbidden by rule"); } //回收request ngx_http_finalize_request(r, r->access_code); return NGX_OK; } //否则进入下一个handler r->phase_handler++; return NGX_AGAIN; }
然后就是NGX_HTTP_TRY_FILES_PHASE这个phase的checker,ngx_http_core_try_files_phase。
这个phase的代码有点小多,不过逻辑还是比较简单的,那就是如果请求文件不在的话,则会打开try_file定义的location然后调用对应的文件,最后正常返回,也就是返回AGAIN.
最后就是NGX_HTTP_CONTENT_PHASE的checker,ngx_http_core_content_phase。
这个phase一般来说,我们编写的大部分handler都是属于这个phase的,他就是用来生成内容。
不过这里要注意一个域content_handler,如果这个handler存在的话,整个content phase就会只执行这一个handler,然后返回NGX_OK.
然后来分析handler返回值。
1 NGX_DONE 此时说明handler执行成功。
2 NGX_DECLINED 此时表示需要执行本phase的下一个handler
3 其他,此时需要finalize request。
来看代码
ngx_int_t ngx_http_core_content_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph) { size_t root; ngx_int_t rc; ngx_str_t path; //如果有content_handler,则直接调用conteng_handler if (r->content_handler) { r->write_event_handler = ngx_http_request_empty_handler; ngx_http_finalize_request(r, r->content_handler(r)); //返回NGX_OK return NGX_OK; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "content phase: %ui", r->phase_handler); //否则调用push进去的handler rc = ph->handler(r); if (rc == NGX_DONE) { //直接返回ok,停止处理。 return NGX_OK; } if (rc != NGX_DECLINED) { //嗲用finalize requst ngx_http_finalize_request(r, rc); return NGX_OK; } /* rc == NGX_DECLINED */ ph++; //如果下一个handler的checker存在则返回again,以待下次调用 if (ph->checker) { r->phase_handler++; return NGX_AGAIN; } /* no content handler was found */ //没有handler的情况。 if (r->uri.data[r->uri.len - 1] == '/' && !r->zero_in_uri) { if (ngx_http_map_uri_to_path(r, &path, &root, 0) != NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "directory index of \"%s\" is forbidden", path.data); } ngx_http_finalize_request(r, NGX_HTTP_FORBIDDEN); return NGX_OK; } ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no handler found"); ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND); return NGX_OK; }
发表评论
-
nginx中sub_request的处理
2010-06-30 18:17 11869首先来看subrequest的处理。 什么是subreque ... -
nginx中handler的处理(一)
2010-05-20 01:09 13190nginx中的处理一个http的请求分为了8个phase,分别 ... -
nginx中的output chain的处理(二)
2010-05-09 13:45 10186接着上次的分析继续, ... -
nginx中锁的设计以及惊群的处理
2010-05-03 02:13 19411nginx中使用的锁是自己来实现的,这里锁的实现分为两种情况, ... -
nginx中的output chain的处理(一)
2010-04-24 00:59 7185这里我们详细来看ngx_linux_sendfile_chai ... -
nginx的filter的处理
2010-04-13 00:38 11766随笔拿一个nginx的filter模块来看,gzip模块,来看 ... -
nginx中request请求的解析
2010-04-04 01:15 11983ngx_http_init_request 中初始化event ... -
linux已经不存在惊群现象
2010-01-02 22:10 16033惊群也就是指多个进程 ... -
nginx的内存管理
2009-12-10 01:20 12775先来看内存池的实现,nginx的内存池实现的非常简单。 这里 ... -
nginx的进程模型
2009-09-13 21:11 20354nginx采用的也是大部分http服务器的做法,就是maste ...
相关推荐
如果多个处理模块映射到了同一个位置,Nginx会在配置文件中处理冲突,确保只有一个模块处理请求。 3. **过滤模块(Filter Modules)**:过滤模块在处理模块之后介入,用于修改或增强处理模块生成的输出。例如,它们...
在自定义handler上读取请求体,并在请求体读取完后处理逻辑,创建子请求转发给后端服务器处理。 3.子请求回调函数处理完后,激活父请求,继续往下阶段处理request的请求或者继续创建子请求转发数据。 4.在filter...
- **handler模块简介**:Handler模块是Nginx中用于处理特定类型的请求的核心组件。 - **模块的基本结构**:每个Handler模块都需要实现一组特定的接口函数,以完成其功能。 - **handler模块的基本结构**:Handler模块...
- 将`nginx-hi`模块源码与Nginx源码一起编译,生成新的Nginx二进制文件。 - 在Nginx配置文件中启用新模块,配置`hi_message`指令。 - 重启Nginx服务,测试自定义模块是否按预期工作。 通过这个例子,开发者可以...
现在,你需要在 Nginx 的 `server` 或 `location` 块中配置 Nginx Upload Module。下面是一个基本示例: ```nginx location /upload { upload_pass @handler; upload_store /var/www/uploads; upload_store_...
从给定文件中可以看出,这是一本关于nginx开发的书籍,内容涵盖了nginx模块开发、原理解析以及架构详解等多个方面。下面将详细介绍这些知识点。 首先,nginx是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3...
创建一个处理文件上传的lua脚本,例如`upload_handler.lua`,这个脚本会接收Nginx传递的文件信息,并进行处理,如保存文件、验证文件大小和类型等。示例脚本可能如下: ```lua local function save_file(file) ...
- `ngx_rtmp_handler.c`: 处理 RTMP 数据包的函数集合。 - `ngx_rtmp_core_module.c`: 核心模块,处理连接、播放、发布等基本操作。 - `ngx_rtmp_hls_module.c`: 实现 HLS 转码功能的模块。 **五、配置与部署** 在 ...
- **Handler 的调用**: 在启动过程中,每个 handler 有机会处理配置文件中的 location 定义。如果有多个 handler 被配置来处理同一 location,则只有一个 handler 可以“获胜”,即被选中来处理该 location。 - **...
- **handler模块的编译和使用**:需要将自定义的handler模块编译进Nginx源代码中,并通过配置文件启用。 - **部分handler模块的分析**:包括但不限于静态文件服务模块、动态内容生成模块等。 - **过滤模块**: -...
总的来说,"nginx1.16.1+nginx-upload-module-2.3.0.zip" 提供了一种实现大文件上传的解决方案,结合了 Nginx 的稳定性和 nginx-upload-module 的便捷性,使得在 Web 应用中处理文件上传变得更加高效和可控。...
**二、Nginx-RTMP模块的功能** 1. **直播流处理**:Nginx-RTMP模块支持RTMP推送和拉取,可以接收来自推流软件(如OBS Studio)的直播流,并向观众分发。 2. **录制功能**:可以自动将接收到的直播流保存为本地文件...
在`src/http/modules/ngx_http_v2_module.c`中,你可以看到Nginx如何处理HTTP/2的连接和数据帧。 8. **缓存机制** Nginx的缓存功能可以显著提高静态内容的访问速度。在`src/...
- **Handler**: Handler 是 Nginx 中处理特定类型请求的模块,例如静态文件服务、动态内容代理等。 - **Filter**: Filter 是一种特殊的 handler,用于对响应进行修改或增强。 #### 1.4 Nginx 的 filter 的处理 ...
Nginx 是由 Igor Sysoev 开发的一款开源 Web 服务器,以其高并发处理能力、低内存占用以及稳定性能而著名。它采用了事件驱动的异步非阻塞模型,能够同时处理大量连接请求。Nginx 支持 HTTP、HTTPS、SMTP、IMAP/POP3 ...
**Nginx-Lua-GraphicsMagick:搭建高效图片处理服务** 在当今互联网时代,图片是网站内容的重要组成部分,无论是社交媒体、电子商务还是个人博客,都需要处理大量的图片。为了提高图片处理效率并减轻服务器负担,...
handler模块在Nginx架构中起着核心的作用,因为每一个HTTP请求最终都会由一个handler模块来处理。 《Nginx开发从入门到精通》这本书是由淘宝核心系统服务器平台组成员创作的,他们利用在淘宝内部使用Nginx的经验和...
Nginx是一款高性能、轻量级的Web服务器/反向代理服务器,因其出色的并发处理能力和稳定性,在互联网行业中广泛应用。本文将针对《reading-code-of-nginx-1.9.2_y123456yz.tar.gz》这个压缩包中的内容,对Nginx 1.9.2...