nginx是一款非常優(yōu)秀的反向代理工具,支持請(qǐng)求分發(fā),負(fù)載均衡,以及緩存等等非常實(shí)用的功能。在請(qǐng)求處理上,nginx采用的是epoll模型,這是一種基于事件監(jiān)聽(tīng)的模型,因而其具備非常高效的請(qǐng)求處理效率,單機(jī)并發(fā)能力能夠達(dá)到上百萬(wàn)。nginx接收到的請(qǐng)求可以通過(guò)負(fù)載均衡策略分發(fā)到其下一級(jí)的應(yīng)用服務(wù)器,這些服務(wù)器一般是以集群方式部署的,因而在性能不足的情況下,應(yīng)用服務(wù)器可以通過(guò)加機(jī)器的方式擴(kuò)展流量。此時(shí),對(duì)于一些特大型的網(wǎng)站,性能的瓶頸就來(lái)自于nginx了,因?yàn)閱螜C(jī)的nginx的并發(fā)能力是有上限的,而nginx本身是不支持集群模式的,因而此時(shí)對(duì)nginx的橫向擴(kuò)展就顯得尤為重要。
keepalived是一款服務(wù)器狀態(tài)檢測(cè)和故障切換的工具。在其配置文件中,可以配置主備服務(wù)器和該服務(wù)器的狀態(tài)檢測(cè)請(qǐng)求。也就是說(shuō)keepalived可以根據(jù)配置的請(qǐng)求,在提供服務(wù)期間不斷向指定服務(wù)器發(fā)送請(qǐng)求,如果該請(qǐng)求返回的狀態(tài)碼是200,則表示該服務(wù)器狀態(tài)是正常的,如果不正常,那么keepalived就會(huì)將該服務(wù)器給下線(xiàn)掉,然后將備用服務(wù)器設(shè)置為上線(xiàn)狀態(tài)。
lvs是一款用于四層負(fù)載均衡的工具。所謂的四層負(fù)載均衡,對(duì)應(yīng)的是網(wǎng)絡(luò)七層協(xié)議,常見(jiàn)的如HTTP協(xié)議是建立在七層協(xié)議上的,而lvs作用于四層協(xié)議上,也即:傳輸層,網(wǎng)絡(luò)層,數(shù)據(jù)鏈路層和物理層。這里的傳輸層主要協(xié)議有TCP和UDP協(xié)議,也就是說(shuō)lvs主要支持的方式是TCP和UDP。也正是因?yàn)閘vs是處于四層負(fù)載均衡上的,因而其處理請(qǐng)求的能力比常見(jiàn)的服務(wù)器要高非常多,比如nginx的請(qǐng)求處理就是建立在網(wǎng)絡(luò)七層上的,lvs的負(fù)載均衡能力是nginx的十倍以上。
通過(guò)上面的介紹,我們可以發(fā)現(xiàn),在特大型網(wǎng)站中,應(yīng)用服務(wù)器是可以橫向擴(kuò)容的,而nginx是不支持橫向擴(kuò)容的,此時(shí)nginx就會(huì)成為性能瓶頸。而lvs是一款負(fù)載均衡工具,因而如果我們結(jié)合lvs和nginx,那么就可以通過(guò)部署多臺(tái)nginx服務(wù)器,通過(guò)lvs的負(fù)載均衡能力,將請(qǐng)求均衡的分發(fā)到各個(gè)nginx服務(wù)器上,再由nginx服務(wù)器分發(fā)到各個(gè)應(yīng)用服務(wù)器,這樣,我們就實(shí)現(xiàn)了nginx的橫向擴(kuò)展了。由于nginx本質(zhì)上也是一款應(yīng)用服務(wù)器,因而其也有可能宕機(jī),因而這里結(jié)合keepalived就可以實(shí)現(xiàn)nginx的故障檢測(cè)和服務(wù)切換。也就是說(shuō),通過(guò)keepalived+lvs+nginx,我們實(shí)現(xiàn)了nginx的高可用集群模式。
在上面的介紹中,我們會(huì)注意到,雖然keepalived+lvs+nginx實(shí)現(xiàn)了nginx的集群模式,但是在我們使用nginx的時(shí)候,其本身是有一個(gè)ip和端口的,默認(rèn)監(jiān)聽(tīng)的端口是80和443,那么lvs是如何實(shí)現(xiàn)將請(qǐng)求分發(fā)給具有不同ip和端口的nginx服務(wù)器的呢?這里就是通過(guò)虛擬ip實(shí)現(xiàn)的,所謂虛擬ip就是對(duì)外提供一個(gè)公共的ip,外部客戶(hù)端請(qǐng)求的都是這個(gè)ip,lvs在接收到虛擬ip的請(qǐng)求之后,通過(guò)配置的調(diào)度器和負(fù)載均衡策略,選擇一個(gè)目標(biāo)nginx服務(wù)器,然后將請(qǐng)求轉(zhuǎn)發(fā)給該服務(wù)器。這里lvs有兩個(gè)概念,就是調(diào)度器和負(fù)載均衡策略,所謂的調(diào)度器指的是lvs將會(huì)以何種方式處理請(qǐng)求和響應(yīng)數(shù)據(jù),其主要有三種調(diào)度器:
Virtual Server via Network Address Translation(VS/NAT):這種方式的主要原理是,用戶(hù)發(fā)送請(qǐng)求到虛擬ip上后,lvs會(huì)根據(jù)負(fù)載均衡算法選擇一個(gè)目標(biāo)處理服務(wù),然后將請(qǐng)求報(bào)文中的目標(biāo)ip地址修改為計(jì)算得到的目標(biāo)服務(wù)器,并且發(fā)送給該服務(wù)器。對(duì)于響應(yīng)的報(bào)文,調(diào)度器會(huì)將目標(biāo)服務(wù)器返回的響應(yīng)數(shù)據(jù)中的源地址修改為虛擬ip地址。通過(guò)這種方式,對(duì)客戶(hù)端而言,其形式上面向的是一臺(tái)服務(wù)器。不過(guò)這種方式的缺點(diǎn)在于,所有的響應(yīng)數(shù)據(jù)都需要通過(guò)調(diào)度器,如果請(qǐng)求量比較大的情況下,那么調(diào)度器就會(huì)成為整個(gè)系統(tǒng)的瓶頸。
Virtual Server via IP Tunneling(VS/TUN):這種方式主要解決的就是VS/NAT中,響應(yīng)數(shù)據(jù)會(huì)經(jīng)過(guò)調(diào)度器的問(wèn)題。同VS/NAT一樣 ,調(diào)度器還是會(huì)接收請(qǐng)求的數(shù)據(jù),并且將報(bào)文中的目標(biāo)ip修改為目標(biāo)服務(wù)的ip,但是在目標(biāo)服務(wù)處理完數(shù)據(jù)之后,其會(huì)直接將響應(yīng)報(bào)文中的源ip修改為虛擬ip,然后將請(qǐng)求發(fā)送給客戶(hù)端。通過(guò)這種方式,響應(yīng)數(shù)據(jù)就由各個(gè)目標(biāo)服務(wù)進(jìn)行了處理,而無(wú)需通過(guò)調(diào)度器進(jìn)行返回,這種方式會(huì)大大提高系統(tǒng)的吞吐量,而且由于一般請(qǐng)求報(bào)文比響應(yīng)報(bào)文小很多,調(diào)度器也只需要處理請(qǐng)求報(bào)文,那么系統(tǒng)的整體負(fù)載將會(huì)被均攤到各個(gè)服務(wù)器上。
Virtual Server via Direct Routing(VS/DR):這種方式相對(duì)于VS/TUN,其主要區(qū)別在于,VS/NAT是將請(qǐng)求報(bào)文中的ip地址修改為目標(biāo)服務(wù)的ip地址,而VS/DR則是直接將請(qǐng)求報(bào)文中的MAC地址修改為目標(biāo)地址,這種方式效率會(huì)更高,因?yàn)閂S/TUN中的ip地址最終還是需要轉(zhuǎn)換為MAC地址來(lái)發(fā)送數(shù)據(jù)的。
1. 環(huán)境準(zhǔn)備
VMware;
4臺(tái)CentOs7虛擬主機(jī):172.16.28.130,172.16.28.131,172.16.28.132,172.16.28.133
系統(tǒng)服務(wù):LVS,Keepalived
Web服務(wù)器:nginx
集群搭建:LVSDR模式
2. 軟件安裝
在四臺(tái)虛擬機(jī)上,我們以如下方式搭建集群:
172.16.28.130lvs+keepalived
172.16.28.131lvs+keepalived
172.16.28.132nginx
172.16.28.133nginx
這里我們使用172.16.28.130 和172.16.28.131 兩臺(tái)機(jī)器作為lvs+keepalived 的工作機(jī)器,也就是說(shuō)這兩臺(tái)機(jī)器的作用主要是進(jìn)行負(fù)載均衡和故障檢測(cè)和下線(xiàn)的;我們使用172.16.28.132和172.16.28.133 兩臺(tái)機(jī)器作為應(yīng)用服務(wù)器,主要是對(duì)外提供服務(wù)的。這四臺(tái)服務(wù)器作為整個(gè)后端集群服務(wù),并且對(duì)外提供的虛擬ip是172.16.28.120 。需要說(shuō)明的是,這里的keepalived 所檢測(cè)的服務(wù)是兩臺(tái)lvs 服務(wù)器,這兩臺(tái)服務(wù)器,一臺(tái)作為master服務(wù)器,一臺(tái)作為backup服務(wù)器,兩者在負(fù)載均衡的配置上是完全一樣的。在正常情況下,客戶(hù)端請(qǐng)求虛擬ip的時(shí)候,lvs 會(huì)將該請(qǐng)求轉(zhuǎn)發(fā)到master服務(wù)器上,然后master服務(wù)器根據(jù)配置的負(fù)載均衡策略選擇一臺(tái)應(yīng)用服務(wù)器,并且將請(qǐng)求發(fā)送給該應(yīng)用服務(wù)器進(jìn)行處理。如果在某個(gè)時(shí)刻,lvs的master服務(wù)器由于故障宕機(jī)了,keepalived就會(huì)檢測(cè)到該故障,并且進(jìn)行故障下線(xiàn),然后將backup機(jī)器上線(xiàn)用于提供服務(wù),從而實(shí)現(xiàn)故障轉(zhuǎn)移的功能。
2.1 lvs+keepalived安裝
在172.16.28.130 和172.16.28.131 上安裝ipvs和keepalived:
#安裝ipvs
sudoyuminstallipvsadm
#安裝keepalived
sudoyuminstallkeepalived
在172.16.28.132 和172.16.28.133 上安裝nginx:
#安裝nginx
sudoyuminstallnginx
需要注意的是,在兩臺(tái)nginx服務(wù)器上需要將防火墻關(guān)閉,否則lvs+keepalived的兩臺(tái)機(jī)器就無(wú)法將請(qǐng)求發(fā)送到兩臺(tái)nginx服務(wù)器上來(lái):
#關(guān)閉防火墻
systemctldisablefirewalld.service
查看兩臺(tái)負(fù)載均衡機(jī)器是否支持lvs:
sudolsmod|grepip_vs
#如果看到如下結(jié)果,則說(shuō)明是支持的
[zhangxufeng@localhost~]$sudolsmod|grepip_vs
ip_vs1454970
nf_conntrack1372391ip_vs
libcrc32c126443xfs,ip_vs,nf_conntrack
如果上述命令沒(méi)有任何結(jié)果,則執(zhí)行sudo ipvsadm 命令啟動(dòng)ipvs之后,再通過(guò)上述命令進(jìn)行查看即可。啟動(dòng)ipvs之后,我們就可以在/etc/keepalived/ 目錄下編輯keepalived.conf 文件,我們以172.16.28.130 機(jī)器作為master機(jī)器,master節(jié)點(diǎn)配置如下:
#GlobalConfiguration
global_defs{
lvs_iddirector1#指定lvs的id
}
#VRRPConfiguration
vrrp_instanceLVS{
stateMASTER#指定當(dāng)前節(jié)點(diǎn)為master節(jié)點(diǎn)
interfaceens33#這里的ens33是網(wǎng)卡的名稱(chēng),通過(guò)ifconfig或者ipaddr可以查看
virtual_router_id51#這里指定的是虛擬路由id,master節(jié)點(diǎn)和backup節(jié)點(diǎn)需要指定一樣的
priority151#指定了當(dāng)前節(jié)點(diǎn)的優(yōu)先級(jí),數(shù)值越大優(yōu)先級(jí)越高,master節(jié)點(diǎn)要高于backup節(jié)點(diǎn)
advert_int1#指定發(fā)送VRRP通告的間隔,單位是秒
authentication{
auth_typePASS#鑒權(quán),默認(rèn)通過(guò)
auth_pass123456#鑒權(quán)訪問(wèn)密碼
}
virtual_ipaddress{
172.16.28.120#指定了虛擬ip
}
}
#VirtualServerConfiguration-forwwwserver
#后臺(tái)真實(shí)主機(jī)的配置
virtual_server172.16.28.12080{
delay_loop1#健康檢查的時(shí)間間隔
lb_algorr#負(fù)載均衡策略,這里是輪詢(xún)
lb_kindDR#調(diào)度器類(lèi)型,這里是DR
persistence_time1#指定了持續(xù)將請(qǐng)求打到同一臺(tái)真實(shí)主機(jī)的時(shí)間長(zhǎng)度
protocolTCP#指定了訪問(wèn)后臺(tái)真實(shí)主機(jī)的協(xié)議類(lèi)型
#RealServer1configuration
#指定了真實(shí)主機(jī)1的ip和端口
real_server172.16.28.13280{
weight1#指定了當(dāng)前主機(jī)的權(quán)重
TCP_CHECK{
connection_timeout10#指定了進(jìn)行心跳檢查的超時(shí)時(shí)間
nb_get_retry3#指定了心跳超時(shí)之后的重復(fù)次數(shù)
delay_before_retry3#指定了在嘗試之前延遲多長(zhǎng)時(shí)間
}
}
#RealServer2Configuration
real_server172.16.28.13380{
weight1#指定了當(dāng)前主機(jī)的權(quán)重
TCP_CHECK{
connection_timeout10#指定了進(jìn)行心跳檢查的超時(shí)時(shí)間
nb_get_retry3#指定了心跳超時(shí)之后的重復(fù)次數(shù)
delay_before_retry3#指定了在嘗試之前延遲多長(zhǎng)時(shí)間
}
}
}
上面是master節(jié)點(diǎn)上keepalived的配置,對(duì)于backup節(jié)點(diǎn),其配置與master幾乎是一致的,只是其state和priority參數(shù)不同。如下是backup節(jié)點(diǎn)的完整配置:
#GlobalConfiguration
global_defs{
lvs_iddirector2#指定lvs的id
}
#VRRPConfiguration
vrrp_instanceLVS{
stateBACKUP#指定當(dāng)前節(jié)點(diǎn)為master節(jié)點(diǎn)
interfaceens33#這里的ens33是網(wǎng)卡的名稱(chēng),通過(guò)ifconfig或者ipaddr可以查看
virtual_router_id51#這里指定的是虛擬路由id,master節(jié)點(diǎn)和backup節(jié)點(diǎn)需要指定一樣的
priority150#指定了當(dāng)前節(jié)點(diǎn)的優(yōu)先級(jí),數(shù)值越大優(yōu)先級(jí)越高,master節(jié)點(diǎn)要高于backup節(jié)點(diǎn)
advert_int1#指定發(fā)送VRRP通告的間隔,單位是秒
authentication{
auth_typePASS#鑒權(quán),默認(rèn)通過(guò)
auth_pass123456#鑒權(quán)訪問(wèn)密碼
}
virtual_ipaddress{
172.16.28.120#指定了虛擬ip
}
}
#VirtualServerConfiguration-forwwwserver
#后臺(tái)真實(shí)主機(jī)的配置
virtual_server172.16.28.12080{
delay_loop1#健康檢查的時(shí)間間隔
lb_algorr#負(fù)載均衡策略,這里是輪詢(xún)
lb_kindDR#調(diào)度器類(lèi)型,這里是DR
persistence_time1#指定了持續(xù)將請(qǐng)求打到同一臺(tái)真實(shí)主機(jī)的時(shí)間長(zhǎng)度
protocolTCP#指定了訪問(wèn)后臺(tái)真實(shí)主機(jī)的協(xié)議類(lèi)型
#RealServer1configuration
#指定了真實(shí)主機(jī)1的ip和端口
real_server172.16.28.13280{
weight1#指定了當(dāng)前主機(jī)的權(quán)重
TCP_CHECK{
connection_timeout10#指定了進(jìn)行心跳檢查的超時(shí)時(shí)間
nb_get_retry3#指定了心跳超時(shí)之后的重復(fù)次數(shù)
delay_before_retry3#指定了在嘗試之前延遲多長(zhǎng)時(shí)間
}
}
#RealServer2Configuration
real_server172.16.28.13380{
weight1#指定了當(dāng)前主機(jī)的權(quán)重
TCP_CHECK{
connection_timeout10#指定了進(jìn)行心跳檢查的超時(shí)時(shí)間
nb_get_retry3#指定了心跳超時(shí)之后的重復(fù)次數(shù)
delay_before_retry3#指定了在嘗試之前延遲多長(zhǎng)時(shí)間
}
}
}
將master和backup配置成完全一樣的原因是,在master宕機(jī)時(shí),可以根據(jù)backup的配置進(jìn)行服務(wù)的無(wú)縫切換。
在lvs+keepalived機(jī)器配置完成之后,我們下面配置兩臺(tái)應(yīng)用服務(wù)器的nginx配置。這里我們是將nginx作為應(yīng)用服務(wù)器,在其配置文件中配置返回狀態(tài)碼為200,并且會(huì)將當(dāng)前主機(jī)的ip返回,如下是其配置:
worker_processesauto;
#pid/run/nginx.pid;
events{
worker_connections786;
}
http{
server{
listen80;
#這里是直接返回200狀態(tài)碼和一段文本
location/{
default_typetext/html;
return200"Hello,[email protected] ";
}
}
}
worker_processesauto;
#pid/run/nginx.pid;
events{
worker_connections786;
}
http{
server{
listen80;
#這里是直接返回200狀態(tài)碼和一段文本
location/{
default_typetext/html;
return200"Hello,[email protected] ";
}
}
}
可以看到,兩臺(tái)機(jī)器返回的文本中主機(jī)ip是不一樣的。nginx配置完成后,可以通過(guò)如下命令進(jìn)行啟動(dòng):
sudonginx
在啟動(dòng)nginx之后,我們需要配置虛擬ip,這是因?yàn)槲覀兪褂玫膌vs調(diào)度器是DR模式,前面我們講到過(guò),這種模式下,對(duì)客戶(hù)端的響應(yīng)是真實(shí)服務(wù)器直接返回給客戶(hù)端的,而真實(shí)服務(wù)器需要將響應(yīng)報(bào)文中的源ip修改為虛擬ip,這里配置的虛擬ip就是起這個(gè)作用的。我們編輯/etc/init.d/lvsrs 文件,寫(xiě)入如下內(nèi)容:
#!/bin/bash
ifconfiglo:0172.16.28.120netmask255.255.255.255broadcast172.16.28.120up
routeadd-host172.16.28.120devlo:0
echo"0">/proc/sys/net/ipv4/ip_forward
echo"1">/proc/sys/net/ipv4/conf/lo/arp_ignore
echo"2">/proc/sys/net/ipv4/conf/lo/arp_announce
echo"1">/proc/sys/net/ipv4/conf/all/arp_ignore
echo"2">/proc/sys/net/ipv4/conf/all/arp_announce
exit0
lo:表示當(dāng)前主機(jī)真實(shí)網(wǎng)卡的名稱(chēng);
172.16.28.120:表示虛擬ip;
編寫(xiě)完成后運(yùn)行該腳本文件即可。然后將兩臺(tái)lvs+keepalived機(jī)器上的keepalived服務(wù)啟動(dòng)起來(lái)即可:
sudoservicekeepalivedstart
最后可以通過(guò)如下命令查看配置的lvs+keepalived的策略:
[zhangxufeng@localhostkeepalived]$sudoipvsadm-ln
IPVirtualServerversion1.2.1(size=4096)
ProtLocalAddress:PortSchedulerFlags
->RemoteAddress:PortForwardWeightActiveConnInActConn
TCP172.16.28.120:80rr
->172.16.28.132:80Route100
2.2 集群測(cè)試
根據(jù)上述步驟,我們配置完成了一個(gè)lvs+keepalived+nginx的集群。在瀏覽器中,我們可以訪問(wèn)http://172.16.28.120 即可看到如下響應(yīng):
Hello,[email protected]
多次刷新瀏覽器之后,可以看到瀏覽器中顯示的文本切換如下,這是因?yàn)閘vs的負(fù)載均衡策略產(chǎn)生的:
Hello,[email protected]
3. 小結(jié)
本文首先對(duì)lvs和keepalived的工作原理進(jìn)行了講解,分別介紹了其工作的幾種模式,然后對(duì)lvs+keepalived+nginx搭建nginx集群的方式進(jìn)行詳細(xì)講解,并且說(shuō)明了其中所需要注意的問(wèn)題。