常見的負載均衡技術

1、簡述四層和七層負載均衡的特點及Haproxy與LVS之間的對比
2、簡述Haproxy常見的負載均衡調度算法及應用場景詳解
3、通過Haproxy的ACL規劃實現智能負載均衡,並簡述tcp、http、health的配置示例
4、LNMT實現動靜分離實戰

1、簡述四層和七層負載均衡的特點及Haproxy與LVS之間的對比

(1)簡述四層和七層負載均衡的特點

四層負責均衡:主要是指通過判斷報文的IP地址和端口並通過一定的負載均衡算法來決定轉發到哪個指定目標,主要工作在OSI模型的第四層。四層負載均衡對數據包只是起一個數據轉發的作用,並不會干預客戶端與服務器之間應用層的通信(如:三次握手等)。所以能對數據所進行的操作也就很少,但相對於七層負載均衡來講效率會高上很多

七層負載均衡:也被稱爲“內容交換”,指的是負載均衡設備通過報文中的應用層信息(URL、HTTP頭部等信息)和負載均衡算法,選擇到達目的的內部服務器。七層負載均衡可以“智能化”地篩選報文中 應用層信息,然後根據不同的信息進行特定的負載均衡調度。這種方式提升了應用系統在網絡層上的靈活性,另外也在一定程度上提升了後端系統的安全性。因爲像網絡常見的DoS攻擊,這些攻擊在七層負載均衡的環境下通常都在負載均衡設備上就截止了,不會影響到後臺服務器的正常運行。

(2)HAproxy、nginx與Lvs的對比

前網絡中常見的負載均衡主要分爲硬件負載均衡和軟件負載均衡。硬件負載均衡比較知名的產品有F5 Big-IP、Cirtix Netscaler等等。而軟件負載均衡就有着衆多的開源項目,常見的有Haproxy、nginx、lvs等。
Haproxy:

1、支持兩種代理模式:TCP(四層)和HTTP(七層),支持虛擬主機;
2、能夠補充Nginx的一些缺點比如Session的保持,Cookie的引導等工作
3、支持url檢測後端的服務器出問題的檢測會有很好的幫助。
4、更多的負載均衡策略比如:動態加權輪循(Dynamic Round Robin),加權源地址哈希(Weighted Source Hash),加權URL哈希和加權參數哈希(Weighted Parameter Hash)。
5、單純從效率上來講HAProxy更會比Nginx有更出色的負載均衡速度。
6、HAProxy可以對Mysql進行負載均衡,對後端的DB節點進行檢測和負載均衡。
9、支持負載均衡算法:Round-robin(輪循)、Weight-round-robin(帶權輪循)、source(原地址保持)、RI(請求URL)、rdp-cookie(根據cookie)
10、不能做Web服務器即Cache。

lvs:

1、抗負載能力強、性能高,能達到F5硬件的60%;對內存和cpu資源消耗比較低
2、工作在網絡4層,通過vrrp協議轉發(僅作分發之用),具體的流量由linux內核處理,因此沒有流量的產生。
2、穩定性、可靠性好,自身有完美的熱備方案;(如:LVS+Keepalived)
3、應用範圍比較廣,可以對所有應用做負載均衡;
4、不支持正則處理,不能做動靜分離。
5、支持負載均衡算法:rr(輪循)、wrr(帶權輪循)、lc(最小連接)、wlc(權重最小連接)
6、配置 複雜,對網絡依賴比較大,穩定性很高。

nginx:

1、工作在網絡的7層之上,可以針對http應用做一些分流的策略,比如針對域名、目錄結構;
2、Nginx對網絡的依賴比較小,理論上能ping通就就能進行負載功能;
3、Nginx安裝和配置比較簡單,測試起來比較方便;
4、可以承擔高的負載壓力且穩定,一般能支撐超過1萬次的併發;
5、對後端服務器的健康檢查,只支持通過端口來檢測,不支持通過url來檢測。
6、Nginx對請求的異步處理可以幫助節點服務器減輕負載;
7、Nginx僅能支持http、https和Email協議,這樣就在適用範圍較小。
8、不支持Session的直接保持,但能通過ip_hash來解決。、對Big request header的支持不是很好,
9、支持負載均衡算法:Round-robin(輪循)、Weight-round-robin(帶權輪循)、Ip-hash(Ip哈希)
10、Nginx還能做Web服務器即Cache功能

