5.6.5 启动subrequest
在处理用户请求的ngx_http_mytest_handler方法中,开始创建subrequest子请求。ngx_http_mytest_handler方法的完整实现如下所示:
static ngx_int_t
ngx_http_mytest_handler(ngx_http_request_t*r)
{
//创建HTTP上下文
ngx_http_mytest_ctx_t*myctx=ngx_http_get_module_ctx(r,ngx_http_mytest_module);
if(myctx==NULL)
{
myctx=ngx_palloc(r->pool,sizeof(ngx_http_mytest_ctx_t));
if(myctx==NULL)
{
return NGX_ERROR;
}
//将上下文设置到原始请求r中
ngx_http_set_ctx(r,myctx,ngx_http_mytest_module);
}
//ngx_http_post_subrequest_t结构体会决定子请求的回调方法,参见5.4.1节
ngxhttp_post_subrequest_t*psr=ngx_palloc(r->pool,sizeof(ngx_http_post
subrequest_t));
if(psr==NULL){
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
//设置子请求回调方法为mytest_subrequest_post_handler
psr->handler=mytest_subrequest_post_handler;
/将data设为myctx上下文,这样回调mytest_subrequest_post_handler时传入的data参数就是myctx/
psr->data=myctx;
/子请求的URI前缀是/list,这是因为访问新浪服务器的请求必须是类似/list=s_sh000001的URI,这与在nginx.conf中配置的子请求location的URI是一致的(见5.6.1节)/
ngx_str_t sub_prefix=ngx_string("/list=");
ngx_str_t sub_location;
sub_location.len=sub_prefix.len+r->args.len;
sub_location.data=ngx_palloc(r->pool,sub_location.len);
ngx_snprintf(sub_location.data,sub_location.len,
"%V%V",&sub_prefix,&r->args);
//sr就是子请求
ngx_http_request_t*sr;
/*调用ngx_http_subrequest创建子请求,它只会返回NGX_OK或者NGX_ERROR。返回NGX_OK时,sr已经是合法的子请求。注意,这里的NGX_HTTP_SUBREQUEST_IN_MEMORY参数将告诉upstream模块把上游服
务器的响应全部保存在子请求的sr->upstream->buffer内存缓冲区中*/
ngx_int_t rc=ngx_http_subrequest(r,&sub_location,NULL,&sr,psr,NGX_HTTP_SUBREQUEST_IN_MEMORY);
if(rc!=NGX_OK){
return NGX_ERROR;
}
//必须返回NGX_DONE,原因同upstream
return NGX_DONE;
}
至此,一个使用subrequest的mytest模块已经创建完成,它支持的并发HTTP连接数只与物理内存大小相关,因此,这样的服务器通常可以轻易地支持几十万的并发TCP连接。