日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > Nginx >内容正文

Nginx

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

發(fā)布時(shí)間:2024/2/28 Nginx 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Nginx:HTTP框架是如何介入请求 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

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

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

?

Nginx是一個(gè)事件驅(qū)動(dòng)構(gòu)架的Web服務(wù)器,在上次的博客中我們可以看到Nginx是如何驅(qū)動(dòng)事件的處理的。

本次將介紹HTTP框架是如何介入跟處理HTTP網(wǎng)絡(luò)事件的。因?yàn)闀系乃悸芬呀?jīng)足夠清晰而且內(nèi)容比較獨(dú)立,因此本次基本上就把本章的重點(diǎn)記錄一下。

?

HTTP框架存在的目的

1.Nginx事件框架主要是針對(duì)傳輸層的TCP的,作為Web服務(wù)器HTTP模塊需要處理的則是HTTP,HTTP框架必須要針對(duì)基于TCP的事件框架解決好HTTP的網(wǎng)絡(luò)傳輸、解析、組裝等問(wèn)題。

2.雖然事件驅(qū)動(dòng)構(gòu)架在性能上是不錯(cuò)的,但是HTTP模塊的業(yè)務(wù)通常較復(fù)雜,HTTP框架的存在則可以讓我們屏蔽事件驅(qū)動(dòng)架構(gòu),盡量只關(guān)注業(yè)務(wù),提供開發(fā)效率。

?

?

新連接建立時(shí)的行為

在上次博客的最后可以看到,在ngx_event_accept方法建立連接的最后一步,將會(huì)調(diào)用ngx_listening_t監(jiān)聽結(jié)構(gòu)體的handler方法。這時(shí)候HTTP框架就開始介入請(qǐng)求了。

HTTP框架在初始化時(shí)就會(huì)將每個(gè)監(jiān)聽ngx_listening_t結(jié)構(gòu)體的handler方法設(shè)為ngx_http_init_connection方法,該方法執(zhí)行流程如下圖:

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

?

?

第一次可讀事件的處理

當(dāng)TCP連接上第一次出現(xiàn)可讀事件時(shí),將會(huì)調(diào)用ngx_http_init_request方法初始化這個(gè)HTTP請(qǐng)求

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

1.對(duì)請(qǐng)求構(gòu)造ngx_http_request_t結(jié)構(gòu)體并初始化部分參數(shù);

2.修改讀事件的回調(diào)方法為ngx_http_process_request_line

3.調(diào)用上面的回調(diào)方法解析HTTP請(qǐng)求行

6.讀事件被觸發(fā),這是需要在用戶態(tài)的進(jìn)程空間分配內(nèi)存,用來(lái)把內(nèi)核緩沖區(qū)上的TCP流復(fù)制到用戶態(tài)的內(nèi)存中。

? ?這一步將在ngx_connection_t的內(nèi)存池中分配一塊內(nèi)存,內(nèi)存塊的大小與nginx.conf文件中的client_header_buffer_size配置項(xiàng)參數(shù)一致。

? ?ngx_connection_t結(jié)構(gòu)體的buffer指針以及ngx_http_request_t結(jié)構(gòu)體的header_in指針共同指向這塊內(nèi)存緩沖區(qū)。

?

?

?

接收HTTP請(qǐng)求行

在初始化請(qǐng)求之后,將調(diào)用ngx_http_process_request_line方法接收HTTP請(qǐng)求行。

因?yàn)檎?qǐng)求行的長(zhǎng)度是不定的,這意味著在讀事件被觸發(fā)時(shí),內(nèi)核套接字緩沖區(qū)的大小未必足夠接收到全部的HTTP請(qǐng)求行。

因此調(diào)用一次ngx_http_process_request_line方法不一定能夠接收完完整的HTTP請(qǐng)求行,該方法會(huì)被多次調(diào)度。下圖展示了該方法的流程

該方法會(huì)調(diào)用recv方法把Linux內(nèi)核套接字緩沖區(qū)中的TCP流復(fù)制到header_in緩沖區(qū)中。

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

?

4.在本次沒有接收到TCP流的時(shí)候,告訴事件驅(qū)動(dòng)程序繼續(xù)檢測(cè)這個(gè)讀事件,然后該方法就結(jié)束。在該讀事件準(zhǔn)備好的時(shí)候,該方法將被再次調(diào)度。

5.在接收到TCP流后,用狀態(tài)機(jī)(ngx_http_parse_request_line方法)解析已經(jīng)接收到的TCP字符流,確認(rèn)其是否構(gòu)成完整的HTTP請(qǐng)求行。

7.如果ngx_http_parse_request_line方法返回NGX_OK,表示已經(jīng)成功地接收到完整的請(qǐng)求行。這一步將把請(qǐng)求行的的信息設(shè)置到ngx_http_request_t結(jié)構(gòu)體的相應(yīng)成員中

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

11.接收完HTTP請(qǐng)求行后,把讀事件的回調(diào)方法更改為ngx_http_request_headers準(zhǔn)備接收HTTP頭部。

?

?

接收HTTP頭部

跟HTTP請(qǐng)求行一樣,HTTP頭部也屬于可變長(zhǎng)度的字符串,它與HTTP請(qǐng)求行和包體間都是通過(guò)換行符來(lái)區(qū)分的。

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

6.調(diào)用ngx_http_parse_header_line方法解析緩沖區(qū)的字符流。這個(gè)方法有3個(gè)返回值:

? ?返回NGX_OK時(shí),表示解析出一行HTTP頭部;返回NGX_HTTP_PARSE_HEADER_DONE時(shí),表示已經(jīng)解析出了完整的HTTP頭部;

? ?返回NGX_AGAIN時(shí),表示還需要接收到更多的字符流才能繼續(xù)解析;除此之外的錯(cuò)誤情況,將發(fā)送400錯(cuò)誤給客戶端。

7.解析出的HTTP頭部信息設(shè)置到ngx_http_request_t結(jié)構(gòu)體headers_in成員的headers鏈表中。

9.當(dāng)ngx_http_parse_header_line方法返回NGX_HTTP_PARSE_HEADER_DONE時(shí),將會(huì)根據(jù)HTTP頭部中的host字段情況,

? ?調(diào)用ngx_http_find_virtual_server方法找到對(duì)應(yīng)的虛擬主機(jī)配置塊。ngx_http_request_t結(jié)構(gòu)體里的srv_conf、loc_conf成員被重新設(shè)置,以指向正確的虛擬主機(jī)。

?

在接收到完整的HTTP頭部后,已經(jīng)有足夠的必要信息開始在業(yè)務(wù)上處理HTTP請(qǐng)求了。下一節(jié)將說(shuō)明HTTP框架是如何召集負(fù)責(zé)具體功能的各HTTP模塊合作處理請(qǐng)求的。

總結(jié)

以上是生活随笔為你收集整理的Nginx:HTTP框架是如何介入请求的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。