nginx準系統和工作原理

來源:互聯網
上載者:User
nginx能做什麼 反向 Proxy 正向 Proxy 負載平衡 HTTP伺服器(包含動靜分離) 反向 Proxy和正向 Proxy

正向 Proxy。簡單的說,我是一個使用者,我無法直接存取一個網站,但是我能訪問一個Proxy 伺服器,這個Proxy 伺服器能訪問那個我不能訪問的網站,於是我先連上Proxy 伺服器,告訴它我需要那個無法訪問網站的內容,Proxy 伺服器去取回來,然後返回給我。從網站的角度,只在Proxy 伺服器來取內容的時候有一次記錄。結論就是,正向 Proxy,是一個位於用戶端和原始伺服器(origin server)之間的伺服器,為了從原始伺服器取得內容,用戶端向代理髮送一個請求並指定目標(原始伺服器),然後代理向原始伺服器轉交請求並將獲得的內容返回給用戶端。用戶端必須要進行一些特別的設定才能使用正向 Proxy。

反向 Proxy。例如我要訪問 localhost:8080/views/test1 這個頁面,但view對應的伺服器上並沒有test1這個資源,它是從另一台伺服器上調用的資源。這樣view對應的那個伺服器就使用了反向 Proxy。即使用者只需要把請求發給特定的反向 Proxy伺服器,具體請求是誰處理的使用者不需要知道(其實也不知道),由Proxy 伺服器統一處理。結論就是 反向 Proxy正好相反,對於用戶端而言它就像是原始伺服器,並且用戶端不需要進行任何特別的設定。用戶端向反向 Proxy 的命名空間(name-space)中的內容發送普通請求,接著反向 Proxy將判斷向何處(原始伺服器)轉交請求,並將獲得的內容返回給用戶端,就像這些內容 原本就是它自己的一樣。

正向 Proxy的典型用途是為在防火牆內的區域網路用戶端提供訪問Internet的途徑。正向 Proxy還可以使用緩衝特性減少網路使用率。反向 Proxy的典型用途是將 防火牆後面的伺服器提供給Internet使用者訪問。反向 Proxy還可以為後端的多台伺服器提供Server Load Balancer,或為後端較慢的伺服器提供緩衝服務。 總結

正向 Proxy:針對用戶端而言, Proxy 伺服器代理用戶端,轉寄請求,並將獲得的內容返回給用戶端。
反向 Proxy:針對用戶端而言, Proxy 伺服器就像是原始伺服器,代理叢集的web節點伺服器返回結果。 負載平衡

負載平衡也是Nginx常用的一個功能,負載平衡其意思就是分攤到多個操作單元上進行執行,例如Web伺服器、FTP伺服器、企業關鍵應用伺服器和其它關鍵任務伺服器等,從而共同完成工作任務。簡單而言就是當有2台或以上伺服器時,根據規則隨機的將請求分發到指定的伺服器上處理,負載平衡配置一般都需要同時配置反向 Proxy,通過反向 Proxy跳轉到負載平衡。而Nginx目前支援內建3種負載平衡策略,還有2種常用的第三方策略。

RR
按照輪詢(預設)方式進行負載,每個請求按時間順序逐一分配到不同的後端伺服器,如果後端伺服器down掉,能自動剔除。雖然這種方式簡便、成本低廉。但缺點是:可靠性低和負載分配不均衡。

權重
指定輪詢幾率,weight和訪問比率成正比,用於後端伺服器效能不均的情況。

upstream test{     server localhost:8080 weight=9;     server localhost:8081 weight=1;}

此時8080和8081分別佔90%和10%。

ip_hash
上面的2種方式都有一個問題,那就是下一個請求來的時候請求可能分發到另外一個伺服器,當我們的程式不是無狀態的時候(採用了session儲存資料),這時候就有一個很大的很問題了,比如把登入資訊儲存到了session中,那麼跳轉到另外一台伺服器的時候就需要重新登入了,所以很多時候我們需要一個客戶只訪問一個伺服器,那麼就需要用iphash了,iphash的每個請求按訪問ip的hash結果分配,這樣每個訪客固定訪問一個後端伺服器,可以解決session的問題。

upstream test {    ip_hash;    server localhost:8080;    server localhost:8081;}

fair(第三方)
按後端伺服器的回應時間來分配請求,回應時間短的優先分配。

