nginx負載均衡的5種策略及原理

版權聲明:本文爲博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處連接和本聲明。
本文連接: http://www.javashuo.com/article/p-crzvlagr-dh.html

nginx的upstream目前支持的5種方式的分配html


一、輪詢(默認)
每一個請求按時間順序逐一分配到不一樣的後端服務器,若是後端服務器down掉,能自動剔除。 
upstream backserver { 
server 192.168.0.14; 
server 192.168.0.15; 


二、指定權重
指定輪詢概率,weight和訪問比率成正比,用於後端服務器性能不均的狀況。 
upstream backserver { 
server 192.168.0.14 weight=8; 
server 192.168.0.15 weight=10; 


三、IP綁定 ip_hash
每一個請求按訪問ip的hash結果分配,這樣每一個訪客固定訪問一個後端服務器,能夠解決session的問題。 
upstream backserver { 
ip_hash; 
server 192.168.0.14:88; 
server 192.168.0.15:80; 


四、fair(第三方)
按後端服務器的響應時間來分配請求,響應時間短的優先分配。 
upstream backserver { 
server server1; 
server server2; 
fair; 


五、url_hash(第三方)
按訪問url的hash結果來分配請求,使每一個url定向到同一個後端服務器,後端服務器爲緩存時比較有效。 
upstream backserver { 
server squid1:3128; 
server squid2:3128; 
hash $request_uri; 
hash_method crc32; 


在須要使用負載均衡的server中增長 

proxy_pass http://backserver/; 
upstream backserver{ 
ip_hash; 
server 127.0.0.1:9090 down; (down 表示當前的server暫時不參與負載) 
server 127.0.0.1:8080 weight=2; (weight 默認爲1.weight越大,負載的權重就越大) 
server 127.0.0.1:6060; 
server 127.0.0.1:7070 backup; (其它全部的非backup機器down或者忙的時候,請求backup機器) 


max_fails :容許請求失敗的次數默認爲1.當超過最大次數時,返回proxy_next_upstream 模塊定義的錯誤 
fail_timeout:max_fails次失敗後,暫停的時間前端

 

深刻解析:

1 前言



隨着網站負載的不斷增長,負載均衡(load balance)已不是陌生話題。負載均衡是將流量負載分攤到不一樣的服務單元,保證服務器的高可用,保證響應足夠快,給用戶良好的體驗。

nginx第一個公開版發佈於2004年。2011年發佈了1.0版。它的特色是穩定性高、功能強大、資源消耗低。從服務器市場佔有率來看,nginx已有與Apache平起平坐勢頭。其中,不得不提到的特性就是其負載均衡功能,這也成了不少公司選擇它的主要緣由。

咱們將從源碼的角度介紹nginx的內置負載均衡策略和擴展負載均衡策略,以實際的工業生產爲案例,對比各負載均衡策略,爲nginx使用者提供一些參考。
 nginx

2. 源碼剖析



nginx的負載均衡策略能夠劃分爲兩大類:內置策略和擴展策略。

內置策略包含加權輪詢和ip hash,在默認狀況下這兩種策略會編譯進nginx內核,只需在nginx配置中指明參數便可。擴展策略有不少,如fair、通用hash、consistent hash等,默認不編譯進nginx內核。

因爲在nginx版本升級中負載均衡的代碼沒有本質性的變化,所以下面將以nginx1.0.15穩定版爲例,從源碼角度分析各個策略。

2.1. 加權輪詢(weighted round robin)

輪詢的原理很簡單,首先咱們介紹一下輪詢的基本流程。以下是處理一次請求的流程圖:



圖中有兩點須要注意:

第一,若是能夠把加權輪詢算法分爲先深搜索和先廣搜索,那麼nginx採用的是先深搜索算法,即將首先將請求都分給高權重的機器,直到該機器的權值降到了比其餘機器低,纔開始將請求分給下一個高權重的機器。

第二,當全部後端機器都down掉時,nginx會當即將全部機器的標誌位清成初始狀態,以免形成全部的機器都處在timeout的狀態,從而致使整個前端被夯住。

接下來看下源碼。nginx的目錄結構很清晰,加權輪詢所在路徑爲nginx-1.0.15/src/http/ngx_http_upstream_round_robin.[c|h],在源碼的基礎上,針對重要的、不易理解的地方我加了註釋。首先看下ngx_http_upstream_round_robin.h中的重要聲明:



從變量命名中就能夠大體猜出其做用。解釋一下current_weight和weight的區別,前者爲權重排序的值,隨着處理請求會動態的變化,後者則是配置值,用來恢復初始狀態。

接下咱們來看下輪詢的建立過程。代碼以下圖:



這裏有個tried變量須要作些說明:tried中記錄了服務器當前是否被嘗試鏈接過。他是一個位圖。若是服務器數量小於32,則只需在一個int中便可記錄下全部服務器狀態。若是服務器數量大於32,則需在內存池中申請內存來存儲。

對該位圖數組的使用可參考以下代碼:



最後是實際的策略代碼,邏輯較簡單,代碼實現也只有30行。來看代碼。



2.2. ip hash策略

ip hash是nginx內置的另外一個負載均衡策略,流程和輪詢很相似,只是其中的算法和具體的策略有些變化。以下圖所示:



ip hash算法的核心實現請看以下代碼:



能夠看到,hash值既與ip有關又與後端機器的數量有關。經測試,上述算法能夠連續產生1045個互異的value,這是此算法硬限制。nginx使用了保護機制,當通過20次hash仍然找不到可用的機器時,算法退化成輪詢。

所以,從本質上說,ip hash算法是一種變相的輪詢算法,若是兩個ip的初始hash值剛好相同,那麼來自這兩個ip的請求將永遠落在同一臺服務器上,這爲均衡性埋下了較深隱患。

2.3. fair

fair策略是擴展策略,默認不被編譯進nginx內核。它根據後端服務器的響應時間判斷負載狀況,從中選出負載最輕的機器進行分流。
這種策略具備很強的自適應性,可是實際的網絡環境每每不是那麼簡單,所以須慎用。

2.4.通用hash、一致性hash

通用hash和一致性hash也是種擴展策略。通用hash能夠以nginx內置的變量爲key進行hash,一致性hash採用了nginx內置的一致性hash環,可支持memcache。
 web

3 對比測試



瞭解了以上負載均衡策略,接下來咱們來作一些測試。
主要是對比各個策略的均衡性、一致性、容災性等,從而分析出其中的差別性,根據數據給出各自的適用場景。

爲了可以全面、客觀的測試nginx的負載均衡策略,咱們採用兩個測試工具、在不一樣場景下作測試,以此來下降環境對測試結果形成的影響。

首先給你們介紹測試工具、測試網絡拓撲和基本之測試流程。

3.1 測試工具

3.1.1  easyABC

easyABC是百度內部開發的性能測試工具,培訓採用epool模型實現,簡單易上手,能夠模擬GET/POST請求,極限狀況下能夠提供上萬的壓力,在團隊內部獲得普遍使用。

因爲被測試對象爲反向代理服務器,所以須要在其後端搭建樁服務器,這裏用nginx做爲樁Web Server,提供最基本的靜態文件服務。

3.1.2  polygraph

polygraph是一款免費的性能測試工具,以對緩存服務、代理、交換機等方面的測試見長。它有規範的配置語言PGL(Polygraph Language),爲軟件提供了強大的靈活性。其工做原理以下圖所示:



polygraph提供Client端和Server端,將測試目標nginx放在兩者之間,三者之間的網絡交互均走http協議,只需配置ip+port便可。

Client端能夠配置虛擬robot的個數以及每一個robot發請求的速率,並向代理服務器發起隨機的靜態文件請求,Server端將按照請求的url生成隨機大小的靜態文件作響應。

選用這個測試軟件的一個主要緣由:能夠產生隨機的url做爲nginx各類hash策略key。
另外polygraph還提供了日誌分析工具,功能比較豐富,感興趣的同窗能夠參考附錄材料。

3.2. 測試環境

本次測試運行在5臺物理機。其中:被測對象單獨搭在一臺8核機器上,另外四臺4核機器分別搭建了easyABC、webserver樁和polygraph。以下圖所示:



3.3. 測試方案

給各位介紹一下關鍵的測試指標:

均衡性:是否可以將請求均勻的發送給後端
一致性:同一個key的請求,是否能落到同一臺機器
容災性:當部分後端機器掛掉時,是否可以正常工做

以上述指標爲指導,咱們針對以下4個測試場景分別用easyABC和polygraph測試:

場景1      server_*均正常提供服務;
場景2      server_4掛掉,其餘正常;
場景3      server_三、server_4掛掉,其餘正常;
場景4      server_*均恢復正常服務。

上述四個場景將按照時間順序進行,每一個場景將創建在上一個場景基礎上,被測試對象無需作任何操做,以最大程度模擬實際狀況。

另外,考慮到測試工具自身的特色,在easyabc上的測試壓力在17000左右,polygraph上的測試壓力在4000左右。以上測試均保證被測試對象能夠正常工做,且無任何notice級別以上(alert/error/warn)的日誌出現,在每一個場景中記錄下server_*的qps用於最後的策略分析。

3.4.  結果

對比在兩種測試工具下的測試結果會發現,結果徹底一致,所以能夠排除測試工具的影響。表1和圖1是輪詢策略在兩種測試工具下的負載狀況。

從圖表中能夠看出,輪詢策略對於均衡性和容災性均可以作到較好的知足。





表2和圖2是fair策略在兩種測試工具下的負載狀況。fair策略受環境影響很是大,在排除了測試工具的干擾以後,結果仍然有很是大的抖動。

從直觀上講,這徹底不知足均衡性。但從另外一個角度出發,偏偏是因爲這種自適應性確保了在複雜的網絡環境中可以物盡所用。所以,在應用到工業生產中以前,須要在具體的環境中作好測試工做。





如下圖表是各類hash策略,所不一樣的僅僅是hash key或者是具體的算法實現,所以一塊兒作對比。實際測試中發現,通用hash和一致性hash均存在一個問題:當某臺後端的機器掛掉時,原有落到這臺機器上的流量會丟失,可是在ip hash中就不存在這樣的問題。

正如上文中對ip hash源碼的分析,當ip hash失效時,會退化爲輪詢策略,所以不會有丟失流量的狀況。從這個層面上說,ip hash也能夠當作是輪詢的升級版。



圖5爲ip hash策略,ip hash是nginx內置策略,能夠看作是前兩種策略的特例:以來源IP爲key。

因爲測試工具不太擅於模擬海量IP下的請求,所以這裏截取線上實際的狀況加以分析。以下圖所示:



圖5 IP Hash策略

圖中前1/3使用輪詢策略,中間段使用ip hash策略,後1/3仍然是輪詢策略。能夠明顯的看出,ip hash的均衡性存在着很大的問題。

緣由並不難分析,在實際的網絡環境中,有大量的高校出口路由器ip、企業出口路由器ip等網絡節點,這些節點帶來的流量每每是普通用戶的成百上千倍,而ip hash策略偏偏是按照ip來劃分流量,所以形成上述後果也就天然而然了。
 算法

4 小結



經過實際的對比測試,咱們對nginx各個負載均衡策略進行了驗證。下面從均衡性、一致性、容災性以及適用場景等角度對比各類策略。以下圖示:



咱們從源碼和實際測試數據角度分析說明了nginx負載均衡的策略,給出了各類策略適合的應用場景。經過分析不難發現,不管哪一種策略都不是萬金油,在具體場景下應該選擇哪一種策略必定程度上依賴於使用者對策略的熟悉程度。

以上分析和測試數據可以對你們有所幫助,期待有更多愈來愈好的負載均衡策略涌現,造福更多運維開發同窗。
 後端

參考:

https://www.cnblogs.com/wpjamer/articles/6443332.html數組

http://www.javashuo.com/article/p-efxuillj-mv.html緩存

相關文章
相關標籤/搜索