HAProxy雙機高可用方案之HAProxy+Keepalived
原創【51CTO.com 獨家特稿】由于公司的注冊用戶已超過八百萬了,而且每天都有持續增漲的趨勢,而PV/日已經有向千萬靠擾的趨勢;原有的Web架構越來越滿足不了我們的需求了,所以我們也考慮上能抗高并發的HAProxy來作為我們網站的最前端的負載均衡器;因為我已經在東莞的二個項目上面成功實施了HAProxy+Keepalived雙機方案,所以我在這里也嘗試在公司的網站上這種負載均衡高可用架構,即HAProxy+Keepalived。
HAProxy+Keepalived配置過程如下:
1. 做好整個環境的準備工作。
兩臺服務器DELL 2950均要做好準備工作,比如設置好hosts文件及進行ntpd對時。
網絡拓樸很簡單,如下所示:
ha1.cn7789.com eth0:203.93.236.145
ha2.cn7789.com eth0:203.93.236.142
網卡用其自帶的千兆網卡均可。
硬盤模式沒有要求,Raid0或Raid1均可。
網站對外的VIP地址是:203.93.236.149,這是通過Keepalived來實現的,原理請參考前面的章節;同時這也是我們的網站的外網DNS對應的IP。
2. HAProxy和Keepalived的安裝過程
關于此安裝過程,請大家參考前面的內容,這里就不重復了,我們主要是注意關鍵位置的改動:
(1)首先是要建立HAProxy啟動、重啟、關閉等狀態腳本,我這里的HAProxy腳本為/root/haproxy,我們給它執行權限,腳本內容如下所示:
- #!/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文件的內容如下所示(兩臺HAProxy機器的配置內容一樣):
- 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(后臺)的形式,方便我們根據需求也可以利用HAProxy的正則做成動靜分離或根據特定的文件名后綴(比如.php或.jsp)訪問指定的phppool池或javapool池(Nginx也能實現此項功能),我們還可以指定靜態服務器池,讓客戶端對靜態文件(比如bmp或jsp或html)訪問我們的Nginx靜態服務器,所以前后臺的模型也是非常有用的,不喜歡frontend(前臺)和backend(后臺)的朋友可以對比下以前沒有采用這種模式的配置文件,內容如下:
- 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的正則寫法,這些對于我們以后的工作幫助還是很大的,內容如下:
####################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 #當請求的header中Content-length等于0時返回 true acl missing_cl hdr_cnt(Content-length) eq 0 ######################acl策略匹配相應################### #當請求中header中Content-length等于0 阻止請求返回403 block if missing_cl #block表示阻止請求,返回403錯誤,當前表示如果不滿足策略invalid_req,或者滿足策略timetask_req,則阻止請求。 block if !invalid_req || timetask_req #當滿足denali_policy的策略時使用denali_server的backend use_backend denali_server if denali_policy #當滿足tm_policy的策略時使用tm_server的backend use_backend tm_server if tm_policy #reqisetbe關鍵字定義,根據定義的關鍵字選擇backend reqisetbe ^Host:\ img dynamic reqisetbe ^[^\ ]*\ /(img|css)/ dynamic reqisetbe ^[^\ ]*\ /admin/stats stats #以上都不滿足的時候使用默認mms_server的backend default_backend mms_server Keepalived的配置過程比較簡單,這里略過,大家可以參考我們前面的配置,配置成功后我們可以分別在二臺機器上啟動HAProxy及Keepalived服務(建議在Screen模式下開啟HAProxy服務,不熟悉Sreen用法的朋友建議熟悉下)。 |
#p#
3.替HAProxy添加日志支持
我們編輯/etc/syslog.conf文件, 添加內容如下:
local3.* /var/log/haproxy.log
local0.* /var/log/haproxy.log
我們編輯/etc/sysconfig/syslog文件,修改內容如下:
SYSLOGD_OPTIONS="-r -m 0"
然后重啟syslog服務,命令如下:
service syslog restart
4.驗證此架構及注意事項
我們可以關閉主HAProxy機器或重新啟動,看在此過程中,VIP地址有沒有正確的轉移到從HAProxy機器上,影響我們訪問網站沒,以上步驟我自己測試過多次,而且線上環境的穩定運行,證明HAProxy+Keeaplived雙機方案確實是有效的。
關于HAProxy+Heartbeat這種負載均衡高可用架構,有些情況我也跟大家說明一下:
◆在此HAProxy+Keepalivp負載均衡高可用架構中,我們是如何解決session的問題呢?我們這里采用的是它自身的balance source機制,它跟Nginx的ip_hash機制原理類似,是讓客戶機訪問時始終訪問后端的某一臺真實的web服務器,這樣讓session就固定下來了;
◆option httpchk HEAD /index.jsp HTTP/1.0 是網頁監控,如果HAProxy檢測不到Web的根目錄下沒有index.jsp,就會產生503報錯。
◆有網友配置HAProxy時喜歡用listen 203.93.236.141:80這樣的格式,這樣其實不好,做負載均衡高可用時由于從機分配不到VIP地址,會導致從機啟動不了,我建議用bind *:80的方式代替。
◆HAProxy的并發監控暫時沒有Nginx中的相關模塊,但可以考慮用SHELL命令或自行開發PHP或JSP程序來監控。
5.HAProxy的監控頁面
我們可以在地址欄輸入http://www.1paituan.com/haproxy-stats/,顯示界面如下(HAProxy自帶的監控頁面,也是我非常喜歡的功能之一):
作者介紹:
余洪春(撫琴煮酒·微博),《構建高可用Linux服務器》一書作者,一拍網系統架構師、資深項目管理工程師,ChinaUnix集群和高可用版版主。
【51CTO.com獨家特稿,非經授權謝絕轉載!合作媒體轉載請注明原文出處及出處!】