負載均衡(Load balancing)是一種計算機網(wǎng)絡(luò)技術(shù),用來在多個計算機(計算機集群)、網(wǎng)絡(luò)連接、CPU、磁盤驅(qū)動器或其他資源中分配負載,以達到最佳化資源使用、最大化吞吐率、最小化響應時間、同時避免過載的目的。
使用帶有負載均衡的多個服務(wù)器組件,取代單一的組件,可以通過冗余提高可靠性。負載均衡服務(wù)通常是由專用軟體和硬件來完成。
負載均衡最重要的一個應用是利用多臺服務(wù)器提供單一服務(wù),這種方案有時也稱之為服務(wù)器農(nóng)場。通常,負載均衡主要應用于 Web 網(wǎng)站,大型的 Internet Relay Chat 網(wǎng)絡(luò),高流量的文件下載網(wǎng)站,NNTP(Network News Transfer Protocol)服務(wù)和 DNS 服務(wù)?,F(xiàn)在負載均衡器也開始支持數(shù)據(jù)庫服務(wù),稱之為數(shù)據(jù)庫負載均衡器。
對于互聯(lián)網(wǎng)服務(wù),負載均衡器通常是一個軟體程序,這個程序偵聽一個外部端口,互聯(lián)網(wǎng)用戶可以通過這個端口來訪問服務(wù),而作為負載均衡器的軟體會將用戶的請求轉(zhuǎn)發(fā)給后臺內(nèi)網(wǎng)服務(wù)器,內(nèi)網(wǎng)服務(wù)器將請求的響應返回給負載均衡器,負載均衡器再將響應發(fā)送到用戶,這樣就向互聯(lián)網(wǎng)用戶隱藏了內(nèi)網(wǎng)結(jié)構(gòu),阻止了用戶直接訪問后臺(內(nèi)網(wǎng))服務(wù)器,使得服務(wù)器更加安全,可以阻止對核心網(wǎng)絡(luò)棧和運行在其它端口服務(wù)的攻擊。
當所有后臺服務(wù)器出現(xiàn)故障時,有些負載均衡器會提供一些特殊的功能來處理這種情況。例如轉(zhuǎn)發(fā)請求到一個備用的負載均衡器、顯示一條關(guān)于服務(wù)中斷的消息等。負載均衡器使得 IT 團隊可以顯著提高容錯能力。它可以自動提供大量的容量以處理任何應用程序流量的增加或減少。
負載均衡在互聯(lián)網(wǎng)世界中的作用如此重要,本章我們一起了解一下 Nginx 是如何幫我們完成 HTTP 協(xié)議負載均衡的。
配置示例,如下:
upstream test.net{
ip_hash;
server 192.168.10.13:80;
server 192.168.10.14:80 down;
server 192.168.10.15:8009 max_fails=3 fail_timeout=20s;
server 192.168.10.16:8080;
}
server {
location / {
proxy_pass http://test.net;
}
}
upstream 是 Nginx 的 HTTP Upstream 模塊,這個模塊通過一個簡單的調(diào)度算法來實現(xiàn)客戶端 IP 到后端服務(wù)器的負載均衡。在上面的設(shè)定中,通過 upstream 指令指定了一個負載均衡器的名稱 test.net。這個名稱可以任意指定,在后面需要用到的地方直接調(diào)用即可。
Nginx 的負載均衡模塊目前支持 6 種調(diào)度算法,下面進行分別介紹,其中后兩項屬于第三方調(diào)度算法。
在 HTTP Upstream 模塊中,可以通過 server 指令指定后端服務(wù)器的 IP 地址和端口,同時還可以設(shè)定每個后端服務(wù)器在負載均衡調(diào)度中的狀態(tài)。常用的狀態(tài)有:
當負載調(diào)度算法為 ip_hash 時,后端服務(wù)器在負載均衡調(diào)度中的狀態(tài)不能是 backup。
http://wiki.jikexueyuan.com/project/openresty/images/ngx_balance.png" alt="實驗拓撲" />
Nginx 配置負載均衡
upstream webservers {
server 192.168.18.201 weight=1;
server 192.168.18.202 weight=1;
}
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
proxy_pass http://webservers;
proxy_set_header X-Real-IP $remote_addr;
}
}
注,upstream 是定義在 server{ }
之外的,不能定義在 server{ }
內(nèi)部。定義好 upstream 之后,用 proxy_pass 引用一下即可。
重新加載一下配置文件
# service nginx reload
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
# curl http://192.168.18.208
web1.test.com
# curl http://192.168.18.208
web2.test.com
# curl http://192.168.18.208
web1.test.com
# curl http://192.168.18.208
web2.test.com
注,大家可以不斷的刷新瀏覽的內(nèi)容,可以發(fā)現(xiàn) web1 與 web2 是交替出現(xiàn)的,達到了負載均衡的效果。
查看一下Web訪問服務(wù)器日志
Web1:
# tail /var/log/nginx/access_log
192.168.18.138 - - [04/Sep/2013:09:41:58 +0800] "GET / HTTP/1.0" 200 23 "-"
192.168.18.138 - - [04/Sep/2013:09:41:58 +0800] "GET / HTTP/1.0" 200 23 "-"
192.168.18.138 - - [04/Sep/2013:09:41:59 +0800] "GET / HTTP/1.0" 200 23 "-"
192.168.18.138 - - [04/Sep/2013:09:41:59 +0800] "GET / HTTP/1.0" 200 23 "-"
192.168.18.138 - - [04/Sep/2013:09:42:00 +0800] "GET / HTTP/1.0" 200 23 "-"
192.168.18.138 - - [04/Sep/2013:09:42:00 +0800] "GET / HTTP/1.0" 200 23 "-"
192.168.18.138 - - [04/Sep/2013:09:42:00 +0800] "GET / HTTP/1.0" 200 23 "-"
192.168.18.138 - - [04/Sep/2013:09:44:21 +0800] "GET / HTTP/1.0" 200 23 "-"
192.168.18.138 - - [04/Sep/2013:09:44:22 +0800] "GET / HTTP/1.0" 200 23 "-"
192.168.18.138 - - [04/Sep/2013:09:44:22 +0800] "GET / HTTP/1.0" 200 23 "-"
Web2:
先修改一下,Web 服務(wù)器記錄日志的格式。
# LogFormat "%{X-Real-IP}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
# tail /var/log/nginx/access_log
192.168.18.138 - - [04/Sep/2013:09:50:28 +0800] "GET / HTTP/1.0" 200 23 "-"
192.168.18.138 - - [04/Sep/2013:09:50:28 +0800] "GET / HTTP/1.0" 200 23 "-"
192.168.18.138 - - [04/Sep/2013:09:50:28 +0800] "GET / HTTP/1.0" 200 23 "-"
192.168.18.138 - - [04/Sep/2013:09:50:28 +0800] "GET / HTTP/1.0" 200 23 "-"
192.168.18.138 - - [04/Sep/2013:09:50:28 +0800] "GET / HTTP/1.0" 200 23 "-"
192.168.18.138 - - [04/Sep/2013:09:50:28 +0800] "GET / HTTP/1.0" 200 23 "-"
192.168.18.138 - - [04/Sep/2013:09:50:28 +0800] "GET / HTTP/1.0" 200 23 "-"
192.168.18.138 - - [04/Sep/2013:09:50:28 +0800] "GET / HTTP/1.0" 200 23 "-"
192.168.18.138 - - [04/Sep/2013:09:50:29 +0800] "GET / HTTP/1.0" 200 23 "-"
192.168.18.138 - - [04/Sep/2013:09:50:29 +0800] "GET / HTTP/1.0" 200 23 "-"
注,大家可以看到,兩臺服務(wù)器日志都記錄是 192.168.18.138 訪問的日志,也說明了負載均衡配置成功。
利用 max_fails、fail_timeout 參數(shù),控制異常情況,示例配置如下:
upstream webservers {
server 192.168.18.201 weight=1 max_fails=2 fail_timeout=2;
server 192.168.18.202 weight=1 max_fails=2 fail_timeout=2;
}
重新加載一下配置文件:
# service nginx reload
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
重新載入 nginx: [確定]
先停止 Web1,進行測試:
# service nginx stop
停止 nginx: [確定]
# curl http://192.168.18.208
web2.test.com
# curl http://192.168.18.208
web2.test.com
# curl http://192.168.18.208
web2.test.com
注,大家可以看到,現(xiàn)在只能訪問 Web2,再重新啟動 Web1,再次訪問一下。
# service nginx start
正在啟動 nginx: [確定]
# curl http://192.168.18.208
web1.test.com
# curl http://192.168.18.208
web2.test.com
# curl http://192.168.18.208
web1.test.com
# curl http://192.168.18.208
web2.test.com
PS:大家可以看到,現(xiàn)在又可以重新訪問,說明 Nginx 的健康狀態(tài)查檢配置成功。但大家想一下,如果不幸的是所有服務(wù)器都不能提供服務(wù)了怎么辦,用戶打開頁面就會出現(xiàn)出錯頁面,那么會帶來用戶體驗的降低,所以我們能不能像配置 LVS 是配置 sorry_server 呢,答案是可以的,但這里不是配置 sorry_server 而是配置 backup。
備份服務(wù)器配置:
server {
listen 8080;
server_name localhost;
root /data/www/errorpage;
index index.html;
}
index.html 文件內(nèi)容:
# cat index.html
<h1>Sorry......</h1>
負載均衡配置:
upstream webservers {
server 192.168.18.201 weight=1 max_fails=2 fail_timeout=2;
server 192.168.18.202 weight=1 max_fails=2 fail_timeout=2;
server 127.0.0.1:8080 backup;
}
重新加載配置文件:
# service nginx reload
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
重新載入 nginx: [確定]
關(guān)閉 Web 服務(wù)器并進行測試:
# service nginx stop
停止 nginx: [確定]
進行測試:
# curl http://192.168.18.208
<h1>Sorry......</h1>
# curl http://192.168.18.208
<h1>Sorry......</h1>
# curl http://192.168.18.208
<h1>Sorry......</h1>
注,大家可以看到,當所有服務(wù)器都不能工作時,就會啟動備份服務(wù)器。好了,backup 服務(wù)器就配置到這里,下面我們來配置 ip_hash 負載均衡。
ip_hash:每個請求按訪問 IP 的 hash 結(jié)果分配,這樣來自同一個 IP 的訪客固定訪問一個后端服務(wù)器,有效解決了動態(tài)網(wǎng)頁存在的 session 共享問題,電子商務(wù)網(wǎng)站用的比較多。
# vim /etc/nginx/nginx.conf
upstream webservers {
ip_hash;
server 192.168.18.201 weight=1 max_fails=2 fail_timeout=2;
server 192.168.18.202 weight=1 max_fails=2 fail_timeout=2;
#server 127.0.0.1:8080 backup;
}
注,當負載調(diào)度算法為 ip_hash 時,后端服務(wù)器在負載均衡調(diào)度中的狀態(tài)不能有 backup。有人可能會問,為什么呢?大家想啊,如果負載均衡把你分配到 backup 服務(wù)器上,你能訪問到頁面嗎?不能,所以了不能配置 backup 服務(wù)器。
重新加載一下服務(wù)器:
# service nginx reload
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
重新載入 nginx: [確定]
測試一下:
# curl http://192.168.18.208
web2.test.com
# curl http://192.168.18.208
web2.test.com
# curl http://192.168.18.208
web2.test.com
注,大家可以看到,你不斷的刷新頁面一直會顯示 Web2,說明 ip_hash 負載均衡配置成功。