11.2 新连接建立时的行为

当Nginx接收到用户发起TCP连接的请求时,事件框架将会负责把TCP连接建立起来,如果TCP连接成功建立,HTTP框架就会介入请求的处理了,如图9-5所示,在ngx_event_accept方法建立新连接的最后1步,将会调用ngx_listening_t监听结构体的handler方法。在10.3节中讲过,HTTP框架在初始化时就会将每个监听ngx_listening_t结构体的handler方法设为ngx_http_init_connection方法,如下所示。


void ngx_http_init_connection(ngx_connection_t*c)


即HTTP框架处理请求的第一步就在ngx_http_init_connection方法中,这里传入的参数c就是新建立的连接。图11-1列举了ngx_http_init_connection方法所做的主要工作。

11.2 新连接建立时的行为 - 图1

图 11-1 建立连接成功后HTTP框架的行为

下面简单解释一下图11-1中的4个步骤:

1)将新建立的连接c的可读事件处理方法设置为ngx_http_init_request。在9.3节我们介绍过ngx_connection_t结构体中会用read成员表示连接上的可读事件,write成员表示可写事件。读/写事件均使用ngx_event_t结构体表示。在9.2节中又介绍过每个事件发生时事件框架都会调用其中的handler方法。这一步骤实际上就是把连接c的read读事件的handler方法设为ngx_http_init_request,它意味着当用户在这个TCP连接上发送的数据到达服务器后,ngx_http_init_request方法将会被调用(参见11.3节)。

事实上,对于可写事件,也会设置它的handler回调方法为ngx_http_empty_handler,这个方法不会做任何工作,如下所示。


void ngx_http_empty_handler(ngx_event_t*wev)

{

ngx_log_debug0(NGX_LOG_DEBUG_HTTP,wev->log,0,"http empty handler");

return;

}


这个方法仅有一个用途:当业务上不需要处理可写事件时,就把ngx_http_empty_handler方法设置到连接的可写事件的handler中,这样可写事件被定时器或者epoll触发后是不做任何工作的。

注意 下面会多次使用ngx_http_empty_handler方法。

2)如果新连接的读事件ngx_event_t结构体中的标志位ready为1,实际上表示这个连接对应的套接字缓存上已经有用户发来的数据,这时就可调用上面说过的ngx_http_init_request方法处理请求,参见11.3节。

3)在9.7.3节的表9-5中我们介绍过定时器的用法,在这一步骤中将调用ngx_add_timer方法把读事件添加到定时器中,设置的超时时间则是nginx.conf中client_header_timeout配置项指定的参数。也就是说,如果经过client_header_timeout时间后这个连接上还没有用户数据到达,则会由定时器触发调用读事件的ngx_http_init_request处理方法。

4)我们在9.2.1节中介绍过ngx_handle_read_event方法,它可以将一个事件添加到epoll中。在这一步骤中,将调用ngx_handle_read_event方法把连接c的可读事件添加到epoll中。注意,这里并没有把可写事件添加到epoll中,因为现在不需要向客户端发送任何数据。

以上4个步骤就是ngx_http_init_connection方法的主要工作,也就是新连接建立成功时HTTP框架对请求的处理。