5.1.5 如何启动upstream机制

直接执行ngx_http_upstream_init方法即可启动upstream机制。例如:


static ngx_int_t ngx_http_mytest_handler(ngx_http_request_t*r)

{

……

r->main->count++;

ngx_http_upstream_init(r);

return NGX_DONE;

}


调用ngx_http_upstream_init就是在启动upstream机制,这时要通过返回NGX_DONE告诉HTTP框架暂停执行请求的下一个阶段。这里还需要执行r->main->count++,这是在告诉HTTP框架将当前请求的引用计数加1,即告诉ngx_http_mytest_handler方法暂时不要销毁请求,因为HTTP框架只有在引用计数为0时才能真正地销毁请求。这样的话,upstream机制接下来才能接管请求的处理工作。

提示 在阅读HTTP反向代理模块(ngx_http_proxy_module)源代码时,会发现它并没有调用r->main->count++,其中proxy模块是这样启动upstream机制的:ngx_http_read_client_request_body(r,ngx_http_upstream_init);,这表示读取完用户请求的HTTP包体后才会调用ngx_http_upstream_init方法启动upstream机制(参见3.6.4节)。由于ngx_http_read_client_request_body的第一行有效语句是r->main->count++,所以HTTP反向代理模块不能再次在其代码中执行r->main->count++。

这个过程看起来似乎让人困惑。为什么有时需要把引用计数加1,有时却不需要呢?因为ngx_http_read_client_request_body读取请求包体是一个异步操作(需要epoll多次调度才能完成的可称其为异步操作),ngx_http_upstream_init方法启用upstream机制也是一个异步操作,因此,从理论上来说,每执行一次异步操作应该把引用计数加1,而异步操作结束时应该调用ngx_http_finalize_request方法把引用计数减1。另外,ngx_http_read_client_request_body方法内是加过引用计数的,而ngx_http_upstream_init方法内却没有加过引用计数(或许Nginx将来会修改这个问题)。在HTTP反向代理模块中,它的ngx_http_proxy_handler方法中用"ngx_http_read_client_request_body(r,ngx_http_upstream_init);"语句同时启动了两个异步操作,注意,这行语句中只加了一次引用计数。执行这行语句的ngx_http_proxy_handler方法返回时只调用ngx_http_finalize_request方法一次,这是正确的。对于mytest模块也一样,务必要保证对引用计数的增加和减少是配对进行的。