Nginx負載均衡(下)
這一小節(jié)中,我們將實戰(zhàn) Nginx 的四層和七層負載均衡功能。條件有限,使用一臺公網(wǎng)主機,在上面搭建好 Nginx 服務。公網(wǎng) IP 為 180.76.152.113。
首先會進行簡單的四層負載均衡實驗,不會涉及多種負載均衡算法,只使用默認的 Round-Robin算法。在后續(xù)的七層負載均衡實驗中,會重點測試不同的負載均衡策略,完成相關(guān)實驗。
1. Nginx的四層負載均衡實驗
首先在 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模擬兩個上游服務器,然后在 upstream 指令塊中指定這兩個上游服務器的地址,同時給第一個設置權(quán)重為2。由于默認采用的是加權(quán)的 Round-Robin 算法,默認服務器的權(quán)重為1。設置為2,表明3次請求中,2次會轉(zhuǎn)發(fā)到3000端口,一次會轉(zhuǎn)發(fā)到3001端口,下面的測試也驗證了這一點。
# 第一次請求,轉(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的七層負載均衡實驗
和四層的配置其實差不多,在七層中除了測試最基本的,我們還將測試前面提到的幾種負載均衡策略,進一步熟悉 Nginx 中的負載均衡配置。
2.1 簡單的七層負載均衡
在 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三個端口模擬了3個上游服務器,默認使用輪詢負載均衡算法,而且三個的權(quán)重均為1。進行如下的 http 請求操作,可以看到 Nginx 轉(zhuǎn)發(fā) http 請求會均勻地分配到3個服務器上。
[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 負載均衡的hash算法
我們打開 ip_hash 指令的注釋,這個時候默認是使用客戶端的 ip 地址作為 hash 的 key,然后重啟 Nginx 服務并進行如下的命令行操作:
# 使用本機的ip地址,無論請求多少出,通過hash轉(zhuǎn)發(fā)到的上游服務器地址都是一致的
[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之后,請求轉(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
接下來,注釋 ip_hash 指令,我們打開 hash user_$arg_username 這行配置的注釋, hash 指令可以讓我們根據(jù)我們設置的 key 進行 hash,然后根據(jù) hash 值選擇上游的服務器。具體測試參看下面的 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
這里我們可以看到,在請求中帶上 username 參數(shù),Nginx 中配置的 hash 算法會根據(jù)請求中帶的 username 參數(shù)作為 key 去進行 hash,然后在根據(jù) hash 結(jié)果映射上游服務器。username 相同時,選擇的上游服務器肯定是一樣的,只有在 username 的值發(fā)生變化時,返回的響應才可能有變化。
3. 小結(jié)
今天我們完成了幾個測試實驗,主要是針對 Nginx 的四層和七層的負載均衡功能進行了測試。這個功能在微服務部署中會有較多的應用。因為高流量企業(yè)為保證服務的高可用性,往往會水平擴展多個相同功能的服務,部署在多臺主機上,這個時候負載均衡技術(shù)就能派上用場了,而 Nginx 提供了完善的負載均衡功能以及多種負載均衡算法,能滿足大部分企業(yè)的需求,如果還不夠,可以通過編寫內(nèi)部開發(fā)模塊并集成到 Nginx,實現(xiàn)相應的需求。所以說 Nginx 是非常值得學習和深入研究的。