5.3 使用upstream的示例

下面以一个简单且能够运行的示例帮助读者理解如何使用upstream机制。这个示例要实现的功能很简单,即以访问mytest模块的URL参数作为搜索引擎的关键字,用upstream方式访问google,查询URL里的参数,然后把google的结果返回给用户。这个场景非常适合使用upstream方式,因为Nginx访问google的服务器使用的是HTTP,它当然符合upstream的使用场景:上游服务器提供基于TCP的协议。上文讲过,upstream提供了3种处理包体的方式,这里选择以固定缓冲区向下游客户端转发google返回的包体(HTTP的包体)的方式。

例如,如果访问的URL是/test?lumia,那么在nginx.conf中可以这样配置location。


location/test{

mytest;

}


mytest模块将会使用upstream机制向www.google.com发送搜索请求,它的请求URL是/search?q=lumia,google返回的包头将在mytest模块中解析并决定如何转发给用户,而包体将会被透传给用户。

这里继续以mytest模块为例来说明如何使用upstream达成上述效果。

5.3.1 upstream的各种配置参数

每一个HTTP请求都会有独立的ngx_http_upstream_conf_t结构体,出于简单考虑,在mytest模块的例子中,所有的请求都将共享同一个ngx_http_upstream_conf_t结构体,因此,这里把它放到ngx_http_mytest_conf_t配置结构体中,如下所示。


typedef struct{

ngx_http_upstream_conf_t upstream;

}ngx_http_mytest_conf_t;


在启动upstream前,先将ngx_http_mytest_conf_t下的upstream成员赋给r->upstream->conf成员,可参考5.3.6节中的示例代码。

ngx_http_upstream_conf_t结构中的各成员可以通过第4章中介绍的方法,即用预设的配置项解析参数来赋值,如5.1.2节中的例子所示。出于方便,这里直接硬编码到create_loc_conf回调方法中了,如下所示。


static voidngx_http_mytest_create_loc_conf(ngx_conf_tcf)

{

ngx_http_mytest_conf_t*mycf;

mycf=(ngx_http_mytest_conf_t*)ngx_pcalloc(cf->pool,sizeof(ngx_http_mytest_conf_t));

if(mycf==NULL){

return NULL;

}

/以下简单的硬编码ngx_http_upstream_conf_t结构中的各成员,如超时时间,都设为1分钟,这也是HTTP反向代理模块的默认值/

mycf->upstream.connect_timeout=60000;

mycf->upstream.send_timeout=60000;

mycf->upstream.read_timeout=60000;

mycf->upstream.store_access=0600;

/实际上,buffering已经决定了将以固定大小的内存作为缓冲区来转发上游的响应包体,这块固定缓冲区的大小就是buffer_size。如果buffering为1,就会使用更多的内存缓存来不及发往下游的响应。例如,最多使用bufs.num个缓冲区且每个缓冲区大小为bufs.size。另外,还会使用临时文件,临时文件的最大长度为max_temp_file_size/

mycf->upstream.buffering=0;

mycf->upstream.bufs.num=8;

mycf->upstream.bufs.size=ngx_pagesize;

mycf->upstream.buffer_size=ngx_pagesize;

mycf->upstream.busy_buffers_size=2*ngx_pagesize;

mycf->upstream.temp_file_write_size=2*ngx_pagesize;

mycf->upstream.max_temp_file_size=102410241024;

/upstream模块要求hide_headers成员必须要初始化(upstream在解析完上游服务器返回的包头时,会调用ngx_http_upstream_process_headers方法按照hide_headers成员将本应转发给下游的一些HTTP头部隐藏),这里将它赋为NGX_CONF_UNSET_PTR,这是为了在merge合并配置项方法中使用upstream模块提供的ngx_http_upstream_hide_headers_hash方法初始化hide_headers成员/

mycf->upstream.hide_headers=NGX_CONF_UNSET_PTR;

mycf->upstream.pass_headers=NGX_CONF_UNSET_PTR;

return mycf;

}


hide_headers的类型是ngx_array_t动态数组(实际上,upstream模块将会通过hide_headers来构造hide_headers_hash散列表)。由于upstream模块要求hide_headers不可以为NULL,所以必须要初始化hide_headers成员。upstream模块提供了ngx_http_upstream_hide_headers_hash方法来初始化hide_headers,但仅可用在合并配置项方法内。例如,在下面的ngx_http_mytest_merge_loc_conf方法中就可以使用,如下所示


static charngx_http_mytest_merge_loc_conf(ngx_conf_tcf,voidparent,voidchild)

{

ngx_http_mytest_conf_tprev=(ngx_http_mytest_conf_t)parent;

ngx_http_mytest_conf_tconf=(ngx_http_mytest_conf_t)child;

ngx_hash_init_t

hash;

hash.max_size=100;

hash.bucket_size=1024;

hash.name="proxy_headers_hash";

if(ngx_http_upstream_hide_headers_hash(cf,&conf->upstream,

&prev->upstream,ngx_http_proxy_hide_headers,&hash)

!=NGX_OK)

{

return NGX_CONF_ERROR;

}

return NGX_CONF_OK;

}