2、簡述Haproxy常見的負載均衡調度算法及應用場景詳解

roundrobin:基於權重進行輪詢,此算法是動態的,其權重可以在運行時進行調整。
static-rr:基於權重進行輪詢,與roundrobin類似,但是爲靜態方法,在運行時調整其服務器權重不會生效。
leastconn:新的連接請求被派發至具有最少連接數目的後端服務器,動態算法,適用於較長時間會話的場景。
source:將請求的源地址進行hash運算,並與後端服務器的總權重作取模運算後調度至某臺服務器;同一IP地址的請求將始終被調度至某特定的服務器,靜態算法,可以使用hash-type修改此特性;
uri:對URI的左半部分(“?”之前的部分)或整個URI進行hash運算,並與後端服務器的總權重作取模運算後調度至某臺服務器;同一URI的請求將始終被調度至某特定的服務器,靜態算法,可以使用hash-type修改此特性;
hdr(<name>):根據用戶請求報文中指定的http首部的值進行調度,常用於實現將對同一個虛擬主機的請求始終發往同個backend server。

3、通過Haproxy的ACL規劃實現智能負載均衡,並簡述tcp、http、health的配置示例

Haproxy可以做代理服務相對於nginx而言有很多相同之處,統一可以基於mode tcp進行四層代理也可以基於mode http進行七層代理,但不同的是其無法使用location和if等進行匹配判斷。突出優勢在於有會話綁定,web管理界面,狀態統計非常詳細。官方推薦只啓用一個進程,相對於nginx多進程架構工作並不理想,更多的線程可能會受到系統內存的一些限制。
程序環境:
主程序:/usr/sbin/haproxy
主配置文件:/etc/haproxy/haproxy.cfg
Unit file:/usr/lib/systemd/system/haproxy.service

    配置段:
        global:全局配置段
            進程及安全配置相關的參數
            性能調整相關參數
            Debug參數
        proxies:代理配置段
            defaults:爲frontend, listen, backend提供默認配置;
            frontend:前端,相當於nginx, server {}
            backend:後端,相當於nginx, upstream {}
            listen:同時擁前端和後端

查看配置文件

global
    log         127.0.0.1 local2
    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    maxconn     4000
    user        haproxy
    group       haproxy
    daemon

    # turn on stats unix socket
    stats socket /var/lib/haproxy/stats

重要的幾個參數,及性能調優,多數無需修改

    log:定義全局的syslog服務器;最多可以定義兩個;
    log <address> [len <length>] <facility> [max level [min level]]
    nbproc <number>:要啓動的haproxy的進程數量;
    ulimit-n <number>:每個haproxy進程可打開的最大文件數;
    maxconn <number>:設定每個haproxy進程所能接受的最大併發連接數;
         最大的併發連接數=nbproc * maxconn
    maxconnrate <number>:每個進程每秒種所能創建的最大連接數量;
    maxcomprate :壓縮創建的速率
    maxsessrate <number>:進程每秒能創建的會話數量
    maxsslconn <number>:每個進程所能接受的ssl連接數
    spread-checks <0..50, in percent>:散開監控狀態檢測

發現日誌發送給本機rsyslog的local2的facility,而本機的rsyslog裏並沒有定義,需要我們自己去配置
所以vim /etc/rsyslog.conf添加一段將local2的所有信息記錄在對應日誌文件中

# Provides UDP syslog reception
$ModLoad imudp
$UDPServerRun 514
local2.*              /var/log/haproxy.log

ACL規則

