nginx是一個強大的web服務器軟件,用於處理高併發的http請求和做爲反向代理服務器作負載均衡。具備高性能、輕量級、內存消耗少,強大的負載均衡能力等優點。nginx
如上官方示意圖所示,nginx啓動之後,會在系統中以daemon的方式在後臺運行,其中包括一個master進程,n(n>=1)個worker進程。web
其中,master進程用於接收來自外界的信號,並給worker進程發送信號,同時監控worker進程的工做狀態。apache
worker進程則是外部請求真正的處理者,每一個worker請求相互獨立且平等的競爭來自客戶端的請求。請求只能在一個worker進程中被處理,且一個worker進程只有一個主線程,因此同時只能處理一個請求。那麼問題來了,一個worker進程只有一個主線程,只能同時處理一個請求,nginx對高併發請求強大的處理能力是如何保證的呢?答案是nginx採用異步非阻塞的方式來處理請求,即單線程、非阻塞、異步IO的工做模型。對比apache的異步非阻塞版本的工做模式,apache會爲每個請求新建一個線程去處理請求,線程進行上下文切換,會形成內存和CPU的浪費。反看nginx的異步非阻塞io模式,實用操做系統提供的io多路複用技術(epoll),在一個線程中處理全部請求,當一個io操做開始的時候,nginx不會等待其完成就回去處理下一個請求,等到io操做完成後,nginx再回來處理這一次請求io操做的後續工做。相比apache,nginx省去了線程上下文切換帶來的資源開銷。 後端
那麼nginx如何肯定哪一個worker來處理請求呢?首先,每一個worker進程都是從master進程fork過來,在master進程裏面,先創建好須要listen的socket(listenfd)以後,而後再fork出多個worker進程。全部worker進程的listenfd會在新鏈接到來時變得可讀,爲保證只有一個進程處理該鏈接,全部worker進程在註冊listenfd讀事件前搶accept_mutex,搶到互斥鎖的那個進程註冊listenfd讀事件,在讀事件裏調用accept接受該鏈接。當一個worker進程在accept這個鏈接以後,就開始讀取請求,解析請求,處理請求,產生數據後,再返回給客戶端,最後才斷開鏈接,這樣一個完整的請求就是這樣的了。這樣,一個請求,徹底由worker進程來處理,並且只在一個worker進程中處理。緩存
這裏援引網上搜索到的nginx的測試數據:10000個非活躍的HTTP keep-alive 鏈接僅佔用約2.5MB內存。三萬併發鏈接下,10個Nginx進程,消耗內存150M。淘寶tengine團隊說測試結果是「24G內存機器上,處理併發請求可達200萬」。tomcat
通訊協議支持:nginx負載均衡主要是對七層網絡通訊模型中的第七層應用層上的http、https進行支持。同時nginx更新版本也在逐步對Websocket、SPDY等協議做出支持。服務器
nginx是以反向代理的方式進行負載均衡的。反向代理(Reverse Proxy)方式是指以代理服務器來接受Internet上的鏈接請求,而後將請求轉發給內部網絡上的服務器,並將從服務器上獲得的結果返回給Internet上請求鏈接的客戶端,此時代理服務器對外就表現爲一個服務器。(爲了理解反向代理,這裏插播一條什麼是正向代理:正向代理指的是,一個位於客戶端和原始服務器之間的服務器,爲了從原始服務器取得內容,客戶端向代理髮送一個請求並指定目標(原始服務器),而後代理向原始服務器轉交請求並將得到的內容返回給客戶端。)網絡
這裏再插播一條實現負載均衡的技術的方式有哪些:硬件層面有F5負載均衡器,網絡層層面有LVS(Linux Virtual Server),應用層層面就是nginx、Haproxy等。session
nginx實現負載均衡的分配策略有不少,被編進nginx內核的策略有輪詢和ip_hash,第三方的有fair、url_hash等。這裏主要對內核策略進行介紹。架構
1.輪詢
a)none(默認輪詢):upstream按照輪詢(默認)方式進行負載,每一個請求按時間順序逐一分配到不一樣的後端服務器,若是後端服務器down掉,能自動剔除。雖然這種方式簡便、成本低廉。但缺點是:可靠性低和負載分配不均衡。
b)weight(按權重輪詢):指定輪詢概率,weight和訪問比率成正比,用於後端服務器性能不均的狀況。
server 192.168.61.22 weight = 6; # 60% 請求 server 192.168.61.23 weight = 4; # 40% 請求
2.ip_hash
每一個請求按訪問ip的hash結果分配,這樣每一個訪客固定訪問一個後端服務器,能夠解決session的問題。配置只須要在upstream中加入"ip_hash;"便可。
upstream tomcats { ip_hash; server 127.0.0.1:9001; server 127.0.0.1:9002; }
3.fair(第三方)
按後端服務器的響應時間來分配請求,響應時間短的優先分配。與weight分配策略相似。
upstream tomcats { server 127.0.0.1:9001; server 127.0.0.1:9002; fair; }
4.url_hash(第三方)
和IP哈希相似,只不過針對請求的url進行hash(基於緩存的server,頁面靜態化)。