5.4 subrequest的使用方式

subrequest是由HTTP框架提供的一种分解复杂请求的设计模式,它可以把原始请求分解为许多子请求,使得诸多请求协同完成一个用户请求,并且每个请求只关注于一个功能。它与访问第三方服务及upstream机制有什么关系呢?首先,只要不是完全将上游服务器的响应包体转发到下游客户端,基本上都会使用subrequest创建出子请求,并由子请求使用upstream机制访问上游服务器,然后由父请求根据上游响应重新构造返回给下游客户端的响应。其次,在HTTP框架的设计上,subrequest与upstream也是密切相关的。例如,上文讲过,描述HTTP请求的ngx_http_request_t结构体中有一个标志位subrequest_in_memory,它决定upstream对待上游响应包体的行为。但是从名字上我们可以看到,它是与subrequest有关的,实际上,在创建子请求的方法中就可以设置subrequest_in_memory。

subrequest设计的基础是生成一个(子)请求的代价要非常小,消耗的内存也要很少,并且不会一直占用进程资源。因此,每个请求都应该做简单、独立的工作,而由多个子请求合成为一个父请求向客户端提供完整的服务。在Nginx中,大量功能复杂的模块都是基于subrequest实现的。

使用subrequest的方式要比upstream简单得多,只需要完成以下4步操作即可。

1)在nginx.conf文件中配置好子请求的处理方式。

2)启动subrequest子请求。

3)实现子请求执行结束时的回调方法。

4)实现父请求被激活时的回调方法。

下面依次说明这4个步骤。

5.4.1 配置子请求的处理方式

实际上,子请求的处理过程与普通请求完全相同,也需要在nginx.conf中配置相应的模块来处理。子请求与普通请求的不同之处在于,子请求是由父请求生成的,不是接收客户端发来的网络包再由HTTP框架解析出的。配置处理子请求的模块与普通请求完全相同,可以任意地使用HTTP官方模块、第三方模块来处理。本章中将以访问第三方服务为例,因此会使用ngx_http_proxy_module反向代理模块来处理子请求(注意,这里并没有使用反向代理的转发响应功能,而只是把响应接收到Nginx的内存中),但在实际应用中不限于此。

假设我们生成的子请求是以URI为/list开头的请求,使用ngx_http_proxy_module模块让子请求访问新浪的hq.sinajs.cn股票服务器,那么可以在nginx.conf中这样设置:


location/list{

proxy_pass http://hq.sinajs.cn;

/不希望第三方服务发来的HTTP包体做过gzip压缩,因为我们不想在子请求结束时要对响应做gzip解压缩操作/

proxy_set_header Accept-Encoding"";

}


这样,在5.4.4节中,如果生成的子请求是以/list开头的,就会使用反向代理模块去访问新浪服务器,并在接收完新浪服务器的响应包后调用5.4.2节中介绍的回调方法。