upstream backend {     fair;     server localhost:8080;    server localhost:8081;}

url_hash(第三方)
按訪問url的hash結果來分配請求,使每個url定向到同一個後端伺服器,後端伺服器為緩衝時比較有效。 在upstream中加入hash語句,server語句中不能寫入weight等其他的參數,hash_method是使用的hash演算法。

upstream backend {     hash $request_uri;     hash_method crc32;     server localhost:8080;    server localhost:8081;} 
HTTP伺服器

Nginx本身也是一個靜態資源的伺服器,當只有靜態資源的時候,就可以使用Nginx來做伺服器,同時現在也很流行動靜分離,就可以通過Nginx來實現,動靜分離是讓動態網站裡的動態網頁根據一定規則把不變的資源和經常變的資源區分開來,動靜資源做好了拆分以後,我們就可以根據靜態資源的特點將其做快取作業,這就是網站靜態化處理的核心思路。 nginx進程模型

在工作方式上,Nginx分為單背景工作處理序和多背景工作處理序兩種模式。在單背景工作處理序模式下,除主進程外,還有一個背景工作處理序,背景工作處理序是單線程的;在多背景工作處理序模式下,每個背景工作處理序包含多個線程。Nginx預設為單背景工作處理序模式。

Nginx在啟動後,會有一個master進程和多個worker進程。 master進程

主要用來管理worker進程,包含:接收來自外界的訊號,向各worker進程發送訊號,監控worker進程的運行狀態,當worker進程退出後(異常情況下),會自動重新啟動新的worker進程。

master進程充當整個進程組與使用者的互動介面,同時對進程進行監護。它不需要處理網路事件,不負責業務的執行,只會通過管理worker進程來實現重啟服務、平滑升級、更換記錄檔、設定檔即時生效等功能。

我們要控制nginx,只需要通過kill向master進程發送訊號就行了。比如kill -HUP pid,則是告訴nginx,從容地重啟nginx,我們一般用這個訊號來重啟nginx,或重新載入配置,因為是從容地重啟,因此服務是不中斷的。master進程在接收到HUP訊號後是怎麼做的呢。

首先master進程在接到訊號後,會先重新載入設定檔,然後再啟動新的worker進程,並向所有老的worker進程發送訊號,告訴他們可以光榮退休了。新的worker在啟動後,就開始接收新的請求,而老的worker在收到來自master的訊號後,就不再接收新的請求,並且在當前進程中的所有未處理完的請求處理完成後,再退出。

當然,直接給master進程發送訊號,這是比較老的操作方式,nginx在0.8版本之後,引入了一系列命令列參數,來方便我們管理。比如,./nginx -s reload,就是來重啟nginx,./nginx -s stop,就是來停止nginx的運行。

如何做到的呢。我們還是拿reload來說,我們看到,執行命令時,我們是啟動一個新的nginx進程,而新的nginx進程在解析到reload參數後,就知道我們的目的是控制nginx來重新載入設定檔了,它會向master進程發送訊號,然後接下來的動作,就和我們直接向master進程發送訊號一樣了。 worker進程

而基本的網路事件,則是放在worker進程中來處理了。多個worker進程之間是對等的,他們同等競爭來自用戶端的請求,各進程互相之間是獨立的。一個請求,只可能在一個worker進程中處理,一個worker進程,不可能處理其它進程的請求。worker進程的個數是可以設定的,一般我們會設定與機器cpu核心數一致,這裡面的原因與nginx的進程模型以及事件處理模型是分不開的。

worker進程之間是平等的,每個進程,處理請求的機會也是一樣的。當我們提供80連接埠的http服務時,一個串連請求過來,每個進程都有可能處理這個串連,怎麼做到的呢。首先,每個worker進程都是從master進程fork過來,在master進程裡面,先建立好需要listen的socket(listenfd)之後,然後再fork出多個worker進程。

所有worker進程的listenfd會在新串連到來時變得可讀,為保證只有一個進程處理該串連,所有worker進程在註冊listenfd讀事件前搶accept_mutex,搶到互斥鎖的那個進程註冊listenfd讀事件,在讀事件裡調用accept接受該串連。當一個worker進程在accept這個串連之後,就開始讀取請求,解析請求,處理請求,產生資料後,再返回給用戶端,最後才中斷連線,這樣一個完整的請求就是這樣的了。

