HAProxy雙機高可用方案之HAProxy+Keepalived
原創(chuàng)【51CTO.com 獨家特稿】由于公司的注冊用戶已超過八百萬了,而且每天都有持續(xù)增漲的趨勢,而PV/日已經(jīng)有向千萬靠擾的趨勢;原有的Web架構(gòu)越來越滿足不了我們的需求了,所以我們也考慮上能抗高并發(fā)的HAProxy來作為我們網(wǎng)站的最前端的負載均衡器;因為我已經(jīng)在東莞的二個項目上面成功實施了HAProxy+Keepalived雙機方案,所以我在這里也嘗試在公司的網(wǎng)站上這種負載均衡高可用架構(gòu),即HAProxy+Keepalived。
HAProxy+Keepalived配置過程如下:
1. 做好整個環(huán)境的準(zhǔn)備工作。
兩臺服務(wù)器DELL 2950均要做好準(zhǔn)備工作,比如設(shè)置好hosts文件及進行ntpd對時。
網(wǎng)絡(luò)拓樸很簡單,如下所示:
ha1.cn7789.com eth0:203.93.236.145
ha2.cn7789.com eth0:203.93.236.142
網(wǎng)卡用其自帶的千兆網(wǎng)卡均可。
硬盤模式?jīng)]有要求,Raid0或Raid1均可。
網(wǎng)站對外的VIP地址是:203.93.236.149,這是通過Keepalived來實現(xiàn)的,原理請參考前面的章節(jié);同時這也是我們的網(wǎng)站的外網(wǎng)DNS對應(yīng)的IP。
2. HAProxy和Keepalived的安裝過程
關(guān)于此安裝過程,請大家參考前面的內(nèi)容,這里就不重復(fù)了,我們主要是注意關(guān)鍵位置的改動:
(1)首先是要建立HAProxy啟動、重啟、關(guān)閉等狀態(tài)腳本,我這里的HAProxy腳本為/root/haproxy,我們給它執(zhí)行權(quán)限,腳本內(nèi)容如下所示:
- #!/bin/sh
- # chkconfig 35 on
- # description: HAProxy is a TCP/HTTP reverse proxy which is particularly suited for high availability environments.
- # Source function library.
- if [ -f /etc/init.d/functions ]; then
- . /etc/init.d/functions
- elif [ -f /etc/rc.d/init.d/functions ] ; then
- . /etc/rc.d/init.d/functions
- else
- exit 0
- fi
- # Source networking configuration.
- . /etc/sysconfig/network
- # Check that networking is up.
- [ ${NETWORKING} = "no" ] && exit 0
- [ -f /usr/local/haproxy/conf/haproxy.cfg ] || exit 1
- RETVAL=0
- start() {
- /usr/local/haproxy/sbin/haproxy -c -q -f /usr/local/haproxy/conf/haproxy.cfg
- if [ $? -ne 0 ]; then
- echo "Errors found in configuration file."
- return 1
- fi
- echo -n "Starting HAproxy: "
- daemon /usr/local/haproxy/sbin/haproxy -D -f /usr/local/haproxy/conf/haproxy.cfg -p /var/run/haproxy.pid
- RETVAL=$?
- echo
- [ $RETVAL -eq 0 ] && touch /var/lock/subsys/haproxy
- return $RETVAL
- }
- stop() {
- echo -n "Shutting down HAproxy: "
- killproc haproxy -USR1
- RETVAL=$?
- echo
- [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/haproxy
- [ $RETVAL -eq 0 ] && rm -f /var/run/haproxy.pid
- return $RETVAL
- }
- restart() {
- /usr/local/haproxy/sbin/haproxy -c -q -f /usr/local/haproxy/conf/haproxy.cfg
- if [ $? -ne 0 ]; then
- echo "Errors found in configuration file, check it with 'haproxy check'."
- return 1
- fi
- stop
- start
- }
- check() {
- /usr/local/haproxy/sbin/haproxy -c -q -V -f /usr/local/haproxy/conf/haproxy.cfg
- }
- rhstatus() {
- status haproxy
- }
- condrestart() {
- [ -e /var/lock/subsys/haproxy ] && restart || :
- }
- # See how we were called.
- case "$1" in
- start)
- start
- ;;
- stop)
- stop
- ;;
- restart)
- restart
- ;;
- reload)
- restart
- ;;
- condrestart)
- condrestart
- ;;
- status)
- rhstatus
- ;;
- check)
- check
- ;;
- *)
- echo $"Usage: haproxy {start|stop|restart|reload|condrestart|status|check}"
- RETVAL=1
- esac
- exit $RETVAL
#p#
(2)/usr/local/haproxy/conf/haproxy.cfg文件的內(nèi)容如下所示(兩臺HAProxy機器的配置內(nèi)容一樣):
- global
- log 127.0.0.1 local0
- maxconn 65535
- chroot /usr/local/haproxy
- uid 99
- gid 99
- daemon
- nbproc 8
- pidfile /usr/local/haproxy/haproxy.pid
- debug
- defaults
- log 127.0.0.1 local3
- mode http
- option httplog
- option httpclose
- option dontlognull
- option forwardfor
- option redispatch
- retries 2
- maxconn 2000
- stats uri /haproxy-stats
- contimeout 5000
- clitimeout 50000
- srvtimeout 50000
- frontend www.1paituan.com
- bind *:80
- mode http
- option httplog
- log global
- default_backend phppool
- backend phppool
- balance source
- option httpchk HEAD /index.jsp HTTP/1.0
- server web1 203.93.236.147:80 weight 5 check inter 2000 rise 2 fall 3
- server web2 203.93.236.146:80 weight 3 check inter 2000 rise 2 fall 3
配置文件建議寫成這種frontend(前臺)和backend(后臺)的形式,方便我們根據(jù)需求也可以利用HAProxy的正則做成動靜分離或根據(jù)特定的文件名后綴(比如.php或.jsp)訪問指定的phppool池或javapool池(Nginx也能實現(xiàn)此項功能),我們還可以指定靜態(tài)服務(wù)器池,讓客戶端對靜態(tài)文件(比如bmp或jsp或html)訪問我們的Nginx靜態(tài)服務(wù)器,所以前后臺的模型也是非常有用的,不喜歡frontend(前臺)和backend(后臺)的朋友可以對比下以前沒有采用這種模式的配置文件,內(nèi)容如下:
- global
- log 127.0.0.1 local0
- maxconn 65535
- chroot /usr/local/haproxy
- uid 99
- gid 99
- daemon
- nbproc 8
- pidfile /usr/local/haproxy/haproxy.pid
- debug
- defaults
- log 127.0.0.1 local3
- mode http
- option httplog
- option httpclose
- option dontlognull
- option forwardfor
- option redispatch
- retries 2
- maxconn 2000
- balance source
- stats uri /haproxy-stats
- contimeout 5000
- clitimeout 50000
- srvtimeout 50000
- listen www.1paituan.com
- bind *:80
- mode http
- option httplog
- log global
- option httpchk HEAD /index.jsp HTTP/1.0
- server web1 203.93.236.147:80 weight 5 check inter 2000 rise 2 fall 3
- server web2 203.93.236.146:80 weight 3 check inter 2000 rise 2 fall 3
HAProxy的正則功能雖然沒Nginx強大靈活,但也是非常有用的;大家可以參考下面的文檔來熟悉下HAProxy的正則寫法,這些對于我們以后的工作幫助還是很大的,內(nèi)容如下:
####################acl策略定義######################### #如果請求的域名滿足正則表達式返回true -i是忽略大小寫 acl denali_policy hdr_reg(host) -i ^(www.gemini.taobao.net|my.gemini.taobao.net|auction1.gemini.taobao.net)$ #如果請求域名滿足trade.gemini.taobao.net 返回 true -i是忽略大小寫 acl tm_policy hdr_dom(host) -i trade.gemini.taobao.net #在請求url中包含sip_apiname=,則此控制策略返回true,否則為false acl invalid_req url_sub -i sip_apiname= #在請求url中存在timetask作為部分地址路徑,則此控制策略返回true,否則返回false acl timetask_req url_dir -i timetask #當(dāng)請求的header中Content-length等于0時返回 true acl missing_cl hdr_cnt(Content-length) eq 0 ######################acl策略匹配相應(yīng)################### #當(dāng)請求中header中Content-length等于0 阻止請求返回403 block if missing_cl #block表示阻止請求,返回403錯誤,當(dāng)前表示如果不滿足策略invalid_req,或者滿足策略timetask_req,則阻止請求。 block if !invalid_req || timetask_req #當(dāng)滿足denali_policy的策略時使用denali_server的backend use_backend denali_server if denali_policy #當(dāng)滿足tm_policy的策略時使用tm_server的backend use_backend tm_server if tm_policy #reqisetbe關(guān)鍵字定義,根據(jù)定義的關(guān)鍵字選擇backend reqisetbe ^Host:\ img dynamic reqisetbe ^[^\ ]*\ /(img|css)/ dynamic reqisetbe ^[^\ ]*\ /admin/stats stats #以上都不滿足的時候使用默認(rèn)mms_server的backend default_backend mms_server Keepalived的配置過程比較簡單,這里略過,大家可以參考我們前面的配置,配置成功后我們可以分別在二臺機器上啟動HAProxy及Keepalived服務(wù)(建議在Screen模式下開啟HAProxy服務(wù),不熟悉Sreen用法的朋友建議熟悉下)。 |
#p#
3.替HAProxy添加日志支持
我們編輯/etc/syslog.conf文件, 添加內(nèi)容如下:
local3.* /var/log/haproxy.log
local0.* /var/log/haproxy.log
我們編輯/etc/sysconfig/syslog文件,修改內(nèi)容如下:
SYSLOGD_OPTIONS="-r -m 0"
然后重啟syslog服務(wù),命令如下:
service syslog restart
4.驗證此架構(gòu)及注意事項
我們可以關(guān)閉主HAProxy機器或重新啟動,看在此過程中,VIP地址有沒有正確的轉(zhuǎn)移到從HAProxy機器上,影響我們訪問網(wǎng)站沒,以上步驟我自己測試過多次,而且線上環(huán)境的穩(wěn)定運行,證明HAProxy+Keeaplived雙機方案確實是有效的。
關(guān)于HAProxy+Heartbeat這種負載均衡高可用架構(gòu),有些情況我也跟大家說明一下:
◆在此HAProxy+Keepalivp負載均衡高可用架構(gòu)中,我們是如何解決session的問題呢?我們這里采用的是它自身的balance source機制,它跟Nginx的ip_hash機制原理類似,是讓客戶機訪問時始終訪問后端的某一臺真實的web服務(wù)器,這樣讓session就固定下來了;
◆option httpchk HEAD /index.jsp HTTP/1.0 是網(wǎng)頁監(jiān)控,如果HAProxy檢測不到Web的根目錄下沒有index.jsp,就會產(chǎn)生503報錯。
◆有網(wǎng)友配置HAProxy時喜歡用listen 203.93.236.141:80這樣的格式,這樣其實不好,做負載均衡高可用時由于從機分配不到VIP地址,會導(dǎo)致從機啟動不了,我建議用bind *:80的方式代替。
◆HAProxy的并發(fā)監(jiān)控暫時沒有Nginx中的相關(guān)模塊,但可以考慮用SHELL命令或自行開發(fā)PHP或JSP程序來監(jiān)控。
5.HAProxy的監(jiān)控頁面
我們可以在地址欄輸入http://www.1paituan.com/haproxy-stats/,顯示界面如下(HAProxy自帶的監(jiān)控頁面,也是我非常喜歡的功能之一):
作者介紹:
余洪春(撫琴煮酒·微博),《構(gòu)建高可用Linux服務(wù)器》一書作者,一拍網(wǎng)系統(tǒng)架構(gòu)師、資深項目管理工程師,ChinaUnix集群和高可用版版主。
【51CTO.com獨家特稿,非經(jīng)授權(quán)謝絕轉(zhuǎn)載!合作媒體轉(zhuǎn)載請注明原文出處及出處!】