本文在這基礎上分析nginx服務器收到http請求行、請求頭部后,http框架是如何調度各個http模塊共同完成這個http請求。例如: http框架調度靜態模塊,獲取服務器目錄下的某個html頁面返回給客戶端; 或者http框架調度access權限訪問模塊,判斷這個客戶端是否有權限訪問服務器。
一、event事件與http框架的交互
在接收完http請求行、http請求頭部后,會調用ngx_http_process_request這個函數開始處理http請求。因為一個http請求由11個處理階段組成,而每一個處理階段都允許多個http模塊介入,因此在這個函數中,將調度各個階段的http模塊共同完成這個請求。
//接收到http請求行與請求頭后,http的處理流程,是第一個http處理請求的讀事件回調 //這個函數執行后,將把讀寫事件的回調設置為ngx_http_request_handler。這樣下次再有事件時 //將調用ngx_http_request_handler函數來處理,而不會再調用ngx_http_process_request了 static void ngx_http_process_request(ngx_http_request_t *r) { ngx_connection_t *c; c = r->connection; //因為已經接收完http請求行、請求頭部了,準備調用各個http模塊處理請求了。 //因此需要接收任何來自客戶端的讀事件,也就不存在接收http請求頭部超時問題 if (c->read->timer_set) { ngx_del_timer(c->read); } //重新設置當前連接的讀寫事件回調 c->read->handler = ngx_http_request_handler; c->write->handler = ngx_http_request_handler; //設置http請求對象的讀事件回調,這個回調不做任何的事情。 //那http請求對象的讀事件回調,與上面的連接對應的讀事件回調有什么關系呢? //當讀事件發生后,連接對應的讀事件回調ngx_http_request_handler會被調用, //在這個回調內會調用http請求對象的讀事件回調ngx_http_block_reading,而這個回調是 //不會做任何事件的,因此相當于忽略了讀事件。因為已經接收完了請求行請求頭,現在要做的是調用各個http模塊, //對接收到的請求行請求頭進行處理 r->read_event_handler = ngx_http_block_reading; //調用各個http模塊協同處理這個請求 ngx_http_handler(r); //處理子請求 ngx_http_run_posted_requests(c); }
ngx_http_process_request函數只會被調用一次。如果一次調度并不能處理完11個http階段,那會將連接對象對應的讀事件、寫事件回調設置為ngx_http_request_handler。而請求對象的讀事件設置為ngx_http_block_reading, 請求對象的寫事件回調設置為ngx_http_core_run_phases, 這個回調在ngx_http_handler內設置。這樣在事件再次到來時不會調用
ngx_http_process_request函數處理了。那event事件模塊的讀寫事件回調與http請求對象的讀寫事件回調有什么關系呢?
//http請求處理讀與寫事件的回調,在ngx_http_process_request函數中設置。 //這個函數中將會調用http請求對象的讀寫事件回調。將event事件模塊與http框架關聯起來 static void ngx_http_request_handler(ngx_event_t *ev) { //如果同時發生讀寫事件,則只有寫事件才會觸發。寫事件優先級更高 if (ev->write) { r->write_event_handler(r); //在函數ngx_http_handler設置為:ngx_http_core_run_phases } else { r->read_event_handler(r); //在函數ngx_http_process_request設置為:ngx_http_block_reading } //處理子請求 ngx_http_run_posted_requests(c); }
新聞熱點
疑難解答