HAProxy 是一款高性能TCP/HTTP 反向代理負載均衡服務器,具備以下功能:html
根據靜態分配的cookies完成HTTP請求轉發前端
在多個服務器間實現負載均衡,而且根據HTTP cookies 實現會話粘性mysql
主備服務器切換nginx
接受訪問特定端口實現服務監控git
實現平滑關閉服務,不中斷已創建鏈接的請求響應,拒絕新的請求github
在請求或響應HTTP報文中添加,修改,或刪除首部信息web
根據正則規則阻斷請求正則表達式
提供帶有用戶認證機制的服務狀態報告頁面算法
HAProxy特別適用於那些負載特大的web站點,這些站點一般又須要會話保持或七層處理。HAProxy運行在時下的硬件上,徹底能夠支持數以萬計的 併發鏈接。而且它的運行模式使得它能夠很簡單安全的整合進您當前的架構中, 同時能夠保護你的web服務器不被暴露到網絡上。sql
HAProxy 實現了一種事件驅動、單一進程模型,此模型支持很是大的併發鏈接數。多進程或多線程模型受內存限制 、系統調度器限制以及無處不在的鎖限制,不多能處理數千併發鏈接。事件驅動模型由於在有更好的資源和時間管理的用戶端(User-Space) 實現全部這些任務,因此沒有這些問題。此模型的弊端是,在多核系統上,這些程序一般擴展性較差。這就是爲何他們必須進行優化以 使每一個CPU時間片(Cycle)作更多的工做。
HAProxy實際工做中,它佔用用戶空間時間要比內核運行時間少20倍,因此對系統參數調優是十分必要的一項工做。
另外衡量一個負載均衡服務器主要考量三個指標
session rate
此項指標很是重要,它決定了一個load balancer 能不能分發全部接受的請求。這項指標一般是由CPU性能決定。測量指標的大小跟傳輸的每一個對象的大小有關,一般用空對象來測試,Session rates 在 100,000 sessions/s 左右,使用 Xeon E5 在 2014測試。
session concurrency
該指標與前一指標相關聯。這一指標與服務器內存和系統能夠處理的文件描述符數量有關。 一般每一個session佔用34KB,即大概3W個session佔用1GB內存空間,實際上,socket buffer也會佔用內存空間,2W個session socket佔用1GB內存。
data forwarding rate
這一指標與 session rate 相對立,它的衡量單位一般是 Megabytes/s (MB/s), 或者 Gigabits/s (Gbps)。傳輸較大的對象有利於該指標的提高,由於較大的對象傳輸能夠減小session創建和關閉浪費的時間。而測量session rate 則在傳輸小對象時有利於指標提高。haproxy 在2014年使用 Xeon E5 測試成績爲40 Gbps。
本文環境:CentOS7.2 haproxy 1.5 經過yum 安裝
程序環境: 配置文件:/etc/haproxy/haproxy.cfg Unit File: haproxy.service 主程序:/usr/sbin/haproxy 配置文件: global:全局配置段 進程及安全配置相關的參數 性能調整相關的參數 Debug相關的參數 proxies:代理配置段 defaults:爲frontend, backend以及listen提供默認配置; frontend:前端,至關於Nginx中的server{ ... }; backend:後端,至關於nginx中的upstream { ... }; listen:先後端的直接組合; **關於前端與後端的關係:一個前端能夠指向多個後端;同時一個後端能夠被多個調用。
定義日誌系統相關屬性
log <address> [len <length>] <facility> [max level [min level]]
harpoxy 將日誌發送到指定的rsyslog服務器,在本地記錄也要開啓rsyslog服務;
全局端最多可配置兩個log 服務器;
< address> :日誌服務器地址
[ len ] 指定記錄的日誌最大長度
定義運行用戶,所屬組
username
group groupname
運行方式
意味着後臺守護進程
maxconn <number>:設定單haproxy進程的最大併發鏈接數; maxconnrate <number>:設定單haproxy進程每秒接受的鏈接數; maxsslconn <number>:設定單haproxy進程的ssl鏈接最大併發鏈接數; maxsslrate <number>:單haproxy進程的ssl鏈接的建立速率上限; spread-checks <0..50, in percent>:避免對於後端檢測同時併發形成 的問題,設置錯開時間比,範圍0到50,通常設置2-5較好。
用於對haproxy 狀態監控頁面的用戶認證。至少要定義一個用戶列表而且添加一個用戶
密碼能夠加密或明文。
Example:
userlist L1 group G1 users tiger,scott group G2 users xdb,scott user tiger password $6$k6y3o.eP$JlKqe4(...)xHSwRv6J.C0/D7cV91 user scott insecure-password elgato user xdb insecure-password hello userlist L2 group G1 group G2 user tiger password $6$k6y3o.eP$JlKBx(...)xHSwRv6J.C0/D7cV91 groups G1 user scott insecure-password elgato groups G1,G2 user xdb insecure-password hello groups G2
這部分配置在下列定義區域下使用
- defaults < name > - frontend < name > - backend < name > - listen < name >
「defaults」 區域定義了frontend,backend,listen 的默認參數
「frontend「 區域描述了接收客戶端請求的監聽配置
」backend「 區域描述接受請求處理的後端服務器配置
」listen「 區域描述一組前端和後端直接一對一綁定的組配置
HAProxy 配置的關鍵字與區域限制特性,即有些關鍵字在某個區域不可使用
下面開始講解關鍵字的用法
1. bind [<address>]:<port_range> [, ...] [param*]
僅在frontend和listen區域使用。定義服務監聽端口地址等參數
[ param* ] 參數根據系統而定,通常不須要指定
example:
bind :80 #監聽本機全部IP的80端口 bind *:80 #監聽本機全部IP的80端口 bind 192.168.12.1:8080,10.1.0.12:8090
2. mode {tcp|http|health}
tcp:基於layer4實現代理,可代理大多數基於tcp的應用層協議,例如ssh/mysql/pgsql等;
http:客戶端的http請求會被深度解析;
health:工做爲健康狀態檢查響應模式,當請求到達時僅迴應「OK」即斷開鏈接;
3. balance <algorithm> [ <arguments> ] balance url_param <param> [check_post]
在backend區域定義調度算法
< algorithm > 以下:
roundrobin
帶有權重的輪詢調度算法; server後面使用weight來定義權重; 動態算法:支持權重的運行時調整,支持慢啓動(緩慢接收大量請求在剛啓動時);僅支持最大4095個後端活動主機
static-rr
靜態的roundrobin算法;
不支持權重的運行時調整及慢啓動;但後端主機數量無限制;
leastconn
帶權重的最少鏈接分配動態算法;
適用長鏈接應用協議,如ssh等
first
第一優先算法;
若是第一個服務端可接受請求則老是把鏈接分配給它,直到第一個服務端處於繁忙,分配給下一個,順序按服務端的數字ID從小到大排列
source
源IP hash 算法;
該算法保證在後端服務器組沒有減小或增長的狀況下,能未來自同一客戶端IP的請求分配至同一個服務端;
該算法適合在沒法使用cookie插入的TCP模式下使用
動態算法或靜態算法取決於hash-type;
uri
uri hash 算法;
該算法hash uri 的查詢標記的左側部分,或者指定whole 參數時hash所有uri;
該算法保證訪問同一uri的請求分配至同一服務端,適用於後端爲緩存服務器的狀況,以提升緩存命中率;
動態算法或靜態算法取決於hash-type;
另外:該算法支持追加參數[ < arguments > ]:
(1) whole :hash完整uri
(2) len number:hash指定uri的長度
(3) depth nubmer:hash指定目錄深度,每一個"/"表明一個深度
uri_param
param hash 算法;
對用戶請求的url中的< param >部分中的指定的參數的值(uri中"="部分)做hash計算;
該算法適用於有用戶識別參數的uri ,它保證同一user id 的請求分配至同一服務端;
若果check_post 標識啓用,則在uri中沒有找到"?"參數時,對HTTP Post 請求實體查找參數聲明;
動態算法或靜態算法取決於hash-type;
Example:
balance url_param userid balance url_param session_id check_post 64
hdr(< name >)
HTTP 首部字段hash算法;
指定的http首部將會被取出作hash計算。若是沒有值,則降至輪詢調度;
動態算法或靜態算法取決於hash-type;
4. hash_type < method >
在balance 指令中選定與hash 有關的算法,都會受此影響。
默認採起的方法爲map-based
< method > 以下:
map-based:取模法,hash數據結構是靜態數組;
該hash是靜態的,不支持在線調整權重,不支持慢啓動;
該算法調度平滑,後端服務器可以均勻承受負載;
缺點也是明顯的:當服務器的總權重發生變化時,即有服務器上線或下線,都會致使調度結果總體改變。若是想避免此種狀況應採用consistent 方法;
consistent:一致性哈希,哈希的數據結構是「樹」;
該hash是動態的,支持在線調整權重,支持慢啓動
每個server 會在"樹"中出現屢次, 在樹中查找hash key,並選擇最近的server;
該方法的優勢在於,當服務器的總權重發生變化時,對調度結果影響是局部的,不會引發大的變更。因此十分適合緩存服務器;
缺點:該算法不夠平滑,很容易致使後端服務器負載不均衡。因此頗有必要對服務器的權重以或者服務器ID進行調整;
爲保持均勻負載,應該保證全部服務器ID保持一致;
5. server <name> <address>[:[port]] [param*] default-server [param*]
server用於在backend和listen中定義一個主機;
default-server 用於設定server的默認參數;
[param*] 以下:
weight < weight >:當前server的權重;
id < number > :設定server ID
cookie < value >:爲當前server指定其cookie值,此值會在收到請求報文時進行檢測,其功能在於實現基於cookie會話保持;
check:對當前server進行健康狀態檢測;
inter < delay >:時間間隔;
rise < count >:斷定爲「健康」狀態須要檢測的次數,默認2;
fall < count >:斷定爲「不健康」狀態須要檢測的次數,默認3;
addr <ipv4|ipv6>:健康狀態檢測時使用的地址;
port < port >:健康狀態檢測時使用的端口;
注意:默認爲傳輸層檢測,即探測端口是否能響應;須要執行應用層檢測,則須要httpchk, smtpchk, mysql-check, pgsql-check, ssl-hello-chk;
maxconn <maxconn>:當前server的最大併發鏈接數;
maxqueue <maxqueue>:當前server的等待隊列的最大長度;
disabled:將主機標記爲不可用;
redir <prefix>:將發往當前server的全部請求GET和HEAD類的請求均重定向至指定的URL;
Examples : server first 10.1.1.1:1080 id 3 cookie first check inter 1000 maxconn 10000 maxqueue 2000 server second 10.1.1.2:1080 id 4 cookie second check inter 1000
6. option httpchk option httpchk <uri> option httpchk <method> <uri> option httpchk <method> <uri> <version>
基於http協議做7層健康狀態檢測機制,默認是基於tcp層進行檢測;
TCP 模式也可使用該檢測機制
< method > < uri > < version >:請求報文的超始行;
method 默認方法爲 OPTIONS;返回狀態碼2XX,3XX意味成功;
Examples : # Relay HTTPS traffic to Apache instance and check service availability # using HTTP request "OPTIONS * HTTP/1.1" on port 80. backend https_relay mode tcp option httpchk OPTIONS /index.html HTTP/1.1\r\nHost:\ www server apache1 192.168.1.1:443 check port 80
7. http-check expect [!] <match> <pattern>
定義檢測有效指望值;
! 表示認定的錯誤值;< match > 可取值爲:
status < string >
rstatus < regex > 正則方式
string < string >
rstring < regex >
Examples : # only accept status 200 as valid http-check expect status 200 # consider SQL errors as errors http-check expect ! string SQL\ Error # consider status 5xx only as errors http-check expect ! rstatus ^5 # check that we have a correct hexadecimal tag before /html http-check expect rstring <!--tag:[0-9a-f]*</html>
8. cookie <name> [ rewrite | insert | prefix ] [ indirect ] [ nocache ] [ postonly ] [ preserve ] [ httponly ] [ secure ] [ domain <domain> ]* [ maxidle <idle> ] [ maxlife <life> ]
啓用基於cookie的會話黏性,要結合server指定的cookie參數一塊兒實現;
經常使用形式:cookie WEBSRV insert nocache indirect
Example: backend websrvs balance roundrobin cookie WEBSRV insert nocache indirect server web1 10.1.0.68:80 check weight 2 maxconn 5000 cookie web1 server web2 10.1.0.69:80 check weight 1 maxconn 3000 cookie web2
9. default_backend <backend>
當use_backend 的使用規則沒有被匹配時,由default_backend 指定默認服務器組;
關於use_backend 使用後續會在acl 章節中講解;
爲frontend或backend定義日誌記錄機制;
log global :使用全局定義的日誌記錄方式 log <address> [len <length>] <facility> [<level> [<minlevel>]]:自定義 no log :不記錄 capture request header <name> len <length> -->記錄請求報文中的指定的首部的值於日誌中;len用於指定要記錄的信息的長度; capture response header <name> len <length> -->記錄響應報文中的指定的首部的值於日誌中;len用於指定要記錄的信息的長度; 示例: capture request header Referer len 30
- errorfile <code> <file>
< code > 指定HTTP返回的狀態碼。200, 400, 403, 408, 500, 502, 503, and 504 可以使用;
< file > 指定一個文件代替HTTP響應;
Example:errorfile 503 /etc/haproxy/errorfiles/503sorry.http
- errorloc <code> <url> - errorloc302 <code> <url>
發生錯誤時由haproxy重定向至指定url,以上兩個命令等同,響應狀態碼爲302
Example:errorloc 503 http://www.mydomain.com/index...
- errorloc303 <code> <url>
響應狀態碼爲303,表示以GET方法從新請求頁面
option forwardfor [ except <network> ] [ header <name> ] [ if-none ]
HAProxy把請求報文發日後端主機以前在請求報文添加「X-Forwared-For」首部
目的爲使後端服務器可記錄發出請求客戶端的IP地址
[ except < network> ] :選擇排除的網絡地址
[ header < name> ] :不使用X-Forwared-For,自定義名稱
[ if-none ]:有時請求原來帶有該字段,此時再也不更改
Example:option forwardfor if-none
reqadd <string> [{if | unless} <cond>] rspadd <string> [{if | unless} <cond>]
在HTTP請求或響應首部內容尾部添加值
Example:rspadd X-Via: HAProxy/1.5
reqdel <search> [{if | unless} <cond>] reqidel <search> [{if | unless} <cond>] (不區分大小寫)
刪除HTTP請求中正則匹配的全部首部
rspdel <search> [{if | unless} <cond>] rspidel <search> [{if | unless} <cond>] (不區分大小寫)
刪除HTTP響應中正則匹配的全部首部。屬於安全增強策略,刪除一些服務器版本信息,防止針對攻擊
Example:rspidel Server.*
timeout client <timeout>
設定客戶端最大非活動時長, 默認單位是ms;最好與timeout server一致
timeout server <timeout>
設定服務端最大非活動時長, 默認單位是ms;
timeout connect <timeout>
設定最大與服務端創建鏈接的時長
timeout http-keep-alive <timeout>
設定最大等待新請求的空閒時長,默認單位爲ms;
timeout client-fin <timeout>
在客戶端側設定半關閉鏈接非活動超時
timeout server-fin <timeout>
在服務端側設定半關閉鏈接非活動超時
Example:
defaults http timeout connect 5s timeout client 30s timeout server 30s timeout client-fin 10s timeout http-keep-alive 500
Haproxy 可以從請求報文,響應報文,從客戶端或者服務端信息,從表,環境信息等等中提取數據。提取這樣的數據的動做咱們稱之爲獲取樣本。進行檢索時,這些樣本能夠用來實現各類目的,好比做爲粘滯表的鍵,最經常使用的用途是,根據預約義的模式來進行匹配。
訪問控制列表(ACL)提供一個靈活方案進行內容切換,或者在從請求,響應,任何環境狀態中提取的數據基礎之上作出決策。控制列表的原則很簡單:
從數據流,表,環境中提取數據樣本
對提取的樣本可選地應用格式轉換
對一個樣本應用一個或多個模式匹配
當模式匹配樣本時才執行動做
執行的動做一般是阻斷請求,選擇一個後端服務器或者添加一個HTTP首部
須要提醒的是,獲取的樣本數據不光可使用在acl中,也可使用別處,例如記錄log中
定義ACL的語法爲:
acl <aclname> <criterion> [flags] [operator] [<value>] ...
這樣一條語句創建了一個acl 測試;
這些測試應用在請求或響應中被"標準"< criterion > 部分所指定的內容,並且能夠指定[ flags] 進行特性調整,有些< criterion > 支持操做符[operator] 進行運算,同時一些轉換格式的關鍵字能夠跟在< criterion >後面,使用" , "隔開。而值[< value >] 要求被
< criterion > 所支持的數據形式,多個值使用空格分隔。
< criterion > 一般是指獲取樣本方法的名稱。使用一個獲取樣本方法,暗含着其輸出樣本的類型,類型是如下列出的一種:
boolean
integer (signed or unsigned)
IPv4 or IPv6 address
string
data block
ACL引擎匹配數據使用的模式類型以下:
boolean
integer or integer range
IP address / network
string (exact, substring, suffix, prefix, subdir, domain)
regular expression
hex block
ACL flags 可用列表以下:
-i : 忽略大小寫
-f filename : 從文件中載入模式
-m method : 指定模式匹配方法
-n : 禁止DNS解析
-M : -f 載入的文件做爲映射文件使用
-u : 強制ACL的名稱惟一
-- : 強制結束flag結束,避免了字符串中含有的- 引發混淆
其中flag中的 -m 選項可以使用的模式匹配方法以下,須要說明的是有些方法已被默認指定無需聲明,例如int,ip
"found" : 只是用來探測數據流中是否存在指定數據,不進行任何比較
"bool" : 檢查結果返回布爾值。匹配沒有模式,能夠匹配布爾值或整數,不匹配0和false,其餘值能夠匹配
"int" : 匹配整數類型數據;能夠處理整數和布爾值類型樣本,0表明false,1表明true
"ip" : 匹配IPv4,IPv6地址類型數據。該模式僅被IP地址兼容,不須要特別指定
"bin" : 匹配二進制數據
"len" : 匹配樣本的長度的整數值
"str" : 精確匹配,根據字符串匹配文本
"sub" : 子串匹配,匹配文本是否包含子串
"reg" : 正則匹配,根據正則表達式列表匹配文本
"beg" : 前綴匹配,檢查文本是否以指定字符串開頭
"end" : 後綴匹配,檢查文本是否以指定字符串結尾
"dir" : 子目錄匹配,檢查部分文本中以" / "做爲分隔符的內容是否含有指定字符串
"dom" : 域匹配。檢查部分文本中以" . "做爲分隔符的內容是否含有指定字符串
若是獲取樣本值爲整數,數值比較符可以使用,:
eq : true if the tested value equals at least one value
ge : true if the tested value is greater than or equal to at least one value
gt : true if the tested value is greater than at least one value
le : true if the tested value is less than or equal to at least one value
lt : true if the tested value is less than at least one value
想必前面一堆理論性的論述已經把你們搞的暈頭轉向,下面結合獲取樣本方法和訪問控制動做指令具體闡述ACL使用方法
先介紹控制動做指令
layer 4 傳輸層控制指令
tcp-request connection <action> [{if | unless} <condition>]
對tcp請求控制指令
< condition > 即爲ACL定義的訪問控制列表
< action > 經常使用值有 "accept", "reject"
layer 7 應用層控制指令
#阻斷符合ACL的訪問請求 block { if | unless } <condition> #http請求的控制指令 http-request { allow | deny} [ { if | unless } <condition> ]
後端主機調用
#根據條件來調用指定後端 use_backend <backend> [{if | unless} <condition>]
由ACL定義的多個< condition > 組成聯合條件,邏輯符爲
and (默認操做符,可省略)
or (或者使用 "||")
! (取反)
# 與後端創建會話速率,每秒鐘創建的新會話 be_sess_rate([<backend>]) : integer
Example :
# 某後端被請求過於繁忙,則重定向至錯誤頁 mode http acl being_scanned be_sess_rate gt 100 redirect location /denied.html if being_scanned
在傳輸層獲取樣本,一般是TCP/IP 協議的IP和端口,以及創建鏈接速率等等。並且此部分樣本一般用於"tcp-request connection"指令中的規則之中。
dst : ip #目標地址 dst_port : integer src : ip #源地址 src_port : integer
Example:
#阻斷來自非指定IP的訪問8080端口的請求 acl myhost src 10.1.0.200 acl myport dst_port 8080 tcp-request connection reject if !myhost myport
/1
path : string
提取請求url的地址信息,從第一個"/"開始,不包含host,不包含參數
ACL 衍生,即包含了-m 選項中匹配模式方法 :
path : exact string match
path_beg : prefix match
path_dir : subdir match
path_dom : domain match
path_end : suffix match
path_len : length match
path_reg : regex match
path_sub : substring match
Example:
#請求資源爲圖片,則調用圖片服務器後端 acl picture path_end -i .jpg .png .gif use_backend server_pic if picture
/2
url : string
提取URL的所有內容,包含host和參數
ACL 衍生相似,再也不列舉
/3
req.hdr([<name>[,<occ>]]) : string
提取http請求的指定首部字段值,< occ >可指定出現的位置
ACL 衍生 :
hdr([<name>[,<occ>]]) : exact string match hdr_beg([<name>[,<occ>]]) : prefix match hdr_dir([<name>[,<occ>]]) : subdir match hdr_dom([<name>[,<occ>]]) : domain match hdr_end([<name>[,<occ>]]) : suffix match hdr_len([<name>[,<occ>]]) : length match hdr_reg([<name>[,<occ>]]) : regex match hdr_sub([<name>[,<occ>]]) : substring match
Example:
#阻斷火狐瀏覽器發送的請求 acl firefox hdr_reg(User-Agent) -i .*firefox.* block if firefox
/4
method : integer + string
提取請求報文中的請求方法
Example:
#拒絕GET HEAD 方式以外的HTTP請求 acl valid_method method GET HEAD http-request deny if ! valid_method
HAProxy有衆多內建的ACLs,這些ACLs可直接調用,例如
LOCALHOST 匹配來自本地IP的鏈接,127.0.0.1/8
HTTP_1.1 匹配http版本1.1
METH_GET 匹配http請求GET或HEAD方法
TRUE
FALSE
Example:
#拒絕GET HEAD 方式以外的HTTP請求 http-request deny if ! METH_GET
傳送門:官方1.5使用手冊--- EOF ---