由於HAProxy可以工作在七層模型下,因此,要實現HAProxy的強大功能,一定要使用強大靈活的ACL規則,通過ACL規則可以實現基於HAProxy的智能負載均衡系統。HAProxy通過ACL規則完成兩種主要的功能,分別是:
1)通過設置的ACL規則檢查客戶端請求是否合法。如果符合ACL規則要求,那麼將放行;如果不符合規則,則直接中斷請求。
2)符合ACL規則要求的請求將被提交到後端的backend服務器集羣,進而實現基於ACL規則的負載均衡。HAProxy中的ACL規則經常使用在frontend段中,使用方法如下:
acl 自定義的acl 名稱 acl 方法 -i [ 匹配的路徑或文件] 其中:
·acl:是一個關鍵字,表示定義ACL規則的開始。後面需要跟上自定義的ACL名稱。
·acl方法:這個字段用來定義實現ACL的方法,HAProxy定義了很多ACL方法,經常使用的方法有hdr_reg(host)、hdr_dom(host)、hdr_beg(host)、url_sub、url_dir、path_beg、path_end等。
·-i:表示不區分大小寫,後面需要跟上匹配的路徑或文件或正則表達式。與ACL規則一起使用的HAProxy參數還有use_backend,use_backend後面需要跟上一個backend實例名,表示在滿足ACL規則後去請求哪個backend實例,與use_backend對應的還有default_backend參數,它表示在沒有滿足ACL條件的時候默認使用哪個後端

acl www_policy  hdr_reg(host)  -i  ^(www.z.cn|z.cn) 
acl bbs_policy  hdr_dom(host)  -i  bbs.z.cn
acl url_policy  url_sub       -i          buy_sid=
use_backend  server_www       if         www_policy 
use_backend  server_app     if        url_policy 
use_backend  server_bbs     if          bbs_policy 
default_backend  server_cache

這些例子定義了www_policy、bbs_policy、url_policy三個ACL規則,第一條規則表示如果客戶端以www.z.cnz.cn開頭的域名發送請求時,則此規則返回true,同理第二條規則表示如果客戶端通過bbs.z.cn域名發送請求時,則此規則返回true,而第三條規則表示如果客戶端在請求的URL中包含“buy_sid=”字符串時,則此規則返回true。
第四、第五、第六條規則定義了當www_policy、bbs_policy、url_policy三個ACL規則返回true時要調度到哪個後端backend,例如,當用戶的請求滿足www_policy規則時,那麼HAProxy會將用戶的請求直接發往名爲server_www的後端backend,其他以此類推。而當用戶的請求不滿足任何一個ACL規則時,HAProxy就會把請求發往由default_backend選項指定的server_cache這個後端backend。

acl host_www        hdr_beg(host) -i www 
acl host_static   hdr_beg(host) -i img. video. download. ftp. 
use_backend static    if host_static || host_www url_static 
use_backend www         if host_www 
default_backend            server_cache

與上面的例子類似,本例中也定義了url_static、host_www和host_static三個ACL規則,其中,第一條規則通過path_end參數定義瞭如果客戶端在請求的URL中以.gif、.png、.jpg、.css或.js結尾時返回true,第二條規則通過hdr_beg(host)參數定義瞭如果客戶端以www開頭的域名發送請求時則返回true,同理,第三條規則也是通過hdr_beg(host)參數定義瞭如果客戶端以img.、video.、download.或ftp.開頭的域名發送請求時則返回true。
第四、第五條規則定義了當滿足ACL規則後要調度到哪個後端backend,例如,當用戶的請求同時滿足host_static規則與url_static規則,或同時滿足host_www和url_static規則時,那麼會將用戶請求直接發往名爲static的後端backend,如果用戶請求滿足host_www規則,那麼請求將被調度到名爲www的後端backend,如果不滿足所有規則,那麼將用戶請求默認調度到名爲server_cache的這個後端backend。

global部分

log:全局的日誌配置,local0是日誌設備,info表示日誌級別。其中日誌級別有err、warning、info、debug4種可選。這個配置表示使用127.0.0.1上的rsyslog服務中的local0日誌設備,記錄日誌等級爲info。

maxconn:設定每個HAProxy進程可接受的最大併發連接數,此選項等同於Linux命令行選項“ulimit -n”。

