在使用subrequest时,须要了解下面3个场景:nginx
- 启动subrequest后子请求时如何运行的;
- 子请求如何存放收到的响应;
- 子请求结束时如何回调处理方法,以及激活父请求的处理方法。
一,如何启动subrequest
处理父请求的过程当中会建立子请求,在父请求处理方法返回NGX_DONE后,HTTP框架会执行子请求,下面将介绍subrequest启动过程: 服务器
(1)NGX主循环会按期地调用事件模块,检查是否有网络事件发生;网络
(2)事件模块发现这个请求的回调方法属于HTTP框架,交由HTTP框架来处理;框架
(3)根据解析完的URI来决定使用哪一个location下的模块来处理这个请求;异步
(4)调用mytest模块的ngx_http_mytest_handler方法处理这个请求;post
(5)设置subrequest子请求的URI及回调方法;//5-9步请见subrequest使用方式一节介绍spa
(6)调用ngx_http_subrequest方法建立子请求;代理
(7)建立的子请求会添加到原始请求的posted_requests链表中;blog
(8)ngx_http_subrequest方法执行完毕,子请求建立成功;事件
(9)ngx_http_mytest_handler方法执行完毕,返回NGX_DONE,这样父请求不会被销毁,等待之后的再次激活;
(10)HTTP框架执行完当前请求(父请求)后,检查posted_requests链表中是否还有子请求,若是存在子请求,则调用子请求的write_event_handler方法;
(11)根据子请求的URI,检查nginx.conf全部的location配置,肯定应有哪一个模块执行子请求,好比能够用反向代理模块执行;
(12)调用模块入口方法来处理子请求,例如反向代理模块入口方法ngx_http_proxy_handler;
(13)因为反向代理模块使用了upstream机制,因此它也要经过不少次的异步调用才能完整的处理完子请求,这是它的入口方法返回的是NGX_DONE;
(14)再次检查是否还有子请求,这是已经发现没有子请求了,固然子请求能够继续建立新的子请求,只是这里的反向代理模块不会这样作;
(15)第二步中网络事件处理完毕后,将控制权交给事件模块;
(16)本轮网络事件处理完毕后,交还控制权给NGINX主循环。
二,子请求如何激活父请求
子请求在结束前会回调在ngx_http_post_subrequest_t中实现的handler方法,在这个handler方法中,又设置了父请求被激活后的执行方法,mytest_post_handler, 流程以下:
(1)nginx主循环按期地调用事件模块,检查是否有网络事件发生;
(2)若是事件模块监测到链接关闭事件,而这个请求的处理方法属于upstream模块,则交由upstream模块来处理请求;
(3)upstream模块开始调用ngx_http_upstream_finalize_request方法来结束upstream机制下的请求;
(4)调用HTTP框架提供的ngx_http_finalize_request方法来结束子请求;
(5)ngx_http_finalize_request方法会检查当前的请求是不是子请求,若是是,则会回调post_suberquest成员中的handler方法,也就是会调用mytest_subrequest_post_handler方法;
(6)在实现的子请求回调方法中,解析子请求返回的响应包。注意,这时须要经过write_event_handler设置父请求被激活后的回调方法(由于此时父请求的回调方法已经被HTTP框架设置为何事都不作的ngx_http_request_empty_handler方法);
(7)子请求的回调方法执行完毕后,交由HTTP框架的ngx_http_finalize_request方法继续向下执行;
(8)ngx_http_finalize_request方法执行完毕;
(9)HTTP框架若是发现当前请求后还有父请求须要执行,则调用父请求的write_event_handler回调方法;
(10)这里能够根据第6步中解析子请求响应后的结果来构造响应包;
(11)调用无阻塞的ngx_http_send_header、ngx_http_output_filter发送方法,向客户端发送响应包;
(12)无阻塞发送方法会马上返回,即便目前未发送完,nginx以后也会异步地发送完全部的响应包,而后再结束请求;
(13)父请求的回调方法执行完毕;
(14)当第2步中的上游服务器链接关闭事件处理完毕后,交还控制权给事件模块;
(15)本轮网络事件处理完毕后,交还控制权给nginx主循环。