NGINX源码之:phase与handlers

一、NGINX处理请求11个步骤
nginx将请求划分为11个阶段(phase),便于对请求细分操作处理,与定制化开发:

 NGX_HTTP_POST_READ_PHASE      // 读取请求阶段
 NGX_HTTP_SERVER_REWRITE_PHASE // server级请求rewrite阶段
 NGX_HTTP_FIND_CONFIG_PHASE,   // 配置查找,location匹配阶段
 NGX_HTTP_REWRITE_PHASE,       // location级请求重写阶段
 NGX_HTTP_POST_REWRITE_PHASE,  // server、location级重写后置处理
 NGX_HTTP_PREACCESS_PHASE,     // 访问权限校验前置处理
 NGX_HTTP_ACCESS_PHASE,        // 访问权限校验阶段
 NGX_HTTP_POST_ACCESS_PHASE,   // 访问权限校验后置chuli
 NGX_HTTP_PRECONTENT_PHASE,    // http请求内容前置处理
 NGX_HTTP_CONTENT_PHASE,       // http请求内容处理阶段
 NGX_HTTP_LOG_PHASE            // 日志处理阶段

处理某个请求时,这些phase按顺序执行,处理NGX_HTTP_POST_REWRITE_PHASE阶段处理后,由于server配置与location配置发生变化,需要在配置查找阶段NGX_HTTP_FIND_CONFIG_PHASE重新查找更新配置。其中有部分阶段可挂在自定义的handler回调处理,如下:

NGX_HTTP_POST_READ_PHASE
NGX_HTTP_SERVER_REWRITE_PHASE
NGX_HTTP_REWRITE_PHASE
NGX_HTTP_PREACCESS_PHASE
NGX_HTTP_ACCESS_PHASE
NGX_HTTP_PRECONTENT_PHASE
NGX_HTTP_CONTENT_PHASE
NGX_HTTP_LOG_PHASE

二、可挂载的阶段Handler数组初始化:ngx_http_init_phases
可挂载handler阶段有个明显的特征,就是解析完配置文件之后(ngx_conf_parse)在ngx_http_init_phases创建了对应handler数组
在这里插入图片描述
这些数组都是空数组,保存在http配置第一级ctx的main_conf中cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];在自定义的handler可通过phase的handlers数组push元素实现挂载。
三、Handler挂载注册:module->postconfiguration
NGINX对于handler的挂载都是在每个module定义的postconfiguration回调方法中完成的。这部分处理也是在ngx_http_block方法中配置文件解析完成之后。postconfiguration回调方法主要两个作用,一个是配置filter,另一个则是为每个可挂载handler的phase挂载module实现的handler。
在这里插入图片描述
在这里插入图片描述
因此自定义的module,定义好对应的postconfiguration回调方法,再在postconfiguration方法中,取出&cmcf->phase[xxx].handlers数组,在push元素handler即可。通常自定义处理的handler会挂载在NGX_HTTP_CONTENT_PHASE阶段。

四、关联phase与Handler:ngx_http_init_phase_handlers
注册好handler之后,还需要将handler与每个phase的checker做关联:
在这里插入图片描述
在NGINX本身的模块的,初始化handler与checker关联关闭后,ph数组的结构如下:
在这里插入图片描述
下标14在ph数组中实际上是没有的,图为了完整性,加上了14表示content的下一个阶段是log.。
n和next的变化如下图:
在这里插入图片描述
NGX_HTTP_POST_READ_PHASE在NGINX原始配置中,没有handler,不占用ph下标,不过NGX_HTTP_POST_READ_PHASE是可挂载自定义的handler的,如果有自定义的handler,这里下标都要响应后移。

五、phase与Handler执行:ngx_http_core_run_phases
接收请求后,在对请求处理时,会进入ngx_http_core_run_phases方法:
在这里插入图片描述
下面来按顺序看下每个节点的phase(checker):
1、NGX_HTTP_POST_READ_PHASE(checker:ngx_http_core_generic_phase)
在NGINX本身的配置中,这个阶段没有handler,另外还有有NGX_HTTP_PREACCESS_PHASE,NGX_HTTP_PRECONTENT_PHASE两个阶段共用这个checker
在这里插入图片描述
2、NGX_HTTP_SERVER_REWRITE_PHASE(checker:ngx_http_core_rewrite_phase)
跟ngx_http_core_generic_phase基本差不多,重写server块内,location块外的指令。
在这里插入图片描述
handler:ngx_http_rewrite_handler

3、NGX_HTTP_FIND_CONFIG_PHASE(checker:ngx_http_core_find_config_phase)
根据经过server重写阶段的request的uri寻找匹配的location块配置项,由静态字符串标识的location被称作static location,由正则表达式表示的location成为regex location,查找顺序从静态到正则进行匹配,当阶段NGX_HTTP_REWRITE_PHASE发生重写,find config阶段会被执行多次重新匹配location配置。
在这里插入图片描述
internal命令使用如下:常用于用户认证后才能访问的资源

location /auth/ {
  internal;
    root  /resource/image/;
}

在这里插入图片描述
在这里插入图片描述

重定向的request的状态设置为NGX_HTTP_MOVED_PERMANENTLY(301)
在这里插入图片描述
如果没有发生重定向,设置request 的ph下标+1,执行下一个Handler,由于findconfig阶段没有Handler,下一个Handler即下一个阶段的第一个Handler:NGX_HTTP_REWRITE_PHASE的第一个Handler。
在发生重定向后重新查找配置,ngx_http_update_location_config(),除了完成keepalive,sendfile,tcp_nopush设置外,还会设置content-handler,完成特定子请求的处理。如ngx_http_proxy_pass()设置clcf->handler = ngx_http_proxy_handler;

4、NGX_HTTP_REWRITE_PHASE(checker:ngx_http_core_rewrite_phase)
与1和2也差不多
在这里插入图片描述
handler:ngx_http_rewrite_handler

5、NGX_HTTP_POST_REWRITE_PHASE(checker:ngx_http_core_post_rewrite_phase)
当location重写阶段均发生了重写(location块有重写配置),那么在重写后置处理阶段,则会跳转find config阶段:
重写示例:
访问这以www.a.com访问,但是在NGINX中发生重写,跳转到www.b.com

server {
	listen 80;
	server_name www.a.com;
	rewrite ^/ http://www.b.com permanent;
}

下图第一段红色字体的,server rewrite阶段不包含,serverrewrite已经经过find config阶段了,这里只需要location块发生重写跳转到findconfig。
在这里插入图片描述

6、NGX_HTTP_ACCESS_PHASE(checker:ngx_http_core_access_phase)
代码示例:

location /{                 
    satisfy any; //满足一个条件即可
    //satisfy all; //满足所有条件              
}

在这里插入图片描述
handler:ngx_http_access_handler、ngx_http_auth_basic_handler

客户端访问进来的请求会在ngx_http_wait_request_handler-》ngx_http_create_request-》ngx_http_alloc_request()中设置
r->main = r; r->count = 1; 也就是只有主请求的情况下,r->main就是请求r本身,当发生了子请求,如upstream请求,那么会设置子请求sr->main = r.main,那么此时sr->main,就不会等于sr。说明子请求不需要验证access。当发生named内部重新跳转,内部重定向,重写或者upstream等情况,r->main->count会加1,然后在请求后置处理,会逐渐清理重定向的资源,count不断减1,直至减至1,最后清理主请求的资源。内部重定向的一些配置可查看location
在这里插入图片描述在这里插入图片描述

7、NGX_HTTP_POST_ACCESS_PHASE (checker:ngx_http_core_access_phase)
主要handler:null
对阶段NGX_HTTP_ACCESS_PHASE处理的access_code做判断,并执行对应的处理

8、NGX_HTTP_CONTENT_PHASE(checker:ngx_http_core_content_phase)
在这里插入图片描述
主要涉及的handler有:ngx_http_autoindex_handler、 ngx_http_index_handler、ngx_http_static_handler、ngx_http_proxy_handler

内容产生阶段,可在location配置响应的处理指令,如:perl, flv, proxy_pass, mp4 等。这样request就可以根据对应的content handler处理并返回正确的响应参考
当一个 request 对应的 location 并没有直接有配置的 content handler指令,那么 nginx 依次尝试:
1、 location 里面有配置 random_index on,那么随机选择一个文件,发送给客户端。
2、 location 里面有配置 index 指令,那么发送 index 指令指明的文件,给客户端。
3、 location 里面有配置 autoindex on,那么就发送请求地址对应的服务端路径下的文件列表给客户端。
4、 request 对应的 location 上有设置 gzip_static on,那么就查找是否有对应的.gz文件存在,有的话,就发送这个给客户端(客户端支持 gzip 的情况下)。
5、请求的 URI 如果对应一个静态文件, static module 就发送静态文件的内容到客户端。

例如proxy_pass的处理:
在解析location{}中的proxy_pass配置时,将给对应的clcf设置handler
在这里插入图片描述
然后再ngx_http_core_find_config_phase阶段,再查找uri对应的location后,对其更新,将handler赋值给请求r的content_handler,然后再ngx_http_core_content_phase方法最开始就判断是否有r->content_handler,有的话就执行。在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值