Nginx負(fù)載均衡(下)
這一小節(jié)中,我們將實(shí)戰(zhàn) Nginx 的四層和七層負(fù)載均衡功能。條件有限,使用一臺(tái)公網(wǎng)主機(jī),在上面搭建好 Nginx 服務(wù)。公網(wǎng) IP 為 180.76.152.113。
首先會(huì)進(jìn)行簡(jiǎn)單的四層負(fù)載均衡實(shí)驗(yàn),不會(huì)涉及多種負(fù)載均衡算法,只使用默認(rèn)的 Round-Robin算法。在后續(xù)的七層負(fù)載均衡實(shí)驗(yàn)中,會(huì)重點(diǎn)測(cè)試不同的負(fù)載均衡策略,完成相關(guān)實(shí)驗(yàn)。
1. Nginx的四層負(fù)載均衡實(shí)驗(yàn)
首先在 nginx.conf 中添加如下 stream 指令塊配置:
stream {
server {
listen 3000;
return '3000 server get ip: $remote_addr!\n';
}
server {
listen 3001;
return '3001 server get ip: $remote_addr!\n';
}
upstream servers {
server 127.0.0.1:3000 weight=2;
server 127.0.0.1:3001;
}
server {
listen 30;
proxy_connect_timeout 3s;
proxy_timeout 3s;
proxy_pass servers;
}
}
上述配置用端口3000和3001模擬兩個(gè)上游服務(wù)器,然后在 upstream 指令塊中指定這兩個(gè)上游服務(wù)器的地址,同時(shí)給第一個(gè)設(shè)置權(quán)重為2。由于默認(rèn)采用的是加權(quán)的 Round-Robin 算法,默認(rèn)服務(wù)器的權(quán)重為1。設(shè)置為2,表明3次請(qǐng)求中,2次會(huì)轉(zhuǎn)發(fā)到3000端口,一次會(huì)轉(zhuǎn)發(fā)到3001端口,下面的測(cè)試也驗(yàn)證了這一點(diǎn)。
# 第一次請(qǐng)求,轉(zhuǎn)發(fā)到3000
[shen@shen ~]$ telnet 180.76.152.113 30
Trying 180.76.152.113...
Connected to 180.76.152.113.
Escape character is '^]'.
3000 server get ip: 127.0.0.1!
Connection closed by foreign host.
[shen@shen ~]$ telnet 180.76.152.113 30
Trying 180.76.152.113...
Connected to 180.76.152.113.
Escape character is '^]'.
3001 server get ip: 127.0.0.1!
Connection closed by foreign host.
[shen@shen ~]$ telnet 180.76.152.113 30
Trying 180.76.152.113...
Connected to 180.76.152.113.
Escape character is '^]'.
3000 server get ip: 127.0.0.1!
Connection closed by foreign host.
[shen@shen ~]$ telnet 180.76.152.113 30
Trying 180.76.152.113...
Connected to 180.76.152.113.
Escape character is '^]'.
3000 server get ip: 127.0.0.1!
Connection closed by foreign host.
2. Nginx的七層負(fù)載均衡實(shí)驗(yàn)
和四層的配置其實(shí)差不多,在七層中除了測(cè)試最基本的,我們還將測(cè)試前面提到的幾種負(fù)載均衡策略,進(jìn)一步熟悉 Nginx 中的負(fù)載均衡配置。
2.1 簡(jiǎn)單的七層負(fù)載均衡
在 nginx.conf 中添加如下的 http 指令塊:
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log logs/access.log main;
sendfile on;
keepalive_timeout 65;
gzip on;
server {
listen 8000;
return 200 '8000, server\n';
}
server {
listen 8001;
return 200 '8001, server\n';
}
server {
listen 8002;
return 200 '8002, server\n';
}
upstream backends {
# ip_hash
# hash user_$arg_username;
server 127.0.0.1:8000;
server 127.0.0.1:8001;
server 127.0.0.1:8002;
}
server {
listen 80;
location / {
proxy_pass http://backends;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}
}
上述配置中,我們用8000,8001和8002三個(gè)端口模擬了3個(gè)上游服務(wù)器,默認(rèn)使用輪詢負(fù)載均衡算法,而且三個(gè)的權(quán)重均為1。進(jìn)行如下的 http 請(qǐng)求操作,可以看到 Nginx 轉(zhuǎn)發(fā) http 請(qǐng)求會(huì)均勻地分配到3個(gè)服務(wù)器上。
[shen@shen ~]$ curl http://180.76.152.113
8000, server
[shen@shen ~]$ curl http://180.76.152.113
8001, server
[shen@shen ~]$ curl http://180.76.152.113
8002, server
[shen@shen ~]$ curl http://180.76.152.113
8000, server
2.2 負(fù)載均衡的hash算法
我們打開(kāi) ip_hash 指令的注釋,這個(gè)時(shí)候默認(rèn)是使用客戶端的 ip 地址作為 hash 的 key,然后重啟 Nginx 服務(wù)并進(jìn)行如下的命令行操作:
# 使用本機(jī)的ip地址,無(wú)論請(qǐng)求多少出,通過(guò)hash轉(zhuǎn)發(fā)到的上游服務(wù)器地址都是一致的
[shen@shen ~]$ curl http://180.76.152.113
8002, server
[shen@shen ~]$ curl http://180.76.152.113
8002, server
[shen@shen ~]$ curl http://180.76.152.113
8002, server
# 只有換了ip之后,請(qǐng)求轉(zhuǎn)發(fā)的上游地址才可能有變化
[shen@shen ~]$ curl -H 'X-Forwarded-For: 111.10.1.3' http://180.76.152.113
8000, server
[shen@shen ~]$ curl -H 'X-Forwarded-For: 111.10.2.3' http://180.76.152.113
8001, server
2.3 使用其他key做hash
接下來(lái),注釋 ip_hash 指令,我們打開(kāi) hash user_$arg_username 這行配置的注釋, hash 指令可以讓我們根據(jù)我們?cè)O(shè)置的 key 進(jìn)行 hash,然后根據(jù) hash 值選擇上游的服務(wù)器。具體測(cè)試參看下面的 Linux 命令:
[shen@shen ~]$ curl http://180.76.152.113?username=shen
8001, server
[shen@shen ~]$ curl http://180.76.152.113?username=test
8000, server
[shen@shen ~]$ curl http://180.76.152.113?username=test
8000, server
[shen@shen ~]$ curl http://180.76.152.113?username=test
8000, server
這里我們可以看到,在請(qǐng)求中帶上 username 參數(shù),Nginx 中配置的 hash 算法會(huì)根據(jù)請(qǐng)求中帶的 username 參數(shù)作為 key 去進(jìn)行 hash,然后在根據(jù) hash 結(jié)果映射上游服務(wù)器。username 相同時(shí),選擇的上游服務(wù)器肯定是一樣的,只有在 username 的值發(fā)生變化時(shí),返回的響應(yīng)才可能有變化。
3. 小結(jié)
今天我們完成了幾個(gè)測(cè)試實(shí)驗(yàn),主要是針對(duì) Nginx 的四層和七層的負(fù)載均衡功能進(jìn)行了測(cè)試。這個(gè)功能在微服務(wù)部署中會(huì)有較多的應(yīng)用。因?yàn)楦吡髁科髽I(yè)為保證服務(wù)的高可用性,往往會(huì)水平擴(kuò)展多個(gè)相同功能的服務(wù),部署在多臺(tái)主機(jī)上,這個(gè)時(shí)候負(fù)載均衡技術(shù)就能派上用場(chǎng)了,而 Nginx 提供了完善的負(fù)載均衡功能以及多種負(fù)載均衡算法,能滿足大部分企業(yè)的需求,如果還不夠,可以通過(guò)編寫(xiě)內(nèi)部開(kāi)發(fā)模塊并集成到 Nginx,實(shí)現(xiàn)相應(yīng)的需求。所以說(shuō) Nginx 是非常值得學(xué)習(xí)和深入研究的。