1. 程式人生 > >三、Nginx原理解析

三、Nginx原理解析

Nginx原理解析

一、反向代理

工作流程

  1. 使用者通過域名發出訪問Web伺服器的請求,該域名被DNS伺服器解析為反向代理伺服器的IP地址;
  2. 反向代理伺服器接受使用者的請求;
  3. 反向代理伺服器在本地快取中查詢請求的內容,找到後直接把內容傳送給使用者;
  4. 如果本地快取裡沒有使用者所請求的資訊內容,反向代理伺服器會代替使用者向源伺服器請求同樣的資訊內容,並把資訊內容發給使用者,如果資訊內容是快取的還會把它儲存到快取中。

優點

  1. 保護了真實的web伺服器,保證了web伺服器的資源安全

通常的代理伺服器,只用於代理內部網路對Internet外部網路的連線請求,客戶機必須指定代理伺服器,並將本來要直接傳送到Web伺服器上的http請求傳送到代理伺服器中。不支援外部網路對內部網路的連線請求,因為內部網路對外部網路是不可見的。當一個代理伺服器能夠代理外部網路上的主機,訪問內部網路時,這種代理服務的方式稱為反向代理服務。此時代理伺服器對外就表現為一個Web伺服器,外部網路就可以簡單把它當作一個標準的Web伺服器而不需要特定的配置。不同之處在於,這個伺服器沒有儲存任何網頁的真實資料,所有的靜態網頁或者CGI程式,都儲存在內部的Web伺服器上。因此對反向代理伺服器的攻擊並不會使得網頁資訊遭到破壞,這樣就增強了Web伺服器的安全性。

  1. 節約了有限的IP地址資源

企業內所有的網站共享一個在internet中註冊的IP地址,這些伺服器分配私有地址,採用虛擬主機的方式對外提供服務。

  1. 減少WEB伺服器壓力,提高響應速度

反向代理就是通常所說的web伺服器加速,它是一種通過在繁忙的web伺服器和外部網路之間增加一個高速的web緩衝伺服器來降低實際的web伺服器的負載的一種技術。反向代理是針對web伺服器提高加速功能,作為代理快取,它並不是針對瀏覽器使用者,而針對一臺或多臺特定的web伺服器,它可以代理外部網路對內部網路的訪問請求。

反向代理伺服器會強制將外部網路對要代理的伺服器的訪問經過它,這樣反向代理伺服器負責接收客戶端的請求,然後到源伺服器上獲取內容,把內容返回給使用者,並把內容儲存到本地,以便日後再收到同樣的資訊請求時,它會把本地快取裡的內容直接發給使用者,以減少後端web伺服器的壓力,提高響應速度。因此Nginx還具有快取功能。

二、Nginx工作原理

Nginx由核心和模組組成。

  Nginx本身做的工作實際很少,當它接到一個HTTP請求時,它僅僅是通過查詢配置檔案將此次請求對映到一個location block,而此location中所配置的各個指令則會啟動不同的模組去完成工作,因此模組可以看做Nginx真正的勞動工作者。通常一個location中的指令會涉及一個handler模組和多個filter模組(當然,多個location可以複用同一個模組)。handler模組負責處理請求,完成響應內容的生成,而filter模組對響應內容進行處理。

使用者根據自己的需要開發的模組都屬於第三方模組。正是有了這麼多模組的支撐,Nginx的功能才會如此強大。

Nginx的模組從結構上分為核心模組、基礎模組和第三方模組:

  • 核心模組:HTTP模組、EVENT模組和MAIL模組
  • 基礎模組:HTTP Access模組、HTTP FastCGI模組、HTTP Proxy模組和HTTP Rewrite模組,
  • 第三方模組:HTTP Upstream Request Hash模組、Notice模組和HTTP Access Key模組。

Nginx的模組從功能上分為如下三類:

  • Handlers(處理器模組)。此類模組直接處理請求,並進行輸出內容和修改headers資訊等操作。Handlers處理器模組一般只能有一個。
  • Filters (過濾器模組)。此類模組主要對其他處理器模組輸出的內容進行修改操作,最後由Nginx輸出。
  • Proxies (代理類模組)。此類模組是Nginx的HTTP Upstream之類的模組,這些模組主要與後端一些服務比如FastCGI等進行互動,實現服務代理和負載均衡等功能。

三、Nginx程序模型

Nginx預設採用多程序工作方式,Nginx啟動後,會執行一個master程序和多個worker程序。其中master充當整個程序組與使用者的互動介面,同時對程序進行監護,管理worker程序來實現重啟服務、平滑升級、更換日誌檔案、配置檔案實時生效等功能。worker用來處理基本的網路事件,worker之間是平等的,他們共同競爭來處理來自客戶端的請求。

nginx的程序模型如圖所示:

在建立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。因為作為反向代理伺服器,每個併發會建立與客戶端的連線和與後端服務的連線,會佔用兩個連線