nginx对于http请求处理的大概流程是:接收客户端发起的链接,而后接收并解析http请求行,接收并解析http头部;再根据配置文件nginx.conf找到相关http模块,使这些模块依次合做处理http请求,最后发送http响应并结束http请求。nginx
在整个http请求处理过程当中,nginx经过链接的读写事件,以及定时器机制,异步回调完成其处理流程。异步
在事件模块一文中咱们知道,当新链接创建后会回调对应侦听的处理方法。对于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; } }
当链接对应的套接字缓冲区首次接收到用户的请求数据后,会回调ngx_http_wait_request_handler方法,在该函数中,会调用recv接收用户的请求数据,同时建立一个ngx_http_request_t用于本次http请求处理,而后调用ngx_http_process_request_line开始处理http请求行。post
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); }
在完成了请求的初始化后,会依次调用ngx_http_process_request_line和ngx_http_process_request_headers方法开始接收http请求行和http头部,并解析出URL,请求方法等各字段的含义。当这些都处理完成后,调用ngx_http_process_request进入请求真正的处理阶段。spa
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 ; } } }
在ngx_http_process_request中,将链接读写事件的回调处理均设置为ngx_http_request_handler方法,而后调用ngx_http_handler,而在ngx_http_handler中最终调用ngx_http_core_run_phases开始http的多阶段处理。.net
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); }
http请求响应回复通常会经过ngx_http_send_header发送http头部,经过ngx_http_output_filter发送http的包体。ngx_http_send_header和ngx_http_output_filter都是由一系列的filter模块组成,这些模块对响应数据进行加工处理,最终调用ngx_http_write_filter进行数据的发送。code
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); .... }
通常来说,结束http请求会调用ngx_http_finalize_request来完成。到这里,整个http的处理流程结束。blog