使用Nginx、Keepalived構(gòu)建文藝負(fù)載均衡
原創(chuàng)【51CTO獨(dú)家特稿】面對網(wǎng)站服務(wù)器端負(fù)載增大的問題,是“拿15萬¥買一臺服務(wù)器”來解決,還是靠“加三倍服務(wù)器”來解決?還是用其它一些辦法?
對于一個訪問量日益增加的網(wǎng)站架構(gòu)而言,從單機(jī)到集群、從集群到分布式,架構(gòu)演化是必然的。
接手環(huán)境,分析瓶頸,擴(kuò)展架構(gòu)
筆者現(xiàn)在的環(huán)境在剛接手時算是單機(jī)LAMP環(huán)境。在單機(jī)LAMP環(huán)境時,由于訪問量逐漸變大,網(wǎng)站會經(jīng)常出現(xiàn)打不開的情況,為了解決這個問題在LAMP前端臨時加了一臺vanish來緩存一些靜態(tài)文件,從而減輕了web服務(wù)器的負(fù)載。再到后來為了滿足業(yè)務(wù)訪問需求,將架構(gòu)改為CDN+Nginx負(fù)載均衡(反向代理)+LNMP+代碼層緩存+MySQL主從,從而將網(wǎng)站整體負(fù)載性能提升15倍,且訪問速度也得到很大提升。
負(fù)載均衡為什么要選擇使用Nginx呢?
普通負(fù)載均衡用LVS,文藝負(fù)載均衡用Nginx/F5/HAproxy,XX負(fù)載均衡用NLB
LVS:四層負(fù)載均衡的典型代表,目前已經(jīng)被添加到linux發(fā)行版的內(nèi)核。LVS用于較為成熟,因此不再做類述,在此推薦一篇不錯的LVS文章:《互聯(lián)網(wǎng)運(yùn)營智慧》第六章負(fù)載均衡及服務(wù)器集群(LVS)。
Nginx/F5/HAproxy:均為七層負(fù)載均衡,F(xiàn)5為商業(yè)設(shè)備,功能強(qiáng)大,但價格不菲,所以在此不做討論;HAproxy為重量級的七層負(fù)載均衡/反向代理程序,一般應(yīng)用于大中型站點(diǎn);而Nginx雖然屬于輕量級產(chǎn)品,但是功能毫不遜色與HAproxy,如可以對靜態(tài)文件可以實(shí)現(xiàn)緩存、可以通過URL、目錄結(jié)構(gòu)、靜動分離對網(wǎng)站實(shí)現(xiàn)分流,還可以實(shí)現(xiàn)對后端服務(wù)器狀態(tài)碼健康檢測、對網(wǎng)絡(luò)依賴較小、對虛擬主機(jī)支持友好等等,這也是筆者選擇Nginx來做負(fù)載均衡的原因。
NLB:windows下的東東,性能、可操作性可想而知。在此也提醒一下各位同仁,針對HTTP類的應(yīng)用千萬不要選擇使用windows,如同樣的業(yè)務(wù)放linux上只需兩臺服務(wù)器,而放windows上可能會需要三臺甚至更多,運(yùn)維/硬件采購成本也會增加,同時license也是一筆不小的費(fèi)用。國內(nèi)較大的一些web站點(diǎn)后端架構(gòu)為windows的分別有京東商城、當(dāng)當(dāng)網(wǎng)、凡客誠品、麥包包。
使用Nginx構(gòu)建負(fù)載均衡時需要注意的幾個問題
Session同步:由于筆者所維護(hù)的架構(gòu)硬件預(yù)算受限,所以在整個架構(gòu)中沒有共享存儲,針對于session處理,筆者使用ip_hash來解決后端服務(wù)器session問題。另外,關(guān)于存儲session,推薦使用redis或memcached(感謝小衛(wèi)、小灰狼 兩位兄弟的建議)。
網(wǎng)站代碼存儲:還是由于沒有共享存儲,所以筆者每臺web服務(wù)器本地均存放一份代碼,為了保證多臺web服務(wù)器的代碼數(shù)據(jù)一致性,使用rsync+inotify實(shí)現(xiàn)動態(tài)同步(具體實(shí)現(xiàn)方法會在后面的文章中介紹)。倘若硬件條件允許的情況下,推薦使用NFS來存儲;若考慮到NFS無法滿足性能需求,可以將NFS的硬盤換成SSD或者使用分布式文件系統(tǒng)來解決。
負(fù)載均衡模式選擇:在不受session困擾的情況下,負(fù)載均衡模式可以使用weight,因?yàn)閕p_hash會有導(dǎo)致后端服務(wù)器負(fù)載不均的情況出現(xiàn)。
開始部署Nginx和Keepalived
為了避免負(fù)載均衡出現(xiàn)單點(diǎn)故障,所以使用keepalived對Nginx負(fù)載均衡做了HA,也就是說當(dāng)主負(fù)載均衡發(fā)生軟硬件故障時,負(fù)載均衡服務(wù)將有備用負(fù)載均衡服務(wù)器自動接管服務(wù),環(huán)境拓?fù)淙缦拢?/p>
Vip:192.168.1.100
Nginx-proxy-master:192.168.1.101
Nginx-proxy-backup:192.168.1.102
安裝Nginx與Keepalived
在Nginx-proxy-master和Nginx-proxy-backup上分別安裝Nginx、Keepalived,兩臺主機(jī)安裝步驟相同
安裝Nginx
#yum -y install pcre pcre-devel #useradd www -s /sbin/nologin #tar zxvf nginx-0.7.62.tar.gz #cd nginx-0.7.62 #./configure \ --prefix=/usr/local/nginx \ --user=www \ --group=www \ --with-http_stub_status_module \ --with-http_ssl_module #make && make install
安裝Keepalived
#tar zxvf keepalived-1.1.17.tar.gz #cd cd keepalived-1.1.17 #./configure --prefix=/usr/local/keepalived #make && make install #rm -rf /usr/local/keepalived/etc/keepalived/keepalived.conf #mkdir /etc/keepalived
配置Nginx
注:Nginx-proxy-master和Nginx-proxy-backup的Nginx配置相同
#more /usr/local/nginx/conf/nginx.conf
user www www;
worker_processes 4;
error_log logs/error.log crit;
pid 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 256;
client_header_buffer_size 256k;
large_client_header_buffers 4 256k;
keepalive_timeout 120;
client_max_body_size 50m;
client_body_buffer_size 256k;
server_tokens off;
gzip on;
gzip_min_length 1k;
gzip_buffers 4 1024k;
gzip_http_version 1.1;
gzip_comp_level 6;
gzip_types text/plain application/x-javascript text/css application/xml;
#gzip_vary on;
proxy_hide_header Vary;
proxy_connect_timeout 600;
proxy_read_timeout 600;
proxy_send_timeout 600;
proxy_buffer_size 16k;
proxy_buffers 4 64k;
proxy_busy_buffers_size 128k;
proxy_temp_file_write_size 128k;
sendfile on;
tcp_nodelay on;
# add_header Cache-Control no-cache;
upstream blog.luwenju.com {
ip_hash;
server 192.168.1.201:80;
server 192.168.1.202:80;
server 192.168.1.203:80;
}
server {
listen 80;
server_name blog.luwenju.com;
location / {
index index.php;
proxy_pass http://blog.luwenju.com;
proxy_set_header Host $host;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_504;
proxy_set_header X-Forwarded-For $remote_addr;
}
location /NginxStatus {
stub_status on;
allow 192.168.1.0/24;
}
log_format blog.luwenju.com '$remote_addr - $remote_user [$time_local] $upstream_addr $upstream_status $request'
'"$status" $body_bytes_sent "$http_referer"'
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /usr/local/nginx/logs/blog.luwenju.com_access.log blog.luwenju.com;
}
}
說明:upstream為服務(wù)器池。以本配置文件為例,upstream中共包含三臺web服務(wù)器,負(fù)載均衡方式為ip_hash。server為主機(jī),用于為upstream內(nèi)的三臺web服務(wù)器實(shí)現(xiàn)反向代理,從而到達(dá)負(fù)載均衡的目的。在本配置文件中只設(shè)置了一個主機(jī)(server),如果要實(shí)現(xiàn)虛擬主機(jī),將一個server分別對應(yīng)一個upstream即可。
另外,還有兩個關(guān)于日志設(shè)置的問題:
負(fù)載均衡上是否需要開啟access_log:系統(tǒng)/程序剛上線時需要開啟,用于Nginx調(diào)試,后期運(yùn)行穩(wěn)定后建議將日志打印關(guān)閉,因?yàn)閷τ谠L問量較大的網(wǎng)站來說大量日志寫入磁盤也會導(dǎo)致磁盤性能下降。
如何設(shè)置日志格式:可能使用Nginx部署過負(fù)載均衡的朋友都知道,當(dāng)把Nginx反向代理服務(wù)器部署在web前端時,web服務(wù)器的access_log就無法獲取用戶的真實(shí)ip地址了,針對這個問題的解決辦法會放到后面的文章中<Nginx日志設(shè)置及日志分析>
在Nginx-proxy-master服務(wù)器上配置Keepalived
#more /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
router_id nginx-proxy-ha
}
vrrp_script check_nginx {
script "/etc/keepalived/check_nginx.sh"
interval 2
weight 2
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 200
advert_int 1
authentication {
auth_type PASS
auth_pass 1234
}
track_interface {
eth0
}
track_script {
check_nginx
}
virtual_ipaddress {
192.168.1.100
}
}
有關(guān)check_nginx.sh的說明:如果Nginx-proxy-master上的nginx進(jìn)程由于某種原因停止了,但是keepalived進(jìn)程還正常運(yùn)行著,這時候Nginx-proxy-backup上的keepalived會認(rèn)為Nginx-proxy-master是正常的(因?yàn)閙aster檢測到backup的keepalived進(jìn)程還存在),所以在這種情況下當(dāng)Nginx進(jìn)程死亡的時候Keepalived也不會發(fā)生故障轉(zhuǎn)移。那么這個腳本的作用就是讓keepalived實(shí)時監(jiān)控Nginx進(jìn)程,當(dāng)發(fā)現(xiàn)Nginx進(jìn)程不存在的時候自動將本機(jī)的keepalived進(jìn)程殺死,從而實(shí)現(xiàn)故障轉(zhuǎn)移,腳本內(nèi)容如下(注:Nginx-proxy-master和Nginx-proxy-backup上此腳本內(nèi)容均一樣)
#more /etc/keepalived/check_nginx.sh #!/bin/bash if [ "$(ps -ef | grep "nginx: master process"| grep -v grep )" == "" ] then killall -9 keepalived fi
在Nginx-proxy-backup服務(wù)器上配置Keepalived
注:Nginx-proxy-backup上keepalived的配置與Nnginx-proxy-master只有兩處不同,state為BACKUP、優(yōu)先級低于master
#more /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
router_id nginx-proxy-ha
}
vrrp_script check_nginx {
script "/etc/keepalived/check_nginx.sh"
interval 2
weight 2
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 51
priority 180
advert_int 1
authentication {
auth_type PASS
auth_pass 1234
}
track_interface {
eth0
}
track_script {
check_nginx
}
virtual_ipaddress {
192.168.1.100
}
}
啟動Nginx和Keepalived
#/usr/local/nginx/sbin/nginx #/usr/local/keepalived/sbin/keepalived –D #echo “/usr/local/nginx/sbin/nginx”>>/etc/rc.local #echo “/usr/local/keepalived/sbin/keepalived –D” >>/etc/rc.local
測試負(fù)載均衡是否正常工作
1、打開瀏覽器,分別訪問Nginx-proxy-master、Nginx-proxy-backup、vip,如都能訪問到后端web內(nèi)容,則說明如上所有配置正確
2、殺死Nginx-proxy-master服務(wù)器上的Nginx進(jìn)程,觀察keepalived進(jìn)程是否自動消失、觀察vip是否已經(jīng)轉(zhuǎn)移到了Nginx-proxy-backup服務(wù)器上,如殺死Nginx進(jìn)程后,keepalived進(jìn)程也隨之消失,且vip已經(jīng)轉(zhuǎn)移到Nginx-proxy-backup服務(wù)器,則說明Nginx-proxy-master可正常實(shí)現(xiàn)故障轉(zhuǎn)移
3、依次啟動 Nginx-proxy-master的Nginx、Keepalived(必須先啟動Nginx后啟動Keepalived。如果先啟動Keepalived,Keepalived檢測到Nginx沒有啟動還是會執(zhí)行殺死自己進(jìn)程的腳本),然后將Nginx-proxy-backup的Nginx進(jìn)程殺死,看vip是否會自動轉(zhuǎn)移到Nginx-proxy-master服務(wù)器上,如殺死Nginx進(jìn)程后,keepalived進(jìn)程也隨之消失,且vip已經(jīng)轉(zhuǎn)移到Nginx-proxy-master服務(wù)器,則說明Nginx-proxy-backup可正常實(shí)現(xiàn)故障轉(zhuǎn)移
至此,Nginx負(fù)載均衡配置完畢。另外,Nginx非常穩(wěn)定,筆者的Nginx負(fù)載均衡運(yùn)行在HP DL380服務(wù)器上(一顆至強(qiáng)E5620CPU,16G內(nèi)存,萬轉(zhuǎn)SAS硬盤),運(yùn)行四個月以來,從未出現(xiàn)過任何問題。在負(fù)載性能上,2000并發(fā)情況下load average:僅為0.02, 0.01, 0.00,CPU使用率僅為3%,內(nèi)存使用為1G(算上linux系統(tǒng)本身使用,系統(tǒng)為64bit)。
作者簡介:陸文舉(微博),85后,一個整天跟機(jī)器打交道的山東人。




















