負載均衡的介紹
負載均衡是由多台伺服器以對稱方式組成伺服器叢集,每台伺服器都具等價關系,均可單獨對外提供服務且無需其他伺服器輔助。通過對應負載分擔均衡,将外部發送請求按既定規則分發到對稱叢集架構其中一台伺服器上,對應接收請求伺服器也獨立地回應用戶端請求。均衡負載能夠平均配置設定客戶請求到伺服器陣列,以快速擷取資料,解決大并發通路服務的洪峰問題。此種叢集技術可用最少的投入獲得超高的性能,是一種成本效益較高的并發解決方案之一。
負載均衡建立在網絡層之上,提供了一種廉價有效透明的方法擴充網絡裝置和伺服器帶寬、增加吞吐量、加強網絡資料處理能力、提高網絡的靈活性和可用性。
負載均衡(LoadBalance)其原意就是前端請求分攤到多個操作單元進行取數執行操作,例如Web伺服器、FTP伺服器、企業關鍵應用伺服器和其它關鍵任務伺服器等,進而共同完成工作任務。
常用負載均衡方法 一、使用者手動選擇
這是一種比較古老的方式,目主要通過提供不同的線路、不同伺服器連結的方式,來實作負載均衡。
這種方式在一些提供下載下傳、線上影院、直播等網站比較常見。
優點:
- 1、部署簡單,新增伺服器或鍊路隻需增加對應的入口即可
- 2、維護友善,如果有伺服器當機隻需關閉對應入口即可
缺點:
- 1、智能化程度不高,需使用者手動切換
- 2、配置設定不可控,容易出現伺服器通路量極不平衡等情況
二、DNS輪詢
大多域名注冊商都支援多條A記錄的解析,這就是DNS輪詢,DNS伺服器将解析請求按照A記錄的順序,逐一配置設定到不同的IP上,這樣就完成了簡單的負載均衡。
優點:
- 1、基本上無成本,因為往往域名注冊商的這種解析都是免費的;
- 2、部署友善,除了網絡拓撲的簡單擴增,新增的Web伺服器隻要增加一個公網IP即可。
缺點:
- 1、健康檢查,如果某台伺服器當機,DNS伺服器是無法知曉的,仍舊會将通路配置設定到此伺服器。修改DNS記錄全部生效起碼要3-4小時,甚至更久;
- 2、配置設定不均,如果幾台Web伺服器之間的配置不同,能夠承受的壓力也就不同,但是DNS解析配置設定的通路卻是均勻配置設定的。其實DNS也是有配置設定算法的,可以根據目前連接配接較少的配置設定、可以設定Rate權重配置設定等等,隻是目前絕大多數的DNS伺服器都不支援;
三、四/七層負載均衡
現代負載均衡技術通常操作于OSI網絡模型的第四層或第七層。第四層負載均衡将一個Internet上合法注冊的IP位址映射為多個内部伺服器的IP位址,對每次TCP連接配接請求動态使用其中一個内部IP第,達到負載均衡的目的。在第四層交換機中,此中均衡技術得到廣泛的應用,一個目标位址是伺服器群VIP連接配接請求的資料包流經交換機,交換機根據源端和目的IP位址、TCP或者UDP端口号和一定的負載政策,在伺服器IP和VIP間進行映射,選取伺服器群衆最好的伺服器來處理連接配接請求。
第七層負載均衡控制應用層服務的内容,提供一種對通路流量的高層控制方式,适合對HTTP伺服器群的應用。第七層負載均衡技術通過檢查流經的HTTP報頭,根據報頭内的資訊來執行負載均衡任務。
常見四/七層負載均衡裝置
- 硬體負載均衡交換機,代表有F5、array等。
- 軟體負載均衡器,Nginx/LVS/HAProxy是目前使用最廣泛的三種負載均衡軟體。
軟體四/七層負載均衡
1.軟體四層負載均衡
代表作為LVS,LVS是一個開源的軟體,可以實作linux平台下的簡單負載均衡。lvs叢集采用IP負載均衡技術和基于内容請求分發技術。排程器具有很好的吞吐率,将請求均衡的轉移到不同的伺服器上執行,且排程器自動屏蔽掉伺服器的故障,進而将一組伺服器構成一個高性能的、高可用的虛拟伺服器。整個伺服器叢集的結構對客戶是透明的,而且無需修改用戶端和伺服器端的程式。
LVS通過修改資料包Ip位址,Mac位址實作負載均衡。
LVS由ipvs(核心中),ipvsadm(使用者态)組成。LVS需要了解tcp,ip頭部。
當tcp握手信号,SYN資料包達到時,ipvs選擇一個後端伺服器,将資料包進行轉發。在此之後,所有包含相同的ip,tcp頭部的資料包都會被轉發到之前選擇的伺服器上。很明顯,ipvs無法感覺資料包内容。
2.軟體的七層負載均衡
大多HTTP反向代理方式,代表産品有nginx、haproxy等,nginx的反向代理負載均衡能夠很好的支援虛拟主機,可配置性很強,可以按輪詢、IP哈希、URL哈希、權重等多種放肆對後端伺服器做負載均衡,同時還支援後端伺服器的健康檢查。
nginx負載均衡工作在7層,它會與client、upstream分别建立tcp連接配接,nginx需要維護這兩個連接配接的狀态。
nginx的stream子產品可以用于4層負載均衡,主要用于tcp、udp的負載均衡。
nginx負載均衡算法 1.weight權重輪循
在輪循算法的基礎上加上權重,即為權重輪循算法,當使用該算法時,權重和使用者通路成正比,權重值越大,被轉發的請求也就越多。可以根據伺服器的配置和性能指定權重值大小,有效解決新舊伺服器性能不均帶來的請求配置設定問題。
upstream myapp1 {
server 172.1.1.103 weight=1;
server 172.1.1.104 weight=2;
}
2.ip_hash
每個請求按用戶端IP 的 hash結果配置設定,當新的請求到達時,先将其用戶端IP通過雜湊演算法哈希出一個值,在随後的用戶端請求中,客戶IP 的哈希值隻要相同,就會被配置設定至同一台伺服器,該排程算法可以解決動态網頁的session 共享問題,但有時會導緻請求配置設定不均,即無法保證1:1 的負載均衡,因為在國内大多數公司都是NAT 上網模式,多個用戶端會對應一個外部IP,是以,這些用戶端都會被配置設定到同一節點伺服器,進而導緻請求配置設定不均。LVS負載均衡的 -P參數、keepalived配置裡的persistence_timeout 50 參數都類似這個Nginx 裡的ip_hash 參數,其功能均為解決動态網頁的session 共享問題。注意:當負載排程算法為ip_hash時,後端伺服器在負載均衡排程中的狀态不能有weight 和backup ,即使有也不會生效。
upstream myapp1 {
ip_hash;
server 172.1.1.103;
server 172.1.1.104;
}
3.輪詢
按用戶端請求順序把用戶端的請求逐一配置設定到不同的後端節點伺服器,如果後端節點伺服器當機(預設情況下nginx隻檢測80端口)。當機的伺服器會自動從節點伺服器池中剔除,以便用戶端的使用者通路不受影響。新的請求會配置設定給正産的伺服器。
upstream myapp1 {
server 172.1.1.103;
server 172.1.1.104;
}
4.fair
排程算法會根據後端節點伺服器的響應時間來配置設定請求,響應時間短的優先配置設定。這是更加智能的排程算法。此種算法可以依據頁面大小和加載時間長短智能地進行負載均衡,也就是根據後端伺服器的響應時間來配置設定請求,響應時間短的優先配置設定。Nginx本身是不支援 fair排程算法的,如果需要使用這種排程算法,必須下載下傳Nginx 的相關子產品upstream_fair。
upstream myapp1 {
fair;
server 172.1.1.103;
server 172.1.1.104;
}
5.url_hash
按通路URL 的 hash結果來配置設定請求,使每個URL定向到同一個後端伺服器,可以進一步提高後端緩存伺服器的效率命中率。(多用于後端伺服器為緩存時的場景下)Nginx本身是不支援rul_hash的,如果需要使用這種排程算法,必須安裝Nginx 的hash子產品軟體包。
upstream myapp1 {
server 172.1.1.103;
server 172.1.1.104;
hash $request_uri;
hash_method crc32;
}
6.Nginx負載均衡排程狀态
在Nginxupstream子產品中,可以設定每台後端伺服器在負載均衡排程中的狀态,常用的狀态有:
- 1、down,表示目前的server暫時不參與負載均衡
- 2、backup,預留的備份機器。當其他所有的非backup機器出現故障或者忙的時候,才會請求backup機器,是以這台機器的通路壓力最低
- 3、max_fails,允許請求失敗的次數,預設為1,當超過最大次數時,傳回proxy_next_upstream子產品定義的錯誤。
- 4、fail_timeout,請求失敗逾時時間,在經曆了max_fails次失敗後,暫停服務的時間。max_fails和fail_timeout可以一起使用。
nginx負載均衡運用場景 1.HTTP負載均衡
upstream子產品控制HTTP的負載均衡。這個子產品定義了一個目的池,這個目的池可以用IP位址和DNS記錄,或者混合使用。
upstream子產品子產品還定義了任何單個請求是如何配置設定給任何上遊伺服器。
在下邊的例子中,srv1不參與負載,srv2隻有在其他伺服器當機或忙時才參與負載,srv3、srv4參與負載,其中每六次srv3通路五次,srv4一次。所有的請求被代理到服務組node,然後nginx負載均衡的分發請求。
nginx反向代理實作包括下面這些負載均衡HTTP、HTTPS、FastCGI、uwsgi,SCGI和memcached。
要配置HTTPS的負載均衡,隻需使用“https”開頭的協定。
當要設定FastCGI,uwsgi,SCGI,或者memcached的負載平衡,分别使用fastcgi_pass,uwsgi_pass,scgi_pass和memcached_pass指令。
upstream node {
server 192.9.191.31:8001 down;
server 192.9.191.31:8002 backup;
server www.aa.com:8003 weight=5;
server 192.9.191.31:8004 max_fail=1 fail_timeout=10s;
}
server{
listen 80;
server_name www.test.com test.com;
location / {
proxy_pass http://node;
}
}
2.TCP、UDP負載均衡
Nginx使用了一個新的stream子產品來實作TCP負載均衡,這個子產品,類似于http和mail子產品,允許我們配置一組監聽TCP連接配接的服務。允許你配置多個服務的TCP連接配接,通過在upstream的server組中配置proxy_pass指令。
TCP負載均衡支援Nginx原有的排程算法,包括輪詢排程,哈希(選擇一緻)等。同時,排程資訊資料也會和健壯性檢測子產品一起協作,為每個連接配接選擇适當的目标上遊伺服器。
和其他upstream子產品一樣,TCP的stream子產品也支援自定義負載均和的轉發權重(配置weight),還有backup和down的參數,用于踢掉失效的上遊伺服器。max_conns參數可以限制一台伺服器的TCP連接配接數量,根據伺服器的容量來設定恰當的配置數值,尤其在高并發的場景下,可以達到過載保護的目的。
stream{
upstream mysql_read {
server read1.example.com:3306 weight=5;
server read2.example.com:3306;
server 10.10.12.34:3306 backup;
}
server {
listen 3306;
proxy_pass mysql_read;
}
}
案例分享 案例一
後端3台tomcat伺服器以2主一備的形式通過2台nginx伺服器實作負載均衡,同時nginx通過keepalived實作主備配置
1、位址配置設定
nginx:172.1.1.106、172.1.1.107
VIP位址:172.1.1.108
tomcatIP:172.1.1.102、172.1.1.103、172.1.1.105
2、應用部署及配置
-
環境配置及tomcat安裝:
安裝java環境:
chmod +x jdk-6u16-linux-i586.bin
./jdk-6u16-linux-i586.bin
ln -s /usr/local/jdk-1.6.0-16/bin/java /usr/bin/java
ln -s /usr/local/jdk-1.6.0-16/bin/javac /usr/bin/javac
ln -s /usr/local/jdk-1.6.0-16 /usr/local/jdk
ln -s /usr/local/jdk-1.6.0-16/jre /usr/local/jre
tar zxvf apache-tomcat-6.0.20.tar.gz
mv apache-tomcat-6.0.20 /usr/local/tomcat
設定環境變量:
JAVA_HOME=/usr/local/jdk
export JAVA_HOME
JRE_HOME=/usr/local/jre
export JRE_HOME
CLASSPATH=/usr/local/tomcat/common/lib/:/usr/local/jdk/lib:/usr/local/jre/lib
export CLASSPATH
PATH=$PATH:/usr/local/tomcat/bin/:/usr/local/apache/bin:/usr/local/jdk/bin:/usr/local/jre/bin
export PATH
TOMCAT_HOME=/usr/local/tomcat
export TOMCAT_HOME
-
nginx安裝及配置
下載下傳及安裝nginx:
wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-7.7.tar.gz
tar zxvf pcre-7.7.tar.gz
cd pcre-7.7/
./configure
make && make install
wget http://sysoev.ru/nginx/nginx-0.7.17.tar.gz
tar zxvf nginx-0.7.17.tar.gz
cd nginx-0.7.17/
./configure --prefix=/usr/local/nginx
make && make install
nginx.conf配置檔案,兩台nginx伺服器保持一緻
user nobody nobody;
worker_processes 1;
pid /usr/local/nginx/logs/nginx.pid;
worker_rlimit_nofile 51200;
events
{
use epoll;
worker_connections 51200;
}
http{
include mime.types;
default_type application/octet-stream;
server_names_hash_bucket_size 128;
client_header_buffer_size 32k;
large_client_header_buffers 4 32k;
client_max_body_size 8m;
sendfile on;
tcp_nopush on;
keepalive_timeout 60;
tcp_nodelay on;
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 128k;
gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_http_version 1.0;
gzip_comp_level 2;
gzip_types text/plain application/x-javascript text/css application/xml;
gzip_vary on;
upstream node
{
server 172.1.1.102:8080;
server 172.1.1.103:8080;
server 172.1.1.105:8080 backup;
}
server {
listen 80;
server_name test.com;
location / {
root /var/www ;
index index.jsp index.htm index.html;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://node;
}
log_format access '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" $http_x_forwarded_for';
access_log /var/log/access.log access;
}
}
-
Nginx伺服器雙機部署
Keepalived下載下傳安裝:
wget http://www.keepalived.org/software/keepalived-1.1.15.tar.gz
http://www.keepalived.org/software/keepalived-1.2.13.tar.gz
tar zxvf keepalived-1.1.15.tar.gz
cd keepalived-1.1.15
./configure
make
make install
cp /usr/local/etc/rc.d/init.d/keepalived /etc/rc.d/init.d/
cp /usr/local/etc/sysconfig/keepalived /etc/sysconfig/
mkdir /etc/keepalived
cp /usr/local/etc/keepalived/keepalived.conf /etc/keepalived/
cp /usr/local/sbin/keepalived /usr/sbin/
service keepalived start|stop
兩台nginx伺服器上keepalived配置檔案
172.1.1.106主機:
ip avrrp_instance VI_INET1 {
state MASTER
interface eth0
virtual_router_id 53
priority 200
advert_int 1
authentication {
auth_type pass
auth_pass yourpass
}
virtual_ipaddress {
172.1.1.108
}
}
172.1.1.107主機:
vrrp_instance VI_INET1 {
state BACKUP
interface eth0
virtual_router_id 53
priority 100
advert_int 1
authentication {
auth_type pass
auth_pass yourpass
}
virtual_ipaddress {
172.1.1.108
}
}
以上步驟即可完成nginx主備下的負載均衡配置,具體負載政策大家可以根據現場環境實際情況進行調整,配置僅供參考。
案例二
在流量陡增的網際網路面前,接口限流也是很有必要的,尤其是針對高并發的場景。Nginx的限流主要是兩種方式:限制通路頻率和限制并發連接配接數。該案例就是一個通過限制單個IP并發連接配接數防止後端伺服器過載的例子。
- 維護人員接到告警發現tuxedo中間件多個服務出現堵塞,嘗試擴服務或重新開機均無法解決。
- 對比業務量情況,發現同比環比均超30%以上
- 随即調整nginx限流政策,配置及注釋如下
http {
include mime.types;
default_type application/octet-stream;
proxy_intercept_errors on;
#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;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
log_format acc "$remote_addr $remote_user [$time_local] $request_method $uri $args $server_protocol"
" $status $body_bytes_sent $request_time $http_referer $upstream_addr $upstream_cache_status"
" $upstream_status $http_x_forwarded_for $cookie_route $http_host $http_user_agent <> <> ";
access_log logs/access_acc$hostname$year$month$day.log acc ;
sendfile on;
tcp_nopush on;
keepalive_timeout 65;
client_header_timeout 60;
client_body_timeout 60;
reset_timedout_connection on;
send_timeout 60;
server_tokens off;
proxy_next_upstream error timeout;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $http_x_forwarded_for;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 65;
proxy_send_timeout 120;
proxy_read_timeout 120;
proxy_buffer_size 8k;
proxy_buffers 8 64k;
proxy_busy_buffers_size 128k;
proxy_temp_file_write_size 128k;
proxy_http_version 1.1;
limit_conn_zone $binary_remote_addr zone=one:10m;
##定義一個10M的名字為one的記憶體區域,用于記錄通路頻次;
upstream dt_cluster {
server 172.1.1.230:17001;
server 172.1.1.230:17002;
server 172.1.1.230:17003;
server 172.1.1.230:17004;
keepalive 32;
check interval=5000 rise=2 fall=3 timeout=10000;
}
lua_package_path "/usr/local/nginx/lua/lua-resty-redis/lib/?.lua;;";
#gzip on;
server {
listen 7001;
listen 7002;
listen 7003;
listen 7004;
#server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
set $resp_body "";
location /OpenEbus {
proxy_pass http://dt_cluster;
# include body_filter_by_lua.conf;
# lua_need_request_body on;
# body_filter_by_lua '
# local resp_body = string.sub(ngx.arg[1], 1, 1000)
# ngx.ctx.buffered = (ngx.ctx.buffered or "") .. resp_body
# if ngx.arg[2] then
# ngx.var.resp_body = ngx.ctx.buffered
# end
# ';
limit_conn one 250;
##限制并發連接配接最多250個;
}
location /hello {
default_type 'text/plain';
content_by_lua 'ngx.say("hello, lua")';
}
location /mockService {
proxy_pass http://dt_cluster;
}
location / {
return 403;
}
}
}
通過使用limit_conn_zone 和limit_conn 對某個目錄或指定字尾,比如.html或.jpg進行并發連接配接限制。有了連接配接數限制,相當于限制了用戶端浏覽器和Nginx之間的管道個數,浏覽器通過管道運輸請求,如同向自來水管中放水,水的流速和壓力對于管道另外一端是有影響的。為了防止不信任的用戶端通過這個管道瘋狂發送請求,消耗CPU記憶體等資源,以及防止URL不斷發出連接配接請求,必須對請求的速度進行限制,如同對水流速度限制一樣。