user/group:設置運行HAProxy進程的用戶和組,也可使用用戶和組的uid和gid值來替代。

daemon:設置HAProxy進程進入後臺運行。這是推薦的運行模式。

nbproc:設置HAProxy啓動時可創建的進程數,此參數要求將HAProxy運行模式設置爲daemon,默認只啓動一個進程。該值的設置應該小於服務器的CPU核數。創建多個進程,能夠減少每個進程的任務隊列,但是過多的進程可能會導致進程崩潰。

pidfile:指定HAProxy進程的pid文件。啓動進程的用戶必須有訪問此文件的權限。

defaults部分

mode:設置HAProxy實例默認的運行模式,有tcp、http、health三個可選值。

  • TCP模式:在此模式下,客戶端和服務器端之間將建立一個全雙工的連接,不會對七層報文做任何類型的檢查,默認爲tcp模式,經常用於SSL、SSH、SMTP等應用。
  • http模式:在此模式下,客戶端請求在轉發至後端服務器之前將會被深度分析,所有不與RFC格式兼容的請求都會被拒絕。
  • health模式:目前此模式基本已經廢棄,不再多說。

retries:設置連接後端服務器的失敗重試次數,如果連接失敗的次數超過這裏設置的值,HAProxy會將對應的後端服務器標記爲不可用。此參數也可在後面部分進行設置。

timeout connect:設置成功連接到一臺服務器的最長等待時間,默認單位是毫秒,但也可以使用其他的時間單位後綴。

timeout client:設置連接客戶端發送數據時最長等待時間,默認單位是毫秒,也可以使用其他的時間單位後綴。

timeout server:設置服務器端迴應客戶端數據發送的最長等待時間,默認單位是毫秒,也可以使用其他的時間單位後綴。

timeout check:設置對後端服務器的檢測超時時間,默認單位是毫秒,也可以使用其他的時間單位後綴。

frontend部分

bind:此選項只能在frontend和listen部分進行定義,用於定義一個或幾個監聽的套接字。bind的使用格式爲: bind [<address>:<port_range>] interface <interface>其可以爲主機名或IP地址,如果將其設置爲“*”或“0.0.0.0”,將監聽當前系統的所有IPv4地址。port_range可以是一個特定的TCP端口,也可是一個端口範圍,小於1024的端口需要有特定權限的用戶才能使用。interface爲可選選項,用來指定網絡接口的名稱,只能在Linux系統上使用。

option httplog:在默認情況下,HAProxy日誌是不記錄HTTP請求的,這樣很不方便HAProxy問題的排查與監控。通過此選項可以啓用日誌記錄HTTP請求。

option forwardfor:如果後端服務器需要獲得客戶端的真實IP,就需要配置此參數。由於HAProxy工作於反向代理模式,因此發往後端真實服務器的請求中的客戶端IP均爲HAProxy主機的IP,而非真正訪問客戶端的地址,這就導致真實服務器端無法記錄客戶端真正請求來源的IP,而X-Forwarded-For則可用於解決此問題。通過使用forwardfor選項,HAProxy就可以向每個發往後端真實服務器的請求添加X-Forwarded-For記錄,這樣後端真實服務器日誌可以通過“X-Forwarded-For”信息來記錄客戶端來源IP。

option httpclose:此選項表示在客戶端和服務器端完成一次連接請求後,HAProxy將主動關閉此TCP連接。這是對性能非常有幫助的一個參數。

log global:表示使用全局的日誌配置,這裏的global表示引用在HAProxy配置文件global部分中定義的log選項配置格式。

default_backend:指定默認的後端服務器池,也就是指定一組後端真實服務器,而這些真實服務器組將在backend段進行定義。這裏的htmpool就是一個後端服務器組。

backend部分

option redispatch:此參數用於cookie保持的環境中。在默認情況下,HAProxy會將其請求的後端服務器的serverID插入cookie中,以保證會話的session持久性。而如果後端的服務器出現故障,客戶端的cookie是不會刷新的,這就會出現問題。此時,如果設置此參數,就會將客戶的請求強制定向到另外一臺健康的後端服務器上,以保證服務正常。

