首頁 運維 Nginx nginx的請求如何處理?

nginx的請求如何處理?

Nov 28, 2019 pm 02:57 PM
nginx

nginx的請求如何處理?

今天我們講 request,在 Nginx 中我們指的是 http 請求,具體到 Nginx 中的資料結構是ngx_http_request_t。 ngx_http_request_t 是對一個 http 請求的封裝。我們知道,一個 http 請求,包含請求行、請求頭、請求體、回應行、回應頭、回應體。

http 請求是典型的請求-回應類型的網路協議,而http 是文字協議,所以我們在分析請求行與請求頭,以及輸出回應行與回應頭,往往是一行一行的進行處理。      ( 建議學習:nginx使用 )

如果我們自己來寫一個 http 伺服器,通常在一個連線建立好後,客戶端會發送請求過來。然後我們讀取一行數據,分析出請求行中包含的 method、uri、http_version 資訊。

然後再一行一行處理請求頭,並根據請求 method 與請求頭的資訊來決定是否有請求體以及請求體的長度,然後再去讀取請求體。

得到請求後,我們處理請求產生需要輸出的數據,然後再產生回應行,回應頭以及回應體。

在將回應傳送給客戶端之後,一個完整的請求就處理完了。當然這是最簡單的 webserver 的處理方式,其實 Nginx 也是這樣做的,只是有一些小小的區別,比如,當請求頭讀取完成後,就開始進行請求的處理了。 Nginx 透過 ngx_http_request_t 來保存解析請求與輸出回應相關的資料。

那接下來,簡單講講 Nginx 是如何處理一個完整的請求的。 對於 Nginx 來說,一個請求是從ngx_http_init_request 開始的,在這個函數中,會設定讀取事件為 ngx_http_process_request_line,也就是說,接下來的網路事件,會由 ngx_http_process_request_line 來執行。

從ngx_http_process_request_line 的函數名,我們可以看到,這就是來處理請求行的,正好與之前講的,處理請求的第一件事就是處理請求行是一致的。

透過 ngx_http_read_request_header 來讀取請求資料。然後呼叫 ngx_http_parse_request_line 函數來解析請求行。 Nginx 為提高效率,採用狀態機來解析請求行,而且在進行method 的比較時,沒有直接使用字串比較,而是將四個字元轉換成一個整數,然後一次比較以減少cpu 的指令數,這個前面有說過。

很多人可能很清楚一個請求行包含請求的方法,uri,版本,卻不知道其實在請求行中,也是可以包含有 host 的。例如一個請求GET http://www.taobao.com/uri HTTP/1.0 這樣一個請求行也是合法的,而且host 是www.taobao.com,這個時候,Nginx 會忽略請求頭中的host 域,而以請求行中的這個為準來查找虛擬主機。

另外,對於 http0.9 版來說,是不支援請求頭的,所以這裡也是要特別的處理。所以,在後面解析請求頭時,協定版本都是 1.0 或 1.1。整個請求行解析到的參數,會儲存到 ngx_http_request_t 結構當中。

在解析完請求行後,Nginx 會設定讀取事件的 handler 為 ngx_http_process_request_headers,然後後續的請求就在 ngx_http_process_request_headers 中進行讀取與解析。

ngx_http_process_request_headers 函數用來讀取請求頭,跟請求行一樣,還是呼叫ngx_http_read_request_header 來讀取請求頭,呼叫ngx_http_parse_header_line 來解析一行請求頭,解析到的請求頭會保存到ngx_http_request_in 的域中,headers_in 是一個鍊錶結構,保存所有的請求頭。

而HTTP 中有些請求是需要特別處理的,這些請求頭與請求處理函數存放在一個映射表裡面,即ngx_http_headers_in,在初始化時,會產生一個hash 表,當每解析到一個請求頭後,就會先在這個hash 表中查找,如果有找到,則呼叫對應的處理函數來處理這個請求頭。例如:Host 頭的處理函數是 ngx_http_process_host。

當 Nginx 解析到兩個回車換行符時,就表示請求頭的結束,此時就會呼叫 ngx_http_process_request 來處理請求了。

ngx_http_process_request 會設定目前的連線的讀寫事件處理函式為 ngx_http_request_handler,然後再呼叫 ngx_http_handler 來真正開始處理一個完整的http請求。

這裡可能比較奇怪,讀寫事件處理函式都是ngx_http_request_handler,其實在這個函式中,會根據目前事件是讀取事件還是寫事件,分別呼叫 ngx_http_request_t 中的 read_event_handler 或是 write_event_handler。

由於此時,我們的請求頭已經讀取完成了,之前有說過,Nginx 的做法是先不讀取請求body,所以這裡面我們設定read_event_handler 為ngx_http_block_reading,即不讀取數據了。

剛才說到,真正開始處理數據,是在 ngx_http_handler 這個函數裡面,這個函數會設定 write_event_handler 為 ngx_http_core_run_phases,並執行 ngx_http_core_run_phases 函數。

ngx_http_core_run_phases 這個函數會執行多階段請求處理,Nginx 將一個 http 請求的處理分成多個階段,那麼這個函數就是執行這些階段來產生資料。

因為 ngx_http_core_run_phases 最後會產生數據,所以我們就很容易理解,為什麼設定寫事件的處理函數為 ngx_http_core_run_phases 了。

在這裡,我簡單說明了一下函數的呼叫邏輯,我們需要明白最終是呼叫ngx_http_core_run_phases 來處理請求,產生的回應頭會放在ngx_http_request_t 的headers_out 中,這一部分內容,我會放在請求處理流程裡面去講。 Nginx 的各種階段會對請求進行處理,最後會呼叫 filter 來過濾數據,對數據進行加工,如 truncked 傳輸、gzip 壓縮等。

