Nginx:HTTP框架是如何介入請求


參考資料 <深入理解Nginx>(陶輝)

            Nginx事件模塊博客地址:http://www.cnblogs.com/runnyu/p/4914698.html

 

Nginx是一個事件驅動構架的Web服務器,在上次的博客中我們可以看到Nginx是如何驅動事件的處理的。

本次將介紹HTTP框架是如何介入跟處理HTTP網絡事件的。因為書上的思路已經足夠清晰而且內容比較獨立,因此本次基本上就把本章的重點記錄一下。

 

HTTP框架存在的目的

1.Nginx事件框架主要是針對傳輸層的TCP的,作為Web服務器HTTP模塊需要處理的則是HTTP,HTTP框架必須要針對基於TCP的事件框架解決好HTTP的網絡傳輸、解析、組裝等問題。

2.雖然事件驅動構架在性能上是不錯的,但是HTTP模塊的業務通常較復雜,HTTP框架的存在則可以讓我們屏蔽事件驅動架構,盡量只關注業務,提供開發效率。

 

 

新連接建立時的行為

在上次博客的最后可以看到,在ngx_event_accept方法建立連接的最后一步,將會調用ngx_listening_t監聽結構體的handler方法。這時候HTTP框架就開始介入請求了。

HTTP框架在初始化時就會將每個監聽ngx_listening_t結構體的handler方法設為ngx_http_init_connection方法,該方法執行流程如下圖:

其中定時器中的超時時間是nginx.conf配置文件中指定的client_header_timeout,后面的超時時間設定也是這個值。

 

 

第一次可讀事件的處理

當TCP連接上第一次出現可讀事件時,將會調用ngx_http_init_request方法初始化這個HTTP請求

該方法主要做了3件事情:

1.對請求構造ngx_http_request_t結構體並初始化部分參數;

2.修改讀事件的回調方法為ngx_http_process_request_line

3.調用上面的回調方法解析HTTP請求行

6.讀事件被觸發,這是需要在用戶態的進程空間分配內存,用來把內核緩沖區上的TCP流復制到用戶態的內存中。

   這一步將在ngx_connection_t的內存池中分配一塊內存,內存塊的大小與nginx.conf文件中的client_header_buffer_size配置項參數一致。

   ngx_connection_t結構體的buffer指針以及ngx_http_request_t結構體的header_in指針共同指向這塊內存緩沖區。

 

 

 

接收HTTP請求行

在初始化請求之后,將調用ngx_http_process_request_line方法接收HTTP請求行。

因為請求行的長度是不定的,這意味着在讀事件被觸發時,內核套接字緩沖區的大小未必足夠接收到全部的HTTP請求行。

因此調用一次ngx_http_process_request_line方法不一定能夠接收完完整的HTTP請求行,該方法會被多次調度。下圖展示了該方法的流程

該方法會調用recv方法把Linux內核套接字緩沖區中的TCP流復制到header_in緩沖區中。

header_in的類型是ngx_buf_t,它的pos成員和last成員指向的地址之間的內存就是收到的未解析的字符流。

 

4.在本次沒有接收到TCP流的時候,告訴事件驅動程序繼續檢測這個讀事件,然后該方法就結束。在該讀事件准備好的時候,該方法將被再次調度。

5.在接收到TCP流后,用狀態機(ngx_http_parse_request_line方法)解析已經接收到的TCP字符流,確認其是否構成完整的HTTP請求行。

7.如果ngx_http_parse_request_line方法返回NGX_OK,表示已經成功地接收到完整的請求行。這一步將把請求行的的信息設置到ngx_http_request_t結構體的相應成員中

   (request_line、uri、method_name、http_protocol、args等)。

11.接收完HTTP請求行后,把讀事件的回調方法更改為ngx_http_request_headers准備接收HTTP頭部。

 

 

接收HTTP頭部

跟HTTP請求行一樣,HTTP頭部也屬於可變長度的字符串,它與HTTP請求行和包體間都是通過換行符來區分的。

下圖展示了HTTP框架使用ngx_http_process_request_headers方法接收、解析HTTP頭部的流程

6.調用ngx_http_parse_header_line方法解析緩沖區的字符流。這個方法有3個返回值:

   返回NGX_OK時,表示解析出一行HTTP頭部;返回NGX_HTTP_PARSE_HEADER_DONE時,表示已經解析出了完整的HTTP頭部;

   返回NGX_AGAIN時,表示還需要接收到更多的字符流才能繼續解析;除此之外的錯誤情況,將發送400錯誤給客戶端。

7.解析出的HTTP頭部信息設置到ngx_http_request_t結構體headers_in成員的headers鏈表中。

9.當ngx_http_parse_header_line方法返回NGX_HTTP_PARSE_HEADER_DONE時,將會根據HTTP頭部中的host字段情況,

   調用ngx_http_find_virtual_server方法找到對應的虛擬主機配置塊。ngx_http_request_t結構體里的srv_conf、loc_conf成員被重新設置,以指向正確的虛擬主機。

 

在接收到完整的HTTP頭部后,已經有足夠的必要信息開始在業務上處理HTTP請求了。下一節將說明HTTP框架是如何召集負責具體功能的各HTTP模塊合作處理請求的。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM