漸進深刻理解Nginx

文章原創於公衆號:程序猿周先森。本平臺不定時更新,喜歡個人文章,歡迎關注個人微信公衆號。
filenginx

以前其實寫過一篇文章具體介紹過:最基礎的Nginx教學,當時有提到過Nginx有一個重要的功能:負載均衡。因此這篇文章主要講講Nginx如何實現反向代理以及在Nginx中負載均衡的參數使用。算法

1、代理segmentfault

正向代理後端

正向代理也是你們最常接觸的到的代理模式,那究竟什麼是正向代理呢?咱們都知道Google在國內是沒法正常訪問的,可是某些時候咱們因爲技術問題須要去訪問Google時,咱們會先找到一個能夠訪問Google的代理服務器,咱們將請求發送到代理服務器,代理服務器去訪問Google,而後將訪問到的數據返回給咱們,這樣的過程就是正向代理。緩存

正向代理的特色安全

正向代理最大的特色是客戶端須要明確知道要訪問的服務器地址,Google服務器只清楚請求來自哪一個代理服務器,而不清楚來自哪一個具體的客戶端,正向代理能夠隱藏真實客戶端的具體信息。服務器

file

客戶端必須設置正向代理服務器,並且須要知道正向代理服務器的IP地址以及代理程序的端口。一句話來歸納就是正向代理代理的是客戶端,是一個位於客戶端和Google服務器之間的服務器,爲了從Google服務器取得數據,客戶端向代理服務器發送一個請求並指定目標(Google服務器),而後代理向原始服務器轉交請求並將得到的數據返回給客戶端。微信

正向代理的使用:網絡

  • 訪問國外沒法訪問的網站
  • 作緩存,加速訪問資源
  • 對客戶端訪問受權,上網進行認證
  • 代理能夠記錄用戶訪問記錄(上網行爲管理),對外隱藏用戶信息

反向代理多線程

說完了什麼是正向代理,咱們接下來看看什麼叫作反向代理,若是咱們網站每日訪問量達到某個上限,單個服務器遠遠不能符合咱們平常需求,這時候咱們首先會想到分佈式部署。經過部署多臺服務器來解決訪問人數限制的問題,而後咱們功能其實大部分都是經過Nginx反向代理來實現的。咱們能夠看下圖:
file

反向代理的特色

咱們能夠清楚的看到,多個客戶端給服務器發送的請求,Nginx服務器接收到請求之後,按照必定的規則轉發到不一樣的服務器進行業務邏輯處理。此時請求來源於哪一個客戶端是肯定的,可是請求由哪臺服務器處理的並不明確,Nginx扮演的就是一個反向代理角色。能夠這樣來理解,反向代理對外都是透明的,訪問者並不知道本身訪問的是一個代理。反向代理代理的是服務端,主要用於服務器集羣分佈式部署的狀況下,反向代理隱藏了服務器的信息。

反向代理的使用:

  • 保證內網的安全,一般將反向代理做爲公網訪問地址,Web服務器是內網
  • 負載均衡,經過反向代理服務器來優化網站的負載

正向代理與反向代理區別
file

  • 在正向代理中,隱藏了請求來源的客戶端信息;
  • 在反向代理中,隱藏了請求具體處理的服務端信息;

服務端中咱們最常使用的反向代理的工具就是Nginx。

2、基本架構

Nginx在啓動後以daemon的方式在後臺運行,會有一個master進程和多個worker進程:

  1. Nginx 在啓動後,會有一個 master 進程和多個相互獨立的 worker 進程。
  2. 接收來自外界的信號,向各worker進程發送信號,每一個進程都有可能來處理這個鏈接。
  3. master 進程能監控 worker 進程的運行狀態,當 worker 進程退出後(異常狀況下),會自動啓動新的 worker 進程。

master進程:主要用來管理worker進程,包含:

  1. 接收來自外界的信號
  2. 向各worker進程發送信號
  3. 監控worker進程的運行狀態
  4. 當worker進程異常退出後,會自動從新啓動新的worker進程。

worker進程:處理基本的網絡事件了。多個worker進程之間是對等的,他們同等競爭來自客戶端的請求,各進程互相之間是獨立的。一個請求只能在一個worker進程中處理,一個worker進程,不可能處理其它進程的請求。worker進程的個數是能夠設置的,通常咱們會設置與機器cpu核數一致,或者直接設置參數worker_processes auto;

Nginx基本架構以下:
file

咱們能夠輸入nginx -s reload來重啓Nginx,nginx -s stop來中止Nginx的運行,執行這些命令時其實會啓動一個新的Nginx進程,而新的Nginx進程在解析到reload參數後,其實就能夠知道用戶執行這個命令是控制Nginx從新加載配置文件,因而向master進程發送信號。master進程接到信號會先從新加載配置文件,而後啓動新的worker進程並向全部舊worker進程發送信號提示老進程能夠中止運行了。新的worker啓動成功後就開始接收新的請求,而舊worker在收到來自master的信號後中止接收新的請求,在未處理完的請求處理完成後進程就會退出。因此說使用nginx -s reload命令重啓Nginx的時候服務是不中斷的。

3、Nginx處理客戶端請求方式

剛纔有講到過每一個worker進程都是從master進程分支的,因此在master進程裏面須要先創建好須要監聽的socket而後再分支出多個worker進程。全部worker進程listenfd事件會在新鏈接時變成可讀,爲保證只有一個進程處理該鏈接,因此須要設置互斥鎖,全部worker進程須要搶互斥鎖,搶到互斥鎖的work進程註冊listenfd讀事件,在listenfd讀事件裏調用accept接受該鏈接。當Nginx監聽80端口時,一個客戶端的鏈接請求過來的時候,每一個worker進程都會去搶互斥鎖註冊listenfd讀事件。當一個worker進程在accept這個鏈接以後,就開始處理請求獲取數據,再將數據返回給客戶端,而後斷開鏈接,到這裏一個請求結束。

一個請求,徹底由worker進程來處理,並且只在一個worker進程中處理。

我下面貼一個簡單的配置:

server {
listen 80;

server_name aaa.com www.aaa.com;

}

server {
listen 80;

server_name aaa.cn www.aaa.cn;

}

server {
listen 80;

server_name aaa.org www.aaa.org;

}

當接收到客戶端http請求,Nginx根據請求頭的Host字段決定請求應該由哪一臺服務器處理,若是Host字段的值沒有匹配的服務器或者請求中沒有Host字段,Nginx會將請求路由至這個端口的默認服務器。沒有顯示配置默認服務器,則默認服務器則爲第一個配置。固然咱們還可使用default_server參數指定默認服務器。

server {

listen 80 default_server;
server_name aaa.com www.aaa.com;

}

這裏須要注意一下:配置默認服務器是監聽端口號,而不是服務器名稱。

4、Nginx實現高併發

Nginx內部採用了異步非阻塞的方式處理請求,使用了epoll和大量的底層代碼優化。能夠同時處理成千上萬個請求的。

異步非阻塞:每進來一個request,會有一個worker進程去處理。但不是全程的處理,處理到什麼程度呢?處理到可能發生阻塞的地方,好比向後端服務器轉發request,並等待請求返回。這個處理的worke會在發送完請求後註冊一個事件:「若是upstream返回了,再進行執行接下來的工做」。此時,若是再有request 進來,他就能夠很快再按這種方式處理。而一旦後端服務器返回了,就會觸發這個事件,worker進程會來接手request接着往下執行。

而Nginx採用一個master進程,多個woker進程的模式。master進程主要負責收集、分發請求。每當一個請求過來時,master就拉起一個worker進程負責處理這個請求。同時master進程也負責監控woker的狀態,保證高可靠性,woker進程通常設置爲跟cpu核心數一致。Nginx的woker進程在同一時間能夠處理的請求數只受內存限制,能夠處理多個請求。Nginx 的異步非阻塞工做方式能夠把當中的進程空閒等待時間利用起來,所以表現爲少數幾個進程就解決了大量的併發問題。

Nginx中以epoll爲例子,當事件沒準備好時,放到epoll裏面,事件準備好了,Nginx就去讀寫,當讀寫返回EAGAIN時,就將它再次加入到epoll裏面。這樣,只要有事件準備好了,Nginx就能夠去處理它,只有當全部事件都沒準備好時,纔在epoll裏面等着。這樣便實現了所謂的併發處理請求,可是線程只有一個,因此同時能處理的請求固然只有一個了,只是在請求間進行不斷地切換而已。

Nginx單線程機制與多線程相比優點:

  • 在於不須要建立線程。
  • 每一個請求佔用的內存也不多。
  • 沒有上下文切換。
  • 事件處理很是的輕量級。
  • 併發數再多也不會致使無謂的資源浪費。

5、Nginx負載均衡的算法及參數

  • weight輪詢(默認):接收到的請求按照請求順序逐一分配到不一樣的後端服務器,若是在使用過程當中,某一臺服務器宕機,Nginx會自動將該服務器剔除出隊列,請求受理狀況不會受到任何影響。這種方式下,能夠給不一樣的後端服務器設置一個權重值,權重數據越大,服務器被分配到請求的概率越大。
  • ip_hash:每一個請求按照發起客戶端的ip的hash結果進行匹配,這樣的算法下一個固定ip地址的客戶端總會訪問到同一個後端服務器。
  • fair:智能調整調度算法,動態的根據後端服務器的請求響應時間進行均衡分配,響應時間短處理效率高的服務器分配到請求的機率高,響應時間長處理效率低的服務器分配到的請求少。
  • url_hash:按照訪問的url的hash結果分配請求,每一個請求的url會指向後端固定的某個服務器,能夠在Nginx做爲靜態服務器的狀況下提升緩存效率。

上面是最基本的4種算法,咱們還能夠經過改變參數來自行配置負載均衡:

upstream localhost{
ip_hash;
server 127.0.0.1:9090 down;
server 127.0.0.1:8080 weight=2;
server 127.0.0.1:6060;
server 127.0.0.1:7070 backup;
}
  • down表示當前的服務器中止參與負載。
  • weight默認爲1,weight越大,負載的權重就越大。
  • backup表示其它全部的非backup機器down或者忙的時候,請求backup機器。因此這臺機器壓力會最輕。

file

歡迎關注個人我的公衆號:程序猿周先森
file

相關文章
相關標籤/搜索