option abortonclose:如果設置了此參數,可以在服務器負載很高的情況下,自動結束當前隊列中處理時間比較長的連接。
-balance:此關鍵字用來定義負載均衡算法。目前HAProxy支持多種負載均衡算法,常用的有如下幾種:

  • roundrobin:是基於權重進行輪叫調度的算法,在服務器的性能分佈比較均勻時,這是一種最公平、最合理的算法。此算法使用頻繁。
  • static-rr:也是基於權重進行輪叫的調度算法,不過此算法爲靜態方法,在運行時調整其服務器權重不會生效。
  • source:是基於請求源IP的算法。此算法先對請求的源IP進行hash運算,然後將結果與後端服務器的權重總數相除後轉發至某臺匹配的後端服務器。這種方式可以使同一個客戶端IP的請求始終被轉發到某特定的後端服務器。
  • leastconn:此算法會將新的連接請求轉發到具有最少連接數目的後端服務器。在會話時間較長的場景中推薦使用此算法,例如數據庫負載均衡等。此算法不適合會話較短的環境中,例如基於HTTP的應用。
  • uri:此算法會對部分或整個URI進行hash運算,再經過與服務器的總權重相除,最後轉發到某臺匹配的後端服務器上。
  • uri_param:此算法會根據URL路徑中的參數進行轉發,這樣可保證在後端真實服務器數量不變時,同一個用戶的請求始終分發到同一臺機器上。
  • hdr(<name>):此算法根據http頭進行轉發,如果指定的http頭名稱不存在,則使用roundrobin算法進行策略轉發。

cookie:表示允許向cookie插入SERVERID,每臺服務器的SERVERID可在下面的server關鍵字中使用cookie關鍵字定義。

option httpchk:此選項表示啓用HTTP的服務狀態檢測功能。HAProxy作爲一個專業的負載均衡器,它支持對backend部分指定的後端服務節點的健康檢查,以保證在後端backend中某個節點不能服務時,把從frotend端進來的客戶端請求分配至backend中其他健康節點上,從而保證整體服務的可用性。
option httpchk的用法如下: option httpchk <method> <uri> <version> 其中,各個參數的含義如下:

  • method:表示HTTP請求的方式,常用的有OPTIONS、GET、HEAD幾種方式。一般的健康檢查可以採用HEAD方式進行,而不是採用GET方式,這是因爲HEAD方式沒有數據返回,僅檢查Response的HEAD是不是狀態碼200。因此,相對於GET,HEAD方式更快、更簡單。
  • uri:表示要檢測的URL地址,通過執行此URL,可以獲取後端服務器的運行狀態。在正常情況下將返回狀態碼200,返回其他狀態碼均爲異常狀態。
  • version:指定心跳檢測時的HTTP的版本號。
    server:這個關鍵字用來定義多臺後端真實服務器,不能用於defaults和frontend部分。使用格式爲: server <name> <address>[:port] [param*] 其中,每個參數含義如下:
  • <name>:爲後端真實服務器指定一個內部名稱,隨便定義一個即可。
  • <address>:後端真實服務器的IP地址或主機名。
  • <port>:指定連接請求發往真實服務器時的目標端口。在未設定時,將使用客戶端請求時的同一端口。
  • [param*]:爲後端服務器設定的一系列參數,可用參數非常多,這裏僅介紹常用的一些參數:

check:表示啓用對此後端服務器執行健康狀態檢查。

inter:設置健康狀態檢查的時間間隔,單位爲毫秒。

rise:設置從故障狀態轉換至正常狀態需要成功檢查的次數,例如,“rise 2”表示2次檢查正確就認爲此服務器可用。

fall:設置後端服務器從正常狀態轉換爲不可用狀態需要檢查的次數,例如,“fall 3”表示3次檢查失敗就認爲此服務器不可用。

