Server提供網路服務時,面臨到一台 Server 的 capacity 瓶頸,這時候,就可以用 L4 Load Balancer 或是 HAProxy 來進行網路分流與 load balance。
HAProxy 目前主要支援兩種 traffic,http 以及一般的 tcp,http traffic 是最主要支援的部份,HAProxy 可深入到 HTTP Traffic 的封包內容,並根據設定的條件修改封包資料。
安裝
我們可以選擇直接用 yum 安裝,目前的版本為 haproxy-1.5.2-2.el6.i686
yum install haproxy
安裝完成後,執行檔會放在 /usr/sbin 目錄中。
也可以選擇直接從 source code 編譯。
tar -zxvf haproxy-1.5.11.tar.gz
cd haproxy-1.5.11
make clean
# linux 核心為 2.6.x 可以用使用 TARGET=linux26 參數進行最佳化,如果真的不知道可以用 TARGET=generic 即可
make TARGET=linux26 USE_OPENSSL=1 ADDLIB=-lz
make install
安裝完成後,執行檔會裝在 /usr/local/sbin 目錄中。
自行編譯後,還需要製作 service 啟動檔,這也是從 yum 安裝的 haproxy 抄來的,改一下執行檔的路徑就可以用了。
vi /etc/init.d/haproxy
#!/bin/sh
#
# haproxy
#
# chkconfig: - 85 15
# description: HAProxy is a free, very fast and reliable solution \
# offering high availability, load balancing, and \
# proxying for TCP and HTTP-based applications
# processname: haproxy
# config: /etc/haproxy/haproxy.cfg
# pidfile: /var/run/haproxy.pid
# Source function library.
. /etc/rc.d/init.d/functions
# Source networking configuration.
. /etc/sysconfig/network
# Check that networking is up.
[ "$NETWORKING" = "no" ] && exit 0
exec="/usr/local/sbin/haproxy"
prog=$(basename $exec)
[ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog
lockfile=/var/lock/subsys/haproxy
check() {
$exec -c -V -f /etc/$prog/$prog.cfg
}
start() {
$exec -c -q -f /etc/$prog/$prog.cfg
if [ $? -ne 0 ]; then
echo "Errors in configuration file, check with $prog check."
return 1
fi
echo -n $"Starting $prog: "
# start it up here, usually something like "daemon $exec"
daemon $exec -D -f /etc/$prog/$prog.cfg -p /var/run/$prog.pid
retval=$?
echo
[ $retval -eq 0 ] && touch $lockfile
return $retval
}
stop() {
echo -n $"Stopping $prog: "
# stop it here, often "killproc $prog"
killproc $prog
retval=$?
echo
[ $retval -eq 0 ] && rm -f $lockfile
return $retval
}
restart() {
$exec -c -q -f /etc/$prog/$prog.cfg
if [ $? -ne 0 ]; then
echo "Errors in configuration file, check with $prog check."
return 1
fi
stop
start
}
reload() {
$exec -c -q -f /etc/$prog/$prog.cfg
if [ $? -ne 0 ]; then
echo "Errors in configuration file, check with $prog check."
return 1
fi
echo -n $"Reloading $prog: "
$exec -D -f /etc/$prog/$prog.cfg -p /var/run/$prog.pid -sf $(cat /var/run/$prog.pid)
retval=$?
echo
return $retval
}
force_reload() {
restart
}
fdr_status() {
status $prog
}
case "$1" in
start|stop|restart|reload)
$1
;;
force-reload)
force_reload
;;
check)
check
;;
status)
fdr_status
;;
condrestart|try-restart)
[ ! -f $lockfile ] || restart
;;
*)
echo $"Usage: $0 {start|stop|status|restart|try-restart|reload|force-reload}"
exit 2
esac
設定
設定檔會放在 /etc/haproxy/haproxy.cfg,設定內容有兩大部份,global 以及 proxy,而 proxy 中,有四個主要項目:defaults, listen, frontend 以及 backend 的部份。
global
範例
global
log 127.0.0.1 local2
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
user haproxy
group haproxy
daemon
nbproc 1
# turn on stats unix socket
stats socket /var/lib/haproxy/stats
此區塊可使用的設定項目
- chroot
- daemon
以 daemon 的方式運行 - nbproc
daemon mode 才能使用,設定 process 的數量 - user/uid
- group/gid
- log
- pidfile
stats
maxconn
可接受最大的連線數量
- noepoll
不使用 linux 的 epoll - nokqueue
不使用 BSD 的 kqueue polling - debug
將所有訊息顯示到 console - quiet
不顯示任何訊息
獨立的 haproxy logfile
我們必須調整一些 rsyslog 的設定,才能將 haproxy 的 log 放到獨立的 logfile 裡面。
vi /etc/rsyslog.conf
# 把這兩行的註解刪除
# Provides UDP syslog reception
$ModLoad imudp
$UDPServerRun 514
# 限制 rsyslog UDP 只會用在 127.0.0.1
$UDPServerAddress 127.0.0.1
新增一個檔案 /etc/rsyslog.d/haproxy.conf
vi /etc/rsyslog.d/haproxy.conf
local2.* /var/log/haproxy/haproxy.log
也可以用這個方式,將 log file 區分不同的 log level,要不然就放在同一個 log file 裡面就好了。
local2.=info /var/log/haproxy-info.log
local2.notice /var/log/haproxy-allbutinfo.log
重新啟動系統 log 記錄器
service rsyslog restart
編輯 haproxy.logrotate,讓 haproxy.log 檔案每天產生一個,然後保留 120 天的資料。
vi /etc/logrotate.d/haproxy.logrotate
/var/log/haproxy/haproxy.log {
missingok
notifempty
sharedscripts
rotate 120
daily
compress
postrotate
reload rsyslog >/dev/null 2>&1 || true
endscript
}
proxy
proxy 設定是由 defaults, listen, frontend, backend 組成。
defaults name
設定所有其他區塊的預設參數,如果設定檔中,後面又多了一塊 defaults 設定,後面的設定會覆蓋掉前面的設定。
frontend name
描述接受 client 端 request 的 listening sockets。
backend name
描述 proxy 會將 frontend 接收的 request 連線 forward 到後端的一組 servers。
listen name
定義完整的 proxy,包含了 frontend 與 backend,這個部份的定義,通常用在設定一般的 TCP-only traffic。
proxy 定義的名稱 name ,必須要使用這些字元 upper and lower case letters, digits,
'-' (dash), '_' (underscore) , '.' (dot) and ':' (colon)。
HTTP traffic
HAProxy 針對 http traffic 提供了五種 mode
KAL: keep alive ("option http-keep-alive")
這是預設值,所有處理中的 request, response 以及 connection 都會持續 idle 並保持連線。
TUN: tunnel ("option http-tunnel")
只會處理第一個 request 與 response,其他封包都會直接 forward,不進行任何分析與處理,目前建議不使用這個模式,因為會對 logging 以及 HTTP processing 造成問題。
PCL: passive close ("option httpclose")
就跟 tunnel mode 一樣,在處理完第一個封包後,會雙向加上 "conneciton: close",讓連線結束。
SCL: server close ("option http-server-close")
在收到最後的 response 時,就會 close server-facing connection,但仍然持續保留 client-facing connection。
FCL: forced close ("option forceclose")
在收到最後的 response 之後,就會關閉連線。
在一個 http connection 經過 frontend 與 backend 設定之後,可能會有兩段 proxy mode 的設定,最終這個 connection 的 mode 是由下表的規則決定,keep-alive 是最弱的設定值,而 force close 是最強的設定值。KAL < TUN < PCL < SCL < FCL
Backend mode
| KAL | TUN | PCL | SCL | FCL
----+-----+-----+-----+-----+----
KAL | KAL | TUN | PCL | SCL | FCL
----+-----+-----+-----+-----+----
TUN | TUN | TUN | PCL | SCL | FCL
Frontend ----+-----+-----+-----+-----+----
mode PCL | PCL | PCL | PCL | FCL | FCL
----+-----+-----+-----+-----+----
SCL | SCL | SCL | FCL | SCL | FCL
----+-----+-----+-----+-----+----
FCL | FCL | FCL | FCL | FCL | FCL
defaults
這個區塊的參數,是設定檔後面所有參數的預設設定值,下面的設定值會蓋掉上面的。
範例
defaults
mode http
log global
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000
此區塊可使用的設定項目
- balance
選擇使用那一種 algorithm 來執行 load balance。 - mode { tcp|http|health } (defaults 為 http)
- log global
- option httplog
Enable logging of HTTP request, session state and timers - option http-server-close
Enable or disable HTTP connection closing on the server side - option forwardfor except 127.0.0.0/8
因為 X-Forwarded-For header 裡面會有 client 的 IP,HAProxy 會利用此 header,所以增加此設定,可讓 X-Forwarded-For header 都轉送到 後端的 server - option redispatch
當 client 連到掛掉的機器時, 可重新再分配 - retries 3
失敗重試次數 - timeout http-request 10s
Set the maximum allowed time to wait for a complete HTTP request,等待 HTTP Request 完成的 timeout 時間 - timeout queue 1m
Set the maximum time to wait in the queue for a connection slot to be free,等待 queue 釋放空間的 timeout 時間 - timeout connect 10s
Set the maximum time to wait for a connection attempt to a server to succeed. - timeout client 1m
Set the maximum inactivity time on the client side. 當有 long polling 時,這個參數在 frontend 要調長到 long polling 最大的等待時間 - timeout server 1m
Set the maximum inactivity time on the server side. 當有 long polling 時,這個參數在 backend 要調長到 long polling 最大的等待時間 - timeout http-keep-alive 10s
Set the maximum allowed time to wait for a new HTTP request to appear - timeout check 10s
Set additional check timeout, but only after a connection has been already established. - maxconn 3000
連線到某個 server 的最大連線數
backend balance mode
這是 balance 設定值可選填的 algorithm 項目。
roundrobin
每個 server 依據權值 weight 依序選擇 servers,這是最快的 algorithm,server weight 會根據 instance slow start 的狀況而隨時變動。這個 algorithm 在每個 backend 最多可處理 4095 個 active server nodes。如果有個 server node 在 down 之後馬上又變成 active,可能會需要數百個 requests 之後,才會再 join 這個 server farm。
static-rr
每個 server 根據 weight 依序選擇 server,類似 roundrobin,但權值 weight 是固定的。沒有 active server node 的處理數量上限。
leastconn
目前處理最少連線數量的 server,作為下一個 connection 轉向的 server。建議在較長 tcp session 的服務中使用這個演算法,例如 LDAP, SQL, etc...,不適合用在類似 HTTP 這種短 sesion time 的 protocol。
first
server nodes 之中,選擇第一個可使用的 server,當這個 server 連線處理數量達到 maxconn 時,就會選擇下一個 server,所以設定檔中一定要有 maxconn 設定值。
source
source IP address 會 hashed 並除以 total weight of running serer,用這個結果來決定要選擇那一個 server,這可確保同一個 client IP 的 traffic 會連到同一個 server。如果 server nodes 數量改變了,就會因為重新計算 hash,造成 clients 連線到不同的 servers。
uri
可用 uri 的 ? 前面的部份,或是整個 uri 進行 hash,可確保同一個 uri 會轉給同一個 server。這個設定通常用在 proxy caches 與 anti-virus proxyies,用以提高 cache hit rate。
有兩個 optinal parameter: len 與 depth。len 就是使用 uri 裡面幾個字元,但因為 uri 通常是 / 開頭,所以不要將 len 設定為 1。
depth 表示計算 hash 的 maxmimum directory depth,出現一個 / 代表多了一層 depth。
url_param
使用 HTTP Get request URL 裡面的參數,如果用到了 "check_post",就會使用 POST request 裡面的參數。
hdr(name)
會尋找名稱為 name 的 HTTP header 欄位。
optonal 參數 "use_domain_only" 可用在指定 header 為 Host 的時候,如果 Host 為 "haproxy.1wt.eu" 就只會考慮 "1wt"
rdp-cookie, rdp-cookie(name)
尋找設定的 cookie,通常就是 session ID,如果沒有 session ID 就會使用 roundrobin algorithm。
一些設定的參考範例
範例 1:雖然這個是 listen 區塊,但實際上是設定一個網頁 service,提供一個 HAProxy 網頁監控界面。
# HAProxy 網頁管理界面
listen stats *:2000
mode http
stats enable
stats hide-version
stats realm Haproxy\ Statistics
stats uri /
# 帳號密碼
stats auth username:password
stats refresh 10s
範例 2:
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
frontend localnodes
bind *:80
mode http
default_backend nodes
backend nodes
mode http
balance roundrobin
option forwardfor
http-request set-header X-Forwarded-Port %[dst_port]
http-request add-header X-Forwarded-Proto https if { ssl_fc }
option httpchk HEAD / HTTP/1.1\r\nHost:localhost
server web01 127.0.0.1:9000 check
server web02 127.0.0.1:9001 check
server web03 127.0.0.1:9002 check
範例 3:
defaults
log global
mode http
option httplog
option dontlognull
retries 3
option redispatch
option httpclose
maxconn 32768
contimeout 5000
clitimeout 50000
srvtimeout 50000
listen www-balancer
bind 0.0.0.0:80
balance roundrobin
server w1 192.168.1.10:80 weight 3 check
server w2 192.168.1.20:80 weight 3 check
option httpchk GET /robots.txt
option forwardfor
範例 4: DB1 與 DB2 設定為 Master-Master Replication
defaults
mode tcp
option redispatch #連前當前配置失敗時,允許重新配發到他台機器
option abortonclose
timeout connect 5000ms
timeout client 30000ms
timeout server 30000ms
log 127.0.0.1 local0
balance roundrobin #使用輪替演算法,分散主機流量
listen proxy
bind *:3306 #綁定192.168.11.180的3306 Port為運行主機端口
mode tcp
server db1 192.168.1.10:3306 weight 1 check
#後端主機.178,179,權重值配置
server db2 192.168.1.20:3306 weight 2 check
#check 參數檢查改主機是否Live
範例 5:
defaults
timeout server 86400000
timeout connect 86400000
timeout client 86400000
timeout queue 1000s
# [HTTP Site Configuration]
listen http_web 192.168.10.10:80
mode http
balance roundrobin # Load Balancing algorithm
option httpchk
option forwardfor
server server1 192.168.1.10:80 weight 1 maxconn 512 check
server server2 192.168.1.20:80 weight 1 maxconn 512 check
# [HTTPS Site Configuration]
listen https_web 192.168.10.10:443
mode tcp
balance source# Load Balancing algorithm
reqadd X-Forwarded-Proto:\ http
server server1 192.168.1.10:443 weight 1 maxconn 512 check
server server2 192.168.1.20:443 weight 1 maxconn 512 check
References
富人用 L4 Switch,窮人用 Linux HAProxy!
使用 HAProxy 完成 網站分流, 平衡負載
[FreeBSD & Linux]網站分流:簡易架設 HAProxy 伺服器
使用 Haproxy 搭建高可用與負載平衡叢集