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连接。