cookie:爲指定的後端服務器設定cookie值,此處指定的值將在請求入站時被檢查,第一次爲此值挑選的後端服務器將在後續的請求中一直被選中,其目的在於實現持久連接的功能。上面的“cookie server1”表示web1的serverid爲server1。同理,“cookie server2”表示web2的serverid爲server2。

weight:設置後端真實服務器的權重,默認爲1,最大值爲256。設置爲0表示不參與負載均衡。

backup:設置後端真實服務器的備份服務器,僅僅在後端所有真實服務器均不可用的情況下才啓用。

通過ACL智能負載均衡動靜分離

rontend web *:80
   compression algo gzip
   compression type text/html text/plain /application/xml application/javascript
   acl static path_end .jpg .jpeg.png .gif .txt .html .css .javascript .
js  #定義靜態acl匹配規則,後綴匹配
   acl static path_beg /imgs /css /javascripts #定義靜態acl匹配規則,前綴匹配
   use_backend staticsrvs if static  #使用靜態acl匹配規則
   default_backend dynsrvs #未匹配到acl的,使用默認後端主機,動態內容

backend dynsrvs   #動態主機組
   cookie SRV insert indirect nocache #啓用cookie綁定
   server dynsrv1 192.168.31.204:80 check cookie dynsrv1

backend staticsrvs  #靜態主機組
   server staticsrv1 192.168.31.203:80 check               

listen stats
   bind *:9099
   stats enable
   stats uri /myproxy?admin #自定義信息頁地址
   stats realm "HAProxy Stats Page" #認證提示
   stats auth admin:admin #認證時用的用戶名和密碼
   stats admin if TRUE  #啓用信息頁管理功能,總是爲真

13920922-b8a7e1984fa61855.png
image.png

4、LNMT實現動靜分離實戰

用nginx反代後端的兩臺tomcat主機,做動靜分離,如果是jsp結尾的就發往後端,否則就交給nginx處理。
在兩臺tomcat主機上創建應用

mkdir -pv /var/lib/tomcat/webapps/test/{WEB-INF,META-INF,calsses,lib}
然後創建應用程序jsp文件
在A主機上
 
            <%@ page language="java" %>
                    <html>
                        <head><title>TomcatA</title></head>
                        <body>
                            <h1><font color="red">TomcatA.magedu.com</font></h1>
                            <table align="centre" border="1">
                                <tr>
                                    <td>Session ID</td>
                                <% session.setAttribute("magedu.com","magedu.com"); %>
                                    <td><%= session.getId() %></td>
                                </tr>
                                <tr>
                                    <td>Created on</td>
                                    <td><%= session.getCreationTime() %></td>
                                </tr>
                            </table>
                        </body>
                    </html>
 
在B主機上
            <%@ page language="java" %>
                    <html>
                        <head><title>TomcatB</title></head>
                            <body>
                            <h1><font color="blue">TomcatB.magedu.com</font></h1>
                            <table align="centre" border="1">
                                <tr>
                                    <td>Session ID</td>
                                <% session.setAttribute("magedu.com","magedu.com"); %>
                                    <td><%= session.getId() %></td>
                                </tr>
                                <tr>
                                    <td>Created on</td>
                                    <td><%= session.getCreationTime() %></td>
                                </tr>
                            </table>
                            </body>
                    </html> 
 
13920922-7d91ac344233066c.png
image.png

13920922-dcaea6e25ed88310.png
image.png

nginx配置

upstream tcservs {
        hash $request_uri consistent; #使用uri一致性哈希算法保持會話粘性
        #hash $cookie_name consistent 對cookie做哈希也可以
        server 192.168.31.203:8080;
        server 192.168.31.204:8080;
    }
vim /etc/nginx/conf.d/lvqin.conf
server {
        listen 80;
        server_name node1.lvqing.com;
 
          location ~* \.(jsp|do)$ {
                     proxy_pass http://tcservs;
         }
}          
13920922-97478cba021fe5b8.png
image.png

13920922-52dcccfd7303b8c2.png
image.png

則動靜分離就實現了,並且我們還基於uri實現了會話粘性

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章