12.2 启动upstream

在把请求里ngx_http_request_t结构体中的upstream成员(ngx_http_upstream_t类型)创建并设置好,并且正确设置upstream->conf配置结构体(ngx_http_upstream_conf_t类型)后,就可以启动upstream机制了。启动方式非常简单,调用ngx_http_upstream_init方法即可。

注意,默认情况下请求的upstream成员只是NULL空指针,在设置upstream之前需要调用ngx_http_upstream_create方法从内存池中创建ngx_http_upstream_t结构体,该方法的原型如下。


ngx_int_t ngx_http_upstream_create(ngx_http_request_t*r)


ngx_http_upstream_create方法只是创建ngx_http_upstream_t结构体而已,其中的成员还需要各个HTTP模块自行设置。启动upstream机制的ngx_http_upstream_init方法定义如下。


void ngx_http_upstream_init(ngx_http_request_t*r)


ngx_http_upstream_init方法将会根据ngx_http_upstream_conf_t中的成员初始化upstream,同时会开始连接上游服务器,以此展开整个upstream处理流程。图12-2简要描述了ngx_http_upstream_init方法所做的主要工作。

下面依次说明图12-2中各个步骤的意义。

1)首先检查请求对应于客户端的连接,这个连接上的读事件如果在定时器中,也就是说,读事件的timer_set标志位为1,那么调用ngx_del_timer方法把这个读事件从定时器中移除。为什么要做这件事呢?因为一旦启动upstream机制,就不应该对客户端的读操作带有超时时间的处理,请求的主要触发事件将以与上游服务器的连接为主。

2)检查ngx_http_upstream_conf_t配置结构中的ignore_client_abort标志位(参见12.1.3节),如果ignore_client_abort为1,则跳到第3步,否则(实际上,还需要让store标志位为0、请求ngx_http_request_t结构体中的post_action标志位为0)就会设置Nginx与下游客户端之间TCP连接的检查方法,如下所示。


r->read_event_handler=ngx_http_upstream_rd_check_broken_connection;

r->write_event_handler=ngx_http_upstream_wr_check_broken_connection;


12.2 启动upstream - 图1

图 12-2 ngx_http_upstream_init方法的流程图

实际上,这两个方法都会通过ngx_http_upstream_check_broken_connection方法检查Nginx与下游的连接是否正常,如果出现错误,就会立即终止连接。

3)调用请求中ngx_http_upstream_t结构体里由某个HTTP模块实现的create_request方法,构造发往上游服务器的请求(请求中的内容是设置到request_bufs缓冲区链表中的)。如果create_request方法没有返回NGX_OK,则upstream机制结束,此时会调用11.10.6节中介绍过的ngx_http_finalize_request方法来结束请求。

4)在11.10.2节中介绍过,ngx_http_cleanup_t是用于清理资源的结构体,还说明了它何时会被执行。在这一步中,upstream机制就用到了ngx_http_cleanup_t。首先,调用ngx_http_cleanup_add方法向这个请求main成员指向的原始请求中的cleanup链表末尾添加一个新成员,然后把handler回调方法设为ngx_http_upstream_cleanup,这意味着当请求结束时,一定会调用ngx_http_upstream_cleanup方法(参见12.9.1节)。

5)调用ngx_http_upstream_connect方法向上游服务器发起连接(详见12.3节)。

注意 启动upstream机制时还有许多分支流程,如缓存文件的使用、上游服务器地址的选取等,图12-2概括了最主要的5个步骤,这样方便读者了解upstream的核心思想。其他分支的处理不影响这5个主要流程,如需了解可自行查看ngx_http_upstream_init和ngx_http_upstream_init_request方法的源代码。