這裡的 filter 包含 header filter 與 body filter,即對回應頭或回應體進行處理。 filter 是鍊錶結構,分別有 header filter 與 body filter,先執行 header filter 中的所有 filter,然後再執行 body filter 中的所有 filter。

在 header filter 中的最後一個 filter,即 ngx_http_header_filter,這個 filter 將會遍歷所有的響應頭,最後需要輸出的響應頭在一個連續的內存,然後調用 ngx_http_write_filter 進行輸出。

ngx_http_write_filter 是 body filter 中的最後一個,所以 Nginx 首先的 body 訊息,在經過一系列的 body filter 之後,最後也會呼叫 ngx_http_write_filter 來進行輸出(有圖來說明)。

這裡要注意的是,Nginx 會將整個請求頭都放在一個buffer 裡面,這個buffer 的大小透過設定項client_header_buffer_size 來設置,如果使用者的請求頭太大,這個buffer 裝不下,那Nginx 就會重新分配一個新的更大的buffer 來裝請求頭,這個大buffer 可以透過large_client_header_buffers 來設置,這個large_buffer 這一組buffer,例如配置48k,就是表示有四個8k 大小的buffer 可以用。

注意,為了保存請求行或請求頭的完整性,一個完整的請求行或請求頭,需要放在一個連續的記憶體裡面,所以,一個完整的請求行或請求頭,只會保存在一個buffer 裡面。

這樣,如果請求行大於一個 buffer 的大小,就會回傳 414 錯誤,如果一個請求頭大小大於一個 buffer 大小,就會回傳 400 錯誤。在了解了這些參數的值,以及 Nginx 實際的做法之後,在應用場景,我們就​​需要根據實際的需求來調整這些參數,來最佳化我們的程式了。

處理流程圖:

nginx的請求如何處理?

#以上這些,就是 Nginx 中一個 http 請求的生命週期了。

以上是nginx的請求如何處理?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

docker容器名稱怎麼查 docker容器名稱怎麼查 Apr 15, 2025 pm 12:21 PM

可以通過以下步驟查詢 Docker 容器名稱:列出所有容器(docker ps)。篩選容器列表(使用 grep 命令)。獲取容器名稱(位於 "NAMES" 列中)。

nginx在windows中怎麼配置 nginx在windows中怎麼配置 Apr 14, 2025 pm 12:57 PM

如何在 Windows 中配置 Nginx?安裝 Nginx 並創建虛擬主機配置。修改主配置文件並包含虛擬主機配置。啟動或重新加載 Nginx。測試配置並查看網站。選擇性啟用 SSL 並配置 SSL 證書。選擇性設置防火牆允許 80 和 443 端口流量。

怎麼查看nginx是否啟動 怎麼查看nginx是否啟動 Apr 14, 2025 pm 01:03 PM

確認 Nginx 是否啟動的方法:1. 使用命令行:systemctl status nginx(Linux/Unix)、netstat -ano | findstr 80(Windows);2. 檢查端口 80 是否開放;3. 查看系統日誌中 Nginx 啟動消息;4. 使用第三方工具,如 Nagios、Zabbix、Icinga。

docker怎麼啟動容器 docker怎麼啟動容器 Apr 15, 2025 pm 12:27 PM

Docker 容器啟動步驟:拉取容器鏡像:運行 "docker pull [鏡像名稱]"。創建容器:使用 "docker create [選項] [鏡像名稱] [命令和參數]"。啟動容器:執行 "docker start [容器名稱或 ID]"。檢查容器狀態:通過 "docker ps" 驗證容器是否正在運行。

nginx怎麼查版本 nginx怎麼查版本 Apr 14, 2025 am 11:57 AM

可以查詢 Nginx 版本的方法有:使用 nginx -v 命令;查看 nginx.conf 文件中的 version 指令;打開 Nginx 錯誤頁,查看頁面的標題。

docker怎麼創建容器 docker怎麼創建容器 Apr 15, 2025 pm 12:18 PM

在 Docker 中創建容器: 1. 拉取鏡像: docker pull [鏡像名] 2. 創建容器: docker run [選項] [鏡像名] [命令] 3. 啟動容器: docker start [容器名]

nginx怎麼配置雲服務器域名 nginx怎麼配置雲服務器域名 Apr 14, 2025 pm 12:18 PM

在雲服務器上配置 Nginx 域名的方法:創建 A 記錄,指向雲服務器的公共 IP 地址。在 Nginx 配置文件中添加虛擬主機塊,指定偵聽端口、域名和網站根目錄。重啟 Nginx 以應用更改。訪問域名測試配置。其他注意事項:安裝 SSL 證書啟用 HTTPS、確保防火牆允許 80 端口流量、等待 DNS 解析生效。

怎麼啟動nginx服務器 怎麼啟動nginx服務器 Apr 14, 2025 pm 12:27 PM

啟動 Nginx 服務器需要按照不同操作系統採取不同的步驟:Linux/Unix 系統:安裝 Nginx 軟件包(例如使用 apt-get 或 yum)。使用 systemctl 啟動 Nginx 服務(例如 sudo systemctl start nginx)。 Windows 系統:下載並安裝 Windows 二進製文件。使用 nginx.exe 可執行文件啟動 Nginx(例如 nginx.exe -c conf\nginx.conf)。無論使用哪種操作系統,您都可以通過訪問服務器 IP

See all articles