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