LB負載平衡叢集分兩類: LVS (四層)和 nginx或haproxy (七層)。LVS是基於IP的,而nginx和haproxy是基於應用的。
用戶端通過訪問分發器的IP來訪問網站。分發器根據請求的類型,將請求轉寄到後端相應的機器上。 使用nginx實現動靜分離的負載平衡叢集
拓撲圖:
分發器的IP是192.168.226.81。其他幾種在後端,處理實際訪問的相應類型的伺服器各兩台。這裡預設每台機器的處理伺服器均已裝好。其中分發器是安裝的nginx,另外的機器可以是apache也可以是nginx。下面只需要講解實際是如何配置的。 分發器配置
修改nginx的設定檔nginx.conf。找到設定檔中server段中的location配置段,在location配置段中增加:
# 匹配到html的請求,就轉寄到htmlserversif ($request_uri ~* \.html$){ proxy_pass http://htmlservers;}# 匹配到php的請求,就轉寄到phpserversif ($request_uri ~* \.php$){ proxy_pass http://phpservers;}# 非上面兩種請求,就轉寄到picserversproxy_pass http://picservers;
然後再在http段的末端加入:
upstream htmlservers { #定義負載平衡伺服器組名稱 server 192.168.226.50:80; server 192.168.226.51:80;}upstream phpservers{ server 192.168.226.81:80; server 192.168.226.83:80;}upstream picservers { server 192.168.226.90:80; server 192.168.226.91:80;}
如果要為每個伺服器增加輪詢的權重,就在每個轉寄IP後添加weight權重值即可。即:
upstream htmlservers { #定義負載平衡伺服器組名稱 server 192.168.226.50:80 weight=1; server 192.168.226.51:80 weight=2;}upstream phpservers{ server 192.168.226.81:80 weight=1; server 192.168.226.83:80 weight=2;}upstream picservers { server 192.168.226.90:80 weight=1; server 192.168.226.91:80 weight=2;}
最後,將nginx設定檔中解析php的部分注釋掉,否則會在訪問php檔案的時候,分發器就直接解析了php,而不是轉寄給後端的php伺服器。
# location ~ \.php$ {# root html;# fastcgi_pass 127.0.0.1:9000;# fastcgi_index index.php;# #fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;# fastcgi_param SCRIPT_FILENAME /usr/local/nginx/html$fastcgi_script_name;# include fastcgi_params;# }
PS:
* 其中htmlservers、phpservers、picservers都是自己命的名,只要滿足一個要求:添加到兩個地方的相應名稱一致即可。即添加到proxy_pass後的伺服器名稱和添加到upstream後的伺服器名稱對應。
2. 重啟nginx
[root@cos-7 nginx]# /usr/local/nginx/sbin/nginx -tnginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is oknginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful[root@cos-7 nginx]# /usr/local/nginx/sbin/nginx -s reload
ok,配置完成。要測試的話,可以在相應的伺服器中新增內容可識別的檔案,然後訪問分發器的ip即可。
這裡我的nginx版本是1.12.2。這裡附上我配置完成後的nginx完整設定檔
user nginx nginx;worker_processes 1;#error_log logs/error.log;#error_log logs/error.log notice;#error_log logs/error.log info;#pid logs/nginx.pid;events { worker_connections 1024;}http { include mime.types; default_type application/octet-stream; #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' # '$status $body_bytes_sent "$http_referer" ' # '"$http_user_agent" "$http_x_forwarded_for"'; #access_log logs/access.log main; sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; #gzip on; server { listen 80; server_name localhost; #charset koi8-r; #access_log logs/host.access.log main; location / { root html; index index.html index.htm index.php; # 添加轉寄配置 if ($request_uri ~* \.html$){ proxy_pass http://htmlserver; } if ($request_uri ~* \.php$){ proxy_pass http://phpserver; } proxy_pass http://picserver; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # #location ~ \.php$ { # proxy_pass http://127.0.0.1; #} # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 ## location ~ \.php$ {# root html;# fastcgi_pass 127.0.0.1:9000;# fastcgi_index index.php;# #fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;# fastcgi_param SCRIPT_FILENAME /usr/local/nginx/html$fastcgi_script_name;# include fastcgi_params;# } # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; #} } # another virtual host using mix of IP-, name-, and port-based configuration # #server { # listen 8000; # listen somename:8080; # server_name somename alias another.alias; # location / { # root html; # index index.html index.htm; # } #} # HTTPS server # #server { # listen 443 ssl; # server_name localhost; # ssl_certificate cert.pem; # ssl_certificate_key cert.key; # ssl_session_cache shared:SSL:1m; # ssl_session_timeout 5m; # ssl_ciphers HIGH:!aNULL:!MD5; # ssl_prefer_server_ciphers on; # location / { # root html; # index index.html index.htm; # } #} # 添加轉寄伺服器,這裡採用權重輪詢的方式 upstream htmlserver { #定義負載平衡伺服器組名稱 server 192.168.226.50:80 weight=1; server 192.168.226.51:80 weight=2; } upstream phpserver{ server 192.168.226.81:80 weight=1; server 192.168.226.83:80 weight=2; } upstream picserver{ server 192.168.226.90:80 weight=1; server 192.168.226.91:80 weight=2; }}
使用haproxy實現負載平衡
HAProxy提供高可用性、負載平衡以及基於TCP和HTTP應用的代理,支援虛擬機器主機,它是免費、快速並且可靠的一種解決方案。根據官方資料,其最高極限支援10G的並發。
HAProxy特別適用於那些負載特大的web網站, 這些網站通常又需要會話保持或七層處理。HAProxy運行在當前的硬體上,完全可以支援數以萬計的並發串連。並且它的運行模式使得它可以很簡單安全的整合進您當前的架構中, 同時可以保護你的web伺服器不被暴露到網路上。
其支援從4層至7層的網路交換,即覆蓋所有的TCP協議。就是說,Haproxy 甚至還支援 Mysql的均衡負載。
相同點: 在功能上,haproxy通過反向 Proxy方式實現 WEB均衡負載。和 Nginx,ApacheProxy,lighttpd,Cheroke 等一樣。
不同點: Haproxy 並不是 網頁伺服器。以上提到所有帶反向 Proxy均衡負載的產品,都是 WEB 伺服器。簡單說,就是他們能處理解析頁面。而Haproxy 僅僅是一款的用於均衡負載的應用代理。其自身並不能提供web服務。但其配置簡單,擁有非常不錯的伺服器健全狀態檢查功能還有專門的系統狀態監控頁面,當其代理的後端伺服器出現故障, HAProxy會自動將該伺服器摘除,故障恢複後再自動將該伺服器加入。
haproxy官網
這裡安裝的版本是1.7.10
拓撲圖:
查看系統版本(haproxy安裝是需要根據系統核心版本的不同來輸入不同的make參數的)
[root@cos-7 soft]# uname -aLinux cos-7.4-90 3.10.0-693.el7.x86_64 #1 SMP Tue Aug 22 21:09:27 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
參數列表:
2. 解壓並安裝(安裝前需要查看系統的版本)
[root@cos-7 soft]# tar xf haproxy-1.7.10.tar.gz -C /usr/local/src/[root@cos-7 soft]# cd /usr/local/src/haproxy-1.7.10[root@cos-7 soft]# make TARGET=linux2628 PREFIX=/usr/local/haproxy[root@cos-7 soft]# make install PREFIX=/usr/local/haproxy
PS: 如果不想在make的時候,後面輸入參數,也可以直接修改源碼包中的Makefile檔案。將其中的PREFIX的值改為你的安裝路徑。TARGET的值改為相應的核心版本。
3. 為haproxy組建組態檔案haproxy.cfg
[root@cos-7 ~]# mkdir -p /usr/local/haproxy/etc[root@cos-7 etc]# cd /usr/local/haproxy/etc[root@cos-7 etc]# vim haproxy.cfg
haproxy.cfg檔案內容是
globallog 127.0.0.1 local0#log 127.0.0.1 local1 notice#log loghost local0 infomaxconn 4096chroot /usr/local/haproxyuid 99 #所屬啟動並執行使用者uidgid 99 #所屬啟動並執行使用者組daemon #以後台形式運行haproxynbproc 1 #啟動1個haproxy執行個體。# #背景工作處理序數量(CPU數量) ,實際工作中,應該設定成和CPU核心數一樣。 這樣可以發揮出最大的效能。pidfile /usr/local/haproxy/run/haproxy.pid #將所有進程寫入pid檔案#debug #調試錯誤時用#quiet #安靜defaultslog globallog 127.0.0.1 local3 #記錄檔的輸出定向。產生的記錄層級為local3. 系統中local1-7,使用者自己定義mode http #工作模式,所處理的類別,預設採用http模式,可配置成tcp作4層訊息轉寄option httplog #日誌類別,記載http日誌option httpclose #每次請求完畢後主動關閉http通道,haproxy不支援keep-alive,只能類比這種模式的實現option dontlognull #不記錄空串連,產生的日誌option forwardfor #如果後端伺服器需要獲得用戶端真實ip需要配置的參數,可以從Http Header中獲得用戶端ipoption redispatch #當serverid對應的伺服器掛掉後,強制定向到其他健康伺服器retries 2 #2次串連失敗就認為伺服器不可用,主要通過後面的check檢查maxconn 2000 #最大串連數balance roundrobin #負載平衡演算法stats uri /haproxy-stats #haproxy 監控頁面的訪問地址 # 可通過 http://localhost:80/haproxy-stats 訪問timeout connect 5000 #連線逾時時間。 單位:ms 毫秒timeout client 50000 #用戶端連線逾時時間timeout server 50000 #伺服器端連線逾時時間mode httpoption httpchk GET /index.html #健康檢測#注意實際工作中測試時,應該下載某一個頁面來進行測試,因此這個頁面應該是個小頁面,而不要用首頁面。這裡是每隔一秒檢查一次頁面。frontend http #前端配置,http名稱可自訂bind 0.0.0.0:80 #發起http請求80連接埠,會被轉寄到設定的ip及連接埠default_backend http_back #轉寄到後端 寫上後端名稱backend http_back #後端配置,名稱上下關聯server s1 192.168.226.81:80 weight 3 check #後端的主機 IP &權衡server s2 192.168.226.83:80 weight 3 check #後端的主機 IP &權衡#server node1 192.168.179.131:8081 check inter 2000 rise 3 fall 3 weight 30 # inter 2000 健全狀態檢查時間間隔2秒 # rise 3 檢測多少次才認為是正常的 # fall 3 失敗多少次才認為是停用# weight 30 權重
PS:關於負載平衡演算法
* source 根據請求源IP
* static-rr 根據權重
* leastconn 最少串連者先處理
* uri 根據請求的uri
* url_param 根據請求的url參數
* rdp-cookie 據據cookie(name)來鎖定並雜湊每一次請求
* hdr(name) 根據HTTP要求標頭來鎖定每一次HTTP請求
* roundrobin 輪詢方式
4. 賦值haproxy啟動指令碼到/etc/init.d/目錄下
[root@cos-7 ~]# cp /usr/local/src/haproxy-1.7.10/examples/haproxy.init /etc/init.d/haproxy[root@cos-7 ~]# chmod 755 /etc/init.d/haproxy[root@cos-7 ~]# mkdir -p /usr/local/haproxy/run[root@cos-7 ~]# cp /usr/local/haproxy/sbin/haproxy /usr/sbin/[root@cos-7 ~]# chown nobody /usr/local/haproxy
haproxy啟動指令碼賦值過來後,還有一些地方需要修改。
* 將BASENAME的值改為haproxy
* BIN的值改為/usr/sbin/haproxy
* CFG的值改為/usr/local/haproxy/etc/haproxy.cfg
* PIDFILE的值改為/usr/local/haproxy/run/haproxy.pid
* LOCKFILE的值改為/usr/local/haproxy/run/haproxy
修改後的檔案內容
#!/bin/sh## chkconfig: - 85 15# description: HA-Proxy is a TCP/HTTP reverse proxy which is particularly suited \# for high availability environments.# processname: haproxy# config: /etc/haproxy/haproxy.cfg# pidfile: /var/run/haproxy.pid# Script Author: Simon Matter <simon.matter@invoca.ch># Version: 2004060600# Source function library.if [ -f /etc/init.d/functions ]; then . /etc/init.d/functionselif [ -f /etc/rc.d/init.d/functions ] ; then . /etc/rc.d/init.d/functionselse exit 0fi# Source networking configuration.. /etc/sysconfig/network# Check that networking is up.[ ${NETWORKING} = "no" ] && exit 0# This is our service nameBASENAME=`haproxy`#if [ -L $0 ]; then# BASENAME=`find $0 -name $BASENAME -printf %l`# BASENAME=`basename $BASENAME`#fiBIN=/usr/sbin/haproxyCFG=/usr/local/haproxy/etc/haproxy.cfg[ -f $CFG ] || exit 1PIDFILE=/usr/local/haproxy/run/haproxy.pidLOCKFILE=/usr/local/haproxy/run/haproxyRETVAL=0start() { quiet_check if [ $? -ne 0 ]; then echo "Errors found in configuration file, check it with '$BASENAME check'." return 1 fi echo -n "Starting $BASENAME: " daemon $BIN -D -f $CFG -p $PIDFILE RETVAL=$? echo [ $RETVAL -eq 0 ] && touch $LOCKFILE return $RETVAL}stop() { echo -n "Shutting down $BASENAME: " killproc $BASENAME -USR1 RETVAL=$? echo [ $RETVAL -eq 0 ] && rm -f $LOCKFILE [ $RETVAL -eq 0 ] && rm -f $PIDFILE return $RETVAL}restart() { quiet_check if [ $? -ne 0 ]; then echo "Errors found in configuration file, check it with '$BASENAME check'." return 1 fi stop start}reload() { if ! [ -s $PIDFILE ]; then return 0 fi quiet_check if [ $? -ne 0 ]; then echo "Errors found in configuration file, check it with '$BASENAME check'." return 1 fi $BIN -D -f $CFG -p $PIDFILE -sf $(cat $PIDFILE)}check() { $BIN -c -q -V -f $CFG}quiet_check() { $BIN -c -q -f $CFG}rhstatus() { status $BASENAME}condrestart() { [ -e $LOCKFILE ] && restart || :}# See how we were called.case "$1" in start) start ;; stop) stop ;; restart) restart ;; reload) reload ;; condrestart) condrestart ;; status) rhstatus ;; check) check ;; *) echo $"Usage: $BASENAME {start|stop|restart|reload|condrestart|status|check}" exit 1esacexit $?
5. 配置日誌收集
[root@cos-7 ~]# vim /etc/rsyslog.conf
將#$ModLoad imudp和#$UDPServerRun 514兩行的注釋開啟。然後在local7.*這一行下面添加兩行
local3.* /var/log/haproxy.loglocal0.* /var/log/haproxy.log