Nginx 工做原理nginx
Nginx由內核和模塊組成。後端
Nginx自己作的工做實際不多,當它接到一個HTTP請求時,它僅僅是經過查找配置文件將這次請求映射到一個location block,而此location中所配置的各個指令則會啓動不一樣的模塊去完成工做,所以模塊能夠看作Nginx真正的勞動工做者。一般一個location中的指令會涉及一個handler模塊和多個filter模塊(固然,多個location能夠複用同一個模塊)。handler模塊負責處理請求,完成響應內容的生成,而filter模塊對響應內容進行處理。數組
用戶根據本身的須要開發的模塊都屬於第三方模塊。正是有了這麼多模塊的支撐,Nginx的功能纔會如此強大。服務器
Nginx的模塊從結構上分爲核心模塊、基礎模塊和第三方模塊:網絡
Nginx的模塊從功能上分爲以下三類:併發
Nginx進程模型負載均衡
Nginx默認採用多進程工做方式,Nginx啓動後,會運行一個master進程和多個worker進程。其中master充當整個進程組與用戶的交互接口,同時對進程進行監護,管理worker進程來實現重啓服務、平滑升級、更換日誌文件、配置文件實時生效等功能。worker用來處理基本的網絡事件,worker之間是平等的,他們共同競爭來處理來自客戶端的請求。socket
nginx的進程模型如圖所示:spa
在建立master進程時,先創建須要監聽的socket(listenfd),而後從master進程中fork()出多個worker進程,如此一來每一個worker進程多能夠監聽用戶請求的socket。通常來講,當一個鏈接進來後,全部在Worker都會收到通知,可是隻有一個進程能夠接受這個鏈接請求,其它的都失敗,這是所謂的驚羣現象。nginx提供了一個accept_mutex(互斥鎖),有了這把鎖以後,同一時刻,就只會有一個進程在accpet鏈接,這樣就不會有驚羣問題了。代理
先打開accept_mutex選項,只有得到了accept_mutex的進程纔會去添加accept事件。nginx使用一個叫ngx_accept_disabled的變量來控制是否去競爭accept_mutex鎖。ngx_accept_disabled = nginx單進程的全部鏈接總數 / 8 -空閒鏈接數量,當ngx_accept_disabled大於0時,不會去嘗試獲取accept_mutex鎖,ngx_accept_disable越大,因而讓出的機會就越多,這樣其它進程獲取鎖的機會也就越大。不去accept,每一個worker進程的鏈接數就控制下來了,其它進程的鏈接池就會獲得利用,這樣,nginx就控制了多進程間鏈接的平衡。
每一個worker進程都有一個獨立的鏈接池,鏈接池的大小是worker_connections。這裏的鏈接池裏面保存的其實不是真實的鏈接,它只是一個worker_connections大小的一個ngx_connection_t結構的數組。而且,nginx會經過一個鏈表free_connections來保存全部的空閒ngx_connection_t,每次獲取一個鏈接時,就從空閒鏈接鏈表中獲取一個,用完後,再放回空閒鏈接鏈表裏面。一個nginx能創建的最大鏈接數,應該是worker_connections * worker_processes。固然,這裏說的是最大鏈接數,對於HTTP請求本地資源來講,可以支持的最大併發數量是worker_connections * worker_processes,而若是是HTTP做爲反向代理來講,最大併發數量應該是worker_connections * worker_processes/2。由於做爲反向代理服務器,每一個併發會創建與客戶端的鏈接和與後端服務的鏈接,會佔用兩個鏈接。
Nginx處理HTTP請求流程
http請求是典型的請求-響應類型的的網絡協議。http是文件協議,因此咱們在分析請求行與請求頭,以及輸出響應行與響應頭,每每是一行一行的進行處理。一般在一個鏈接創建好後,讀取一行數據,分析出請求行中包含的method、uri、http_version信息。而後再一行一行處理請求頭,並根據請求method與請求頭的信息來決定是否有請求體以及請求體的長度,而後再去讀取請求體。獲得請求後,咱們處理請求產生須要輸出的數據,而後再生成響應行,響應頭以及響應體。在將響應發送給客戶端以後,一個完整的請求就處理完了。
處理流程圖: