1. http处理流程概述
nginx对于http请求处理的大概流程是:接收客户端发起的连接,然后接收并解析http请求行,接收并解析http头部;再根据配置文件nginx.conf找到相关http模块,使这些模块依次合作处理http请求,最后发送http响应并结束http请求。
在整个http请求处理过程中,nginx通过连接的读写事件,以及定时器机制,异步回调完成其处理流程。
2. http新连接的建立
在事件模块一文中我们知道,当新连接建立后会回调对应侦听的处理方法。对于http模块,该回调方法为ngx_http_init_connection。在该方法中,主要完成的事情是:设置连接的读事件回调处理方法为ngx_http_wait_request_handler,设置连接的写事件回调处理方法为ngx_http_empty_handler;然后查看读事件是否已经准备好,即连接对应的套接字缓冲区上是否已经接收到用户的请求数据了,如果是,则直接调用ngx_http_wait_request_handler进入下一处理步骤;如果还没有准备好,则对连接的读事件设置定时器,同时将读事件添加到事件驱动中,等待下一次回调处理。
void ngx_http_init_connection(ngx_connection_t *c)
{
...
// 设置读写事件回调处理方法
rev = c->read;
rev->handler = ngx_http_wait_request_handler;
c->write->handler = ngx_http_empty_handler;
if( rev->ready ) {
if( ngx_use_accept_mutex ) {
ngx_post_event(rev, &ngx_posted_events);
return;
}
// 事件已经准备好, 直接处理
rev->handler(rev);
return;
}
// 设置定时器
ngx_add_timer(rev, c->listening->post_accept_timeout);
ngx_reusable_connection(c, 1);
// 将读事件加入事件驱动中
if(ngx_handle_read_event(rev, 0) != NGX_OK) {
ngx_http_close_connection(c);
return;
}
}
3. 首次可读事件的处理
当连接对应的套接字缓冲区首次接收到用户的请求数据后,会回调ngx_http_wait_request_handler方法,在该函数中,会调用recv接收用户的请求数据,同时创建一个ngx_http_request_t用于本次http请求处理,然后调用ngx_http_process_request_line开始处理http请求行。
static void ngx_http_wait_request_handler(ngx_event_t *rev)
{
....
// 接收数据
n = c->recv(c, b->last, size);
if( n == NGX_AGAIN ) {
if(!rev->timer_set) {
ngx_add_timer(rev, c->listening->post_accept_timeout);
ngx_reusable_connection(c, 1);
}
if( ngx_handle_read_event(rev,0) != NGX_OK ) {
ngx_http_close_connection(c);
return ;
}
}
if(n == NGX_ERROR ) {
ngx_http_close_connection(c);
return ;
}
....
// 创建request
c->data = ngx_http_create_request(c);
if(c->data == NULL) {
ngx_http_close_connection(c);
return ;
}
rev->handler = ngx_http_process_request_line;
ngx_http_post_request_line(rev);
}
4. http请求行/http头部的接收处理
在完成了请求的初始化后,会依次调用ngx_http_process_request_line和ngx_http_process_request_headers方法开始接收http请求行和http头部,并解析出URL,请求方法等各字段的含义。当这些都处理完成后,调用ngx_http_process_request进入请求真正的处理阶段。
static void ngx_http_process_request_line(ngx_event_t * rev)
{
....
for( ;; ) {
// 解析 http行
rc = ngx_http_parse_request_line(r, r->header_in);
if( rc == NGX_OK ) {
// 处理http uri
if(ngx_http_process_request_uri(r) != NGX_OK) {
return ;
}
// 设置连接的读事件回调处理, 并开始处理http请求的头部
rev->handler = ngx_http_process_request_headers;
ngx_http_process_request_headers(rev);
return ;
}
}
}
static void ngx_http_process_request_headers(ngx_event_t * rev)
{
....
rc = NGX_AGAIN;
for( ;; ) {
if( rc == NGX_AGAIN ) {
n = ngx_http_request_header(r);
}
// 解析http的头部
rc = ngx_http_parse_header_line(r, r->header_in, cscf->underscores_in_headers);
if( rc == NGX_HTTP_PARSE_HEADER_DONE) {
r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE;
// 处理http的头部
rc = ngx_http_process_request_header(r);
if(rc != NGX_OK) {
return ;
}
// 开始http请求的处理
ngx_http_process_request(r);
return ;
}
}
}
5. http请求的处理
在ngx_http_process_request中,将连接读写事件的回调处理均设置为ngx_http_request_handler方法,然后调用ngx_http_handler,而在ngx_http_handler中最终调用ngx_http_core_run_phases开始http的多阶段处理。
void ngx_http_process_request(ngx_http_request_t *r )
{
....
c->read->handler = ngx_http_request_handler;
c->write->handler = ngx_http_request_handler;
c->read_event_handler = ngx_http_block_reading;
ngx_http_handler(r);
ngx_http_run_posted_requests(c);
}
void ngx_http_handler(ngx_http_request_t * r)
{
...
// 开始http请求的多阶段处理
r->write_event_handler = ngx_http_core_run_phases;
ngx_http_core_run_phases(r);
}
6. 发送http请求响应
http请求响应回复一般会通过ngx_http_send_header发送http头部,通过ngx_http_output_filter发送http的包体。ngx_http_send_header和ngx_http_output_filter都是由一系列的filter模块组成,这些模块对响应数据进行加工处理,最终调用ngx_http_write_filter进行数据的发送。
ngx_int_t ngx_http_send_header(ngx_http_request_t *r)
{
....
return ngx_http_top_header_filter(r);
}
ngx_int_t ngx_http_output_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
....
rc = ngx_http_top_body_filter(r, in);
....
}
7. 结束http请求
一般来讲,结束http请求会调用ngx_http_finalize_request来完成。到这里,整个http的处理流程结束。