一、nginx的upstream目前支持負(fù)載均衡方式的分配
1、RR(默認(rèn))
每個(gè)請(qǐng)求按時(shí)間順序逐一分配到不同的后端服務(wù)器,如果后端服務(wù)器down掉,能自動(dòng)剔除。
例如:
upstream tomcats {
server
server
}
2、ip_hash
每個(gè)請(qǐng)求按訪問ip的hash結(jié)果分配,這樣每個(gè)訪客固定訪問一個(gè)后端服務(wù)器,可以解決session的問題。
例如:
upstream tomcats {
ip_hash;
server
server
}
3、fair(第三方)
按后端服務(wù)器的響應(yīng)時(shí)間來分配請(qǐng)求,響應(yīng)時(shí)間短的優(yōu)先分配。
4、url_hash(第三方)
按訪問url的hash結(jié)果來分配請(qǐng)求,使每個(gè)url定向到同一個(gè)后端服務(wù)器,后端服務(wù)器為緩存時(shí)比較有效。
下面,我們針對(duì)RR和ip_hash的負(fù)載均衡策略進(jìn)行分析。因?yàn)槊恳环N負(fù)載均衡策略都是在upstream的框架中使用,upstream控制總的工作流程,負(fù)載均衡策略僅僅提供選擇或釋放server的函數(shù),所以,我們?cè)诜治?/span>RR時(shí)結(jié)合upstream(ngx_http_upstream.c)。 ip_hash大部分內(nèi)容與RR一致,只是重新實(shí)現(xiàn)RR中的ngx_http_upstream_get_peer函數(shù)。
二、RR策略
RR機(jī)制分為三個(gè)部分:初始化upstream,獲取一個(gè)可用的后臺(tái)服務(wù)器和釋放后臺(tái)服務(wù)器。
以下分析以此配置為例:
upstream backend {
server A max_fails=3 fail_timeout=4s weight=9;
server B max_fails=3 fail_timeout=4s weight=9;
server C max_fails=3 fail_timeout=4s weight=9;
server D backup;
Server E backup;
}
2.1 初始化upstream
對(duì)于例子中的upstream backend來說,
首先初始化各個(gè)server, 除了設(shè)置IP和端口號(hào)外,還要設(shè)置如下置weight,current_weight,max_fails和fail_timeout。其中max_fails和fail_timeout 這兩個(gè)參數(shù)是組合使用的,表示server 如果失敗次數(shù)達(dá)到max_fails 次,并保持fail_timeout秒之內(nèi)該服務(wù)器不能被訪問。
對(duì)于serverA來說,設(shè)置如下
serverA.weight =9;
serverA.current_weight = 9; //初始值等于配置文件中的weight.
serverA.max_fails = 3;
serverA.fail_timeout = 4;
接著,創(chuàng)建兩個(gè)server類型(在下文介紹中,server類型等同于peer類型,都是用來指明存儲(chǔ)upstream中一個(gè)server的信息)的數(shù)組,peers和backup,分別存儲(chǔ)正常的輪循server和備用server. 并且,按照數(shù)組中各個(gè)server的weight值的大小,由高到底排序。
本例中,在數(shù)組peers中存儲(chǔ)serverA、serverB和 serverC, 并記錄server的總個(gè)數(shù)peers->number=3; 在數(shù)組backup中存儲(chǔ)serverD和 serverE, 并記錄server的總個(gè)數(shù)backup->number=2;
最后,設(shè)置upstream中各個(gè)變量的值。
rrp 表示當(dāng)前要輪循的server數(shù)組,初始設(shè)置為Upstream->rrp = peers.
tries 表示嘗試的次數(shù),當(dāng)嘗試一個(gè)server失敗后,tries的值就會(huì)減一。初始設(shè)置為peers的總個(gè)數(shù)。
Next 表示當(dāng)peers數(shù)組中server都失敗,不能提供服務(wù)了,通過upstream->next,切換到back數(shù)組中選擇server.
2.2 具體的RR策略
當(dāng)一個(gè)客戶端請(qǐng)求到達(dá)nginx后,nginx就會(huì)在upstream的peers 數(shù)組中挑選一個(gè)current_weight最大的server作為當(dāng)前請(qǐng)求最初要輪循的server. 在peers數(shù)組中選取current_weight最大的算法如下:
由于peers數(shù)組中的server是按照weight值的大小排序好的。
它是通過雙重循環(huán),滿足下列條件后,
if (peer[n].current_weight * 1000 / peer[i].current_weight > peer[n].weight * 1000 / peer[i].weight) //peer[i].current_weight不為0
并且該server的current_weight大于0,就選擇sever n, 把編號(hào)n賦給rrp->current,成功返回。
如果當(dāng)upstream的peers 數(shù)組中的所有server的current_weight都為零時(shí),立即無(wú)條件地把所有server的current_weight設(shè)置為初始值。for (i = 0; i < peers->number; i++) {
peer[i].current_weight = peer[i].weight;
}
然后,當(dāng)所有server的current_weight設(shè)置為初始值后,重新查找peers 數(shù)組中current_weight最大的server。把編號(hào)賦給rrp->current,返回。
判斷server 是否有效的方法是:
1)如果server的失敗次數(shù)(peers->peer[i].fails)沒有達(dá)到了max_fails所設(shè)置的最大失敗次數(shù),則該server是有效的。
2)如果server已經(jīng)達(dá)到了max_fails所設(shè)置的最大失敗次數(shù),從這一時(shí)刻開始算起,在fail_timeout 所設(shè)置的時(shí)間段內(nèi), server是無(wú)效的。
3)當(dāng)server的失敗次數(shù)(peers->peer[i].fails)為最大的失敗次數(shù),當(dāng)距離現(xiàn)在的時(shí)間超過了fail_timeout 所設(shè)置的時(shí)間段, 則令peers->peer[i].fails =0,使得該server重新有效。
for (i = 0; i < peers->number; i++) {
peers->peer[i].fails = 0;
}
并返回錯(cuò)誤碼給nginx, nginx得到此錯(cuò)誤碼后,就不再向后臺(tái)server發(fā)請(qǐng)求,而是在nginx的錯(cuò)誤日志中輸出“no live upstreams while connecting to upstream”的記錄(這就是no live產(chǎn)生的真正原因),并直接返回給請(qǐng)求的客戶端一個(gè)502的錯(cuò)誤。
2.2..3.1 如果nginx在等待了proxy_connect_timeout所設(shè)置的時(shí)間段后(如3秒),連接仍然沒有建立成功,nginx就在錯(cuò)誤日志中輸出“upstream timed out (110: Connection timed out) while connecting to upstream”的記錄(這就是 timed out(連接超時(shí))產(chǎn)生的真正原因).
跳轉(zhuǎn)到
三、Ip_hash策略
3.1 Ip_hash和RR 的策略有兩點(diǎn)不同在于:
當(dāng)一個(gè)客戶請(qǐng)求到nginx后,
1)nginx如何選擇一個(gè)最初的server,
2)以及當(dāng)前選擇的server不能提供服務(wù)時(shí),如何選擇下一個(gè)server.
3.2 RR策略回顧
從第二部分對(duì)RR的介紹中,我們知道:
當(dāng)一個(gè)客戶請(qǐng)求到達(dá)后,RR策略是從upstream的所有server中選擇一個(gè)當(dāng)前權(quán)重(current_weight)最大的server作為最初的server.
upstream的所有server是按照由高到低排序后存儲(chǔ)在一個(gè)peers數(shù)組中,當(dāng)最初選擇的server不能提供服務(wù)時(shí),RR策略就會(huì)選擇peers數(shù)組中的下一個(gè)元素作為當(dāng)前server,繼續(xù)嘗試, 如果已經(jīng)達(dá)到數(shù)組的最大元素,就會(huì)從第一個(gè)元素再輪循。
3.3 ip_hash策略介紹
在ip_hash策略中,它選擇最初的server的方法是根據(jù)請(qǐng)求客戶端的IP計(jì)算出一個(gè)哈希值,再根據(jù)哈希值選擇后臺(tái)的服務(wù)器。
1)由IP計(jì)算哈希值的算法如下, 其中公式中hash初始值為89,iphp->addr[i]表示客戶端的IP, 通過三次哈希計(jì)算得出一個(gè)IP的哈希值:
for (i = 0; i < 3; i++) {
hash = (hash * 113 + iphp->addr[i]) % 6271;
}
2)在選擇下一個(gè)server時(shí),ip_hash的選擇策略是這樣的:
它在上一次哈希值的基礎(chǔ)上,再次哈希,就會(huì)得到一個(gè)全新的哈希值,再根據(jù)哈希值選擇另外一個(gè)后臺(tái)的服務(wù)器。
哈希算法仍然是
for (i = 0; i < 3; i++) {
hash = (hash * 113 + iphp->addr[i]) % 6271;
}
在這種ip_hash策略,如果一個(gè)后臺(tái)服務(wù)器不能提供提服務(wù)(連接超時(shí)或讀超時(shí)),該服務(wù)器的失敗次數(shù)就會(huì)加一,當(dāng)一個(gè)服務(wù)器的失敗次數(shù)達(dá)到max_fails所設(shè)置的值,就會(huì)在fail_timeout所設(shè)置的時(shí)間段內(nèi)不能對(duì)外提供服務(wù),這點(diǎn)和RR是一致的。
如果當(dāng)前server不能提供服務(wù),就會(huì)根據(jù)當(dāng)前的哈希值再哈希出一個(gè)新哈希值,選擇另一個(gè)服務(wù)器繼續(xù)嘗試,嘗試的最大次是upstream中server的個(gè)數(shù),如果server的個(gè)數(shù)超過20,也就是要最大嘗試次數(shù)在20次以上,當(dāng)嘗試次數(shù)達(dá)到20次,仍然找不到一個(gè)合適的服務(wù)器,ip_hah策略不再嘗試ip哈希值來選擇server, 而在剩余的嘗試中,它會(huì)轉(zhuǎn)而使用RR的策略,使用輪循的方法,選擇新的server。
3)除了以上部分不同外,IP_hash的其余部分和RR完全一樣,因?yàn)樗钠溆嗖糠止δ艿膶?shí)現(xiàn)都是通過調(diào)用RR中的函數(shù)。
4)IP_hash優(yōu)勢(shì)是把同一個(gè)客戶IP的請(qǐng)求分配給同一個(gè)后臺(tái)服務(wù)器。
聯(lián)系客服
微信登錄中...
請(qǐng)勿關(guān)閉此頁(yè)面