我們可以看到,一個請求,完全由worker進程來處理,而且只在一個worker進程中處理。worker進程之間是平等的,每個進程,處理請求的機會也是一樣的。當我們提供80連接埠的http服務時,一個串連請求過來,每個進程都有可能處理這個串連,怎麼做到的呢。首先,每個worker進程都是從master進程fork過來,在master進程裡面,先建立好需要listen的socket(listenfd)之後,然後再fork出多個worker進程。

所有worker進程的listenfd會在新串連到來時變得可讀,為保證只有一個進程處理該串連,所有worker進程在註冊listenfd讀事件前搶accept_mutex,搶到互斥鎖的那個進程註冊listenfd讀事件,在讀事件裡調用accept接受該串連。當一個worker進程在accept這個串連之後,就開始讀取請求,解析請求,處理請求,產生資料後,再返回給用戶端,最後才中斷連線,這樣一個完整的請求就是這樣的了。我們可以看到,一個請求,完全由worker進程來處理,而且只在一個worker進程中處理。 多進程IO模型好處

首先,對於每個worker進程來說,獨立的進程,不需要加鎖,所以省掉了鎖帶來的開銷,同時在編程以及問題尋找時,也會方便很多。

其次,採用獨立的進程,可以讓互相之間不會影響,一個進程退出後,其它進程還在工作,服務不會中斷,master進程則很快啟動新的worker進程。當然,worker進程的異常退出,肯定是程式有bug了,異常退出,會導致當前worker上的所有請求失敗,不過不會影響到所有請求,所以降低了風險。 nginx多進程事件模型:非同步非阻塞

雖然nginx採用多worker的方式來處理請求,每個worker裡面只有一個主線程,那能夠處理的並發數很有限啊,多少個worker就能處理多少個並發,何來高並發呢。非也,這就是nginx的高明之處,nginx採用了非同步非阻塞的方式來處理請求,也就是說,nginx是可以同時處理成千上萬個請求的。

一個worker進程可以同時處理的請求數只受限於記憶體大小,而且在架構設計上,不同的worker進程之間處理並發請求時幾乎沒有同步鎖的限制,worker進程通常不會進入睡眠狀態,因此,當Nginx上的進程數與CPU核心數相等時(最好每一個worker進程都綁定特定的CPU核心),進程間切換的代價是最小的。

而apache的常用工作方式(apache也有非同步非阻塞版本,但因其與內建某些模組衝突,所以不常用),每個進程在一個時刻只處理一個請求,因此,當並發數上到幾千時,就同時有幾千的進程在處理請求了。這對作業系統來說,是個不小的挑戰,進程帶來的記憶體佔用非常大,進程的環境切換帶來的cpu開銷很大,自然效能就上不去了,而這些開銷完全是沒有意義的。

為什麼nginx可以採用非同步非阻塞的方式來處理呢,或者非同步非阻塞到底是怎麼回事呢。

我們先回到原點,看看一個請求的完整過程:首先,請求過來,要建立串連,然後再接收資料,接收資料後,再發送資料。

具體到系統底層,就是讀寫事件,而當讀寫事件沒有準備好時,必然不可操作,如果不用非阻塞的方式來調用,那就得阻塞調用了,事件沒有準備好,那就只能等了,等事件準備好了,你再繼續吧。阻塞調用會進入核心等待,cpu就會讓出去給別人用了,對單線程的worker來說,顯然不合適,當網路事件越多時,大家都在等待呢,cpu空閑下來沒人用,cpu利用率自然上不去了,更別談高並發了。

好吧,你說加進程數,這跟apache的執行緒模式有什麼區別,注意,別增加無謂的環境切換。所以,在nginx裡面,最忌諱阻塞的系統調用了。不要阻塞,那就非阻塞嘍。非阻塞就是,事件沒有準備好,馬上返回EAGAIN,告訴你,事件還沒準備好呢,你慌什麼,過會再來吧。

好吧,你過一會,再來檢查一下事件,直到事件準備好了為止,在這期間,你就可以先去做其它事情,然後再來看看事件好了沒。雖然不阻塞了,但你得不時地過來檢查一下事件的狀態,你可以做更多的事情了,但帶來的開銷也是不小的。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.