1.HAProxy介紹
? HAProxy: 是法國人Willy Tarreau開發(fā)的一個開源軟件,是 一款應(yīng)對客戶端10000以上的同時連接的高性能的TCP
和 HTTP負載均衡器吏够。其功能是用來提供基于cookie持久性, 基于內(nèi)容的交換庶骄,過載保護的高級流量管制扣泊,自動故障切換 句各,
以正則表達式為基礎(chǔ)的標(biāo)題控制運行時間,基于Web的報 表蛹批,高級日志記錄以幫助排除故障的應(yīng)用或網(wǎng)絡(luò)及其他功能
? LB Cluster:
四層:lvs, nginx(stream)仰泻,haproxy(mode tcp)
七層:http: nginx(http), haproxy(mode http), httpd...
? HAProxy:http://www.haproxy.org
? 文檔:https://cbonte.github.io/haproxy-dconv/
● HAProxy是TCP / HTTP反向代理服務(wù)器荆陆,尤其適合于高可用 性環(huán)境
● 可以針對HTTP請求添加cookie,進行路由后端服務(wù)器
● 可平衡負載至后端服務(wù)器集侯,并支持持久連接
● 支持基于cookie進行調(diào)度
● 支持所有主服務(wù)器故障切換至備用服務(wù)器
● 支持專用端口實現(xiàn)監(jiān)控服務(wù)
● 支持不影響現(xiàn)有連接情況下停止接受新連接請求
● 可以在雙向添加被啼,修改或刪除HTTP報文首部
● 支持基于pattern實現(xiàn)連接請求的訪問控制
● 通過特定的URI為授權(quán)用戶提供詳細的狀態(tài)信息
? 版本:1.4 1.5 1.6 1.7 1.8
clipboard.png
2.Haproxy功能
● 支持http反向代理
● 支持動態(tài)程序的反向代理
● 支持基于數(shù)據(jù)庫的反向代理
clipboard1.png
3. HAProxy組成
https://cbonte.github.io/haproxy-dconv/
clipboard2.png
? 程序環(huán)境:
主程序:/usr/sbin/haproxy
配置文件:/etc/haproxy/haproxy.cfg
Unit file:/usr/lib/systemd/system/haproxy.service
? 配置段:
● global:全局配置段
進程及安全配置相關(guān)的參數(shù)
性能調(diào)整相關(guān)參數(shù)
Debug參數(shù)
● proxies:代理配置段
defaults:為frontend, backend, listen提供默認配置
fronted:前端,相當(dāng)于nginx, server {}
backend:后端棠枉,相當(dāng)于nginx, upstream {}
listen:同時擁有前端和后端,適用于一對一環(huán)境 (最好前后端分開浓体,以后
好調(diào)整)
? 簡單的配置示例:
frontend web
bind *:80 綁定所有端口
default_backend websrvs 默認的backend
backend websrvs
balance roundrobin
server srv1 172.16.0.6:80 check
server srv2 172.16.0.7:80 check
haproxy -f haproxy 檢查配置文件
systemctl status haproxy 檢查一下haproxy狀態(tài)
eg:
clipboard3.png
clipboard4.png
clipboard5.png
4.global配置 :
global配置參數(shù):
進程及安全管理:chroot, deamon,user, group, uid, gid
nbproc :要啟動的haproxy的進程數(shù)量辈讶,系統(tǒng) 默認單進程命浴,要求使用daemon模式
ulimit-n :每個haproxy進程可打開的最大文件數(shù),系統(tǒng)自動會指定贱除,不建議設(shè)置
daemon:后端方式運行生闲,建議使用
log:定義全局的syslog服務(wù)器媳溺;最多可以定義兩個
log <address> [len <length>] <facility>[max level [min level]]
address: rsyslog服務(wù)器地址
len: 記錄日志的長度,默認1024 10
5.日志系統(tǒng)
log:
log global
log <address> [len <length>] <facility>[<level>[<minlevel>]]
no log
注意:
默認發(fā)往本機的日志服務(wù)器跪腹;
(1) local2.* /var/log/local2.log
(2)#vim /etc/rsyslog.conf
$ModLoad imudp
$UDPServerRun 514
? log-format <string>:
課外實踐:參考文檔實現(xiàn)combined格式的記錄
記錄日志到本機
clipboard6.png
clipboard7.png
clipboard8.png
clipboard9.png
存放日志到遠程服務(wù)器
clipboard10.png
clipboard11.png
clipboard12.png
clipboard13.png
6.日志管理
將特定信息記錄在日志中
? capture cookie len <name> len <length>
捕獲請求和響應(yīng)報文中的 cookie并記錄日志
? capture request header <name> len <length>
捕獲請求報文中指定的首部并記錄日志
示例: capture request header X-Forwarded-For len
? capture response header <name> len <length>
捕獲響應(yīng)報文中指定的首部并記錄日志
示例: capture response header Content-length len 9
capture response header Location len 15
7.性能調(diào)整
性能調(diào)整:
maxconn <number>:設(shè)定每個haproxy進程所能接受的最大并發(fā)連接數(shù)
maxconnrate <number>:設(shè)置每個進程每秒種所能建立的最大連接數(shù)量
maxsessrate <number>:設(shè)置每個進程每秒種所能建立的最大會話數(shù)量
maxsslconn <number> : 每進程支持SSL的最大連接數(shù)量
spread-checks <0..50, in percent> 健康檢測延遲時長百分比
建議2%-5%之間
8.配置段
* 代理配置段:
- defaults
- frontend
- backend
- listen
? Frontend段:指定接收客戶端連接偵聽套接字設(shè)置
? Backend段:指定將連接請求轉(zhuǎn)發(fā)至后端服務(wù)器的相關(guān)設(shè)置
? Listen段:指定完整的前后端設(shè)置,只對 TCP 有效
? proxy 名稱:使用字母 數(shù)字 - _ . : 并區(qū)分字符大小寫
9.配置參數(shù)
? bind:指定一個或多個前端偵聽地址和端口
bind [<address>]:<port_range> [, ...] [param*]
? 示例:
listen http_proxy
bind :80,:443 監(jiān)聽所有IP的80和443端口
bind 10.0.0.1:10080,10.0.0.1:10443
bind /var/run/ssl-frontend.sock user root mode 600 accept-proxy
clipboard14.png
10.Balance配置
? balance:后端服務(wù)器組內(nèi)的服務(wù)器調(diào)度算法
? balance <algorithm> [ <arguments> ]
? balance url_param <param> [check_post]
? 調(diào)度算法:
* roundrobin:基于權(quán)重輪詢飞醉,動態(tài)算法冲茸,支持權(quán)重的運行時調(diào)整,支持慢啟 動缅帘;每個后端backend中最多支持4095個server
server options: weight #
* static-rr:基于權(quán)重輪詢轴术,靜態(tài)算法,不支持權(quán)重的運行時調(diào)整及慢啟動钦无;后端主機數(shù)量無上限
* leastconn:加權(quán)最少連接逗栽,動態(tài)算法,最少連接的后端服務(wù)器優(yōu)先分配接收新連接失暂,相同連接時輪詢彼宠,推薦在較長會話的場景使用,例如 MySQL弟塞、LDAP等凭峡,不適合http
* first:根據(jù)服務(wù)器在列表中的位置,自上而下進行調(diào)度决记;前面服務(wù)器 的連接數(shù)達到上限摧冀,新請求才會分配給下一臺服務(wù)
* source:源地址hash,新連接先按權(quán)重分配系宫,后續(xù)連接按source分配 請求 16 Balance配置
* uri: 對URI的左半部分或整個uri做hash計算索昂,并除以服務(wù)器總權(quán) 重取模,以后派發(fā)至某挑出的服務(wù)器,適用于后端緩存服務(wù)器
<scheme>://<user>:<passwd>@<host>:<port>/<path>;<params>?<query>#<frag>
左半部分:/<path>;<params>
整個uri:/<path>;<params>?<query>#<frag>
* url_param: 對用戶請求的uri聽部分中的參數(shù)的值作hash計算扩借,并由服務(wù)器總權(quán)重相除以后派發(fā)至某挑出的服務(wù)器椒惨;通常用于追蹤用 戶,以確保來自同一個用戶請求始終發(fā)往同一個Backend Server
* hdr():對于每個http請求潮罪,此處由<name>指定的 http首部將會被取出做hash計算框产; 并由服務(wù)器總權(quán)重相除以后派發(fā)至某挑出的服務(wù)器;無有效值的會被輪詢調(diào)度
hdr(Cookie)
* rdp-cookie 遠程桌面相關(guān)
* rdp-cookie()
11.哈希算法
? hash-type:哈希算法
hash-type <method> <function> <modifier>
method:
map-based:除權(quán)取余法错洁,哈希數(shù)據(jù)結(jié)構(gòu)是靜態(tài)數(shù)組
consistent:一致性哈希秉宿,哈希數(shù)據(jù)結(jié)構(gòu)是一棵樹
<function> : 哈希函數(shù)
sdbm djb2 wt6
? default_backend <backend>
無use_backend 匹配時,使用默認的backend屯碴,用于 frontend中
? default-server [param*]
為backend中的各server設(shè)定默認選項
配置
? server <name> <address> [:[port]] [param*]
定義后端主機的各服務(wù)器及其選項
server <name> <address> [:port] [settings ...]
default-server [settings ...]
<name>:服務(wù)器在haproxy上的內(nèi)部名稱描睦;出現(xiàn)在日志及警告信息
<address>:服務(wù)器地址,支持使用主機名
[:[port]]:端口映射导而;省略時忱叭,表示同bind中綁定的端口
[param*]:參數(shù)
weight :權(quán)重隔崎,默認為1
maxconn :當(dāng)前server的最大并發(fā)連接數(shù)
backlog :當(dāng)server的連接數(shù)達到上限后的后援隊列長度
backup:設(shè)定當(dāng)前server為備用服務(wù)器 20 健康狀態(tài)檢測
? check:對當(dāng)前server做健康狀態(tài)檢測,只用于四層檢測
注意:httpchk韵丑, “smtpchk”, “mysql-check”, “pgsql-check” and “sslhello-chk” 用于定義應(yīng)用層檢測方法
addr :檢測時使用的IP地址
port :針對此端口進行檢測
inter <delay> :連續(xù)兩次檢測之間的時間間隔爵卒,默認為2000ms
rise <count>:連續(xù)多少次檢測結(jié)果為“成功”才標(biāo)記服務(wù)器為可用 ;默認為2
fall <count>:連續(xù)多少次檢測結(jié)果為“失敗”才標(biāo)記服務(wù)器為不可 用撵彻;默認為3
cookie <value>:為當(dāng)前server指定cookie值钓株,實現(xiàn)基于cookie的會話黏性
disabled:標(biāo)記為不可用
redir <prefix>:將發(fā)往此server的所有GET和HEAD類的請求重定向至指定的URL
12.cookie配置
? cookie <name> [ rewrite | insert | prefix ] [ indirect ] [ nocache ] [ postonly ] [ preserve ] [ httponly ] [ secure ] [ domain ]* [ maxidle ] [ maxlife <life> ]
<name> :cookie名稱,用于實現(xiàn)持久連接
rewrite:重寫
insert:插入
prefix:前綴
配置示例
? 基于cookie的session sticky的實現(xiàn):
backend websrvs
cookie WEBSRV insert nocache indirect
server srv1 172.16.100.6:80 weight 2 check rise 1 fall 2 maxconn 3000 cookie srv1
server srv2 172.16.100.7:80 weight 1 check rise 1 fall 2 maxconn 3000 cookie srv2
13. 統(tǒng)計接口啟用相關(guān)的參數(shù)
? stats enable
啟用統(tǒng)計頁陌僵;基于默認的參數(shù)啟用stats page
- stats uri : /haproxy?stats uri默認值
- stats realm : HAProxy\ Statistics
- stats auth : no authentication
? stats uri <prefix>
自定義stats page uri
? stats auth <user>:<passwd>
認證時的賬號和密碼轴合,可使用多次
? stats realm <realm>
認證時的realm
? stats hide-version
隱藏版本
? stats refresh <delay>
設(shè)定自動刷新時間間隔
? stats admin { if | unless } <cond>
啟用stats page中的管理功能
? 配置示例:
listen stats
bind :9099
stats enable
stats realm HAPorxy\ Stats\ Page
stats auth admin:admin
stats admin if TRUE
14.工作模式
? maxconn :為指定的frontend定義其最大并發(fā)連接 數(shù);默認為2000
? mode { tcp|http|health }
定義haproxy的工作模式
tcp:基于layer4實現(xiàn)代理碗短;可代理mysql, pgsql, ssh, ssl等協(xié)議,https時使用此模式受葛,默認模式
http:僅當(dāng)代理協(xié)議為http時使用,centos實際默認模式
health:工作為健康狀態(tài)檢查的響應(yīng)模式,當(dāng)連接請求到達時回應(yīng)“OK”后即斷開連接偎谁,較少使用
TCP模式的健康狀態(tài)檢測示例
? 示例:
listen ssh
bind :22022
balance leastconn
mode tcp
server sshsrv1 172.16.100.6:22 check
server sshsrv2 172.16.100.7:22 check
15.健康狀態(tài)檢測
? 對后端服務(wù)器做http協(xié)議的健康狀態(tài)檢測:
option httpchk 默認為:/ OPTIONS HTTP/1.0
option httpchk <uri>
option httpchk <method> <uri>
option httpchk <method> <uri> <version>
定義基于http協(xié)議的7層健康狀態(tài)檢測機制
http-check expect [!] <match> <pattern>
http協(xié)議健康狀態(tài)檢測響應(yīng)內(nèi)容或指定響應(yīng)碼
16.forwardfor配置
? option forwardfor [ except <network> ] [ header <name> ] [ if-none ]
在由haproxy發(fā)往后端主機的請求報文中添加“X-ForwardedFor”首部总滩,其值為前端客戶端的地址;用于向后端主發(fā)送真實的客戶端IP
[ except <network> ]:請求報請來自此處指定的網(wǎng)絡(luò)時不予 添加此首部巡雨,如haproxy自身所在網(wǎng)絡(luò)
[ header <name> ]:使用自定義的首部名稱咳秉,而非“XForwarded-For”
[ if-none ] 如果沒有首部才添加首部,如果有使用默認值
? 為指定的MIME類型啟用壓縮傳輸功能
compression algo ...:啟用http協(xié)議的壓縮機 制鸯隅,指明壓縮算法gzip, deflate
compression type ...:指明壓縮的MIMI類型
17.錯誤頁配置
errorfile <code> <file> 自定義錯誤頁
<code> :HTTP status code.
支持200, 400, 403, 408, 500, 502, 503, 504\.
<file>:錯誤頁文件路徑
? 示例:
errorfile 400 /etc/haproxy/errorfiles/400badreq.http
errorfile 408 /dev/null # workaround Chrome preconnect bug
errorfile 403 /etc/haproxy/errorfiles/403forbid.http
errorfile 503 /etc/haproxy/errorfiles/503sorry.http
? errorloc <code> <url>
相當(dāng)于errorloc302 澜建,利用302重定向至指URL
errorloc 503 http://www.magedu.com/error_pages/503.html
報文首部
? 修改報文首部
* reqadd <string>[{if | unless} <cond> ]
在請求報文尾部添加指定首部
* rspadd <string> [{if | unless} <cond> ]
在響應(yīng)報文尾部添加指定首部
示例:rspadd X-Via:\ HAPorxy
* reqdel <search> [{if | unless}<cond>]
* reqidel <search> [{if | unless} <cond> ] (ignore case) 不分大小寫
從請求報文中刪除匹配正則表達式的首部
* rspdel <search> [{if | unless} <cond> ]
* rspidel <search> [{if | unless} <cond> ] (ignore case) 不分大小寫
從響應(yīng)報文中刪除匹配正則表達式的首部
示例: rspidel Server.*
連接超時
* timeout client <timeout> 客戶端最長空閑連接超時時長 默認單位是毫秒
* timeout server <timeout> 后端服務(wù)器最長空閑連接超時時長
* timeout http-keep-alive <timeout>持久連接的持久時長
* timeout http-request <timeout>一次完整的HTTP請求的最大等待時長
* timeout connect <timeout> 成功連接后端服務(wù)器的最大等待時長
* timeout client-fin <timeout> 客戶端半連接的空閑時長
* timeout server-fin <timeout> 后端服務(wù)器半連接的空閑時長
18.ACL
? acl:訪問控制列表(ACL)的使用提供了一個靈活的解決方 案來執(zhí)行內(nèi)容交換,并且通瞅蛞裕基于從請求中提取的內(nèi)容炕舵、響 應(yīng)或任何環(huán)境狀態(tài)進行決策
? acl <aclname> <criterion> [flags] [operator] [<value>]
...
<aclname>:ACL名稱,可使用字母 數(shù)字 : . - _
區(qū)分字符大小寫
<criterion>: 比較的標(biāo)準(zhǔn)和條件
? <value>的類型:
- boolean
- integer or integer range
- IP address / network
- string (exact, substring, suffix, prefix, subdir, domain)
- regular expression
- hex block
?<flag>
-i 不區(qū)分大小寫
-m 使用指定的pattern匹配方法
-n 不做DNS解析
-u 強制每個ACL必須唯一ID跟畅,否則多個同名ACL或關(guān)系
-- 強制flag結(jié)束. 當(dāng)字符串和某個flag相似時使用
? [operator]
匹配整數(shù)值:eq咽筋、ge、gt徊件、le奸攻、lt
匹配字符串:
- exact match (-m str) :字符串必須完全匹配模式
- substring match (-m sub) :在提取的字符串中查找模式,如果其中任何一個被發(fā)現(xiàn)虱痕,ACL將匹配
- prefix match (-m beg) :在提取的字符串首部中查找模式 睹耐,如果其中任何一個被發(fā)現(xiàn),ACL將匹配
- suffix match (-m end) :將模式與提取字符串的尾部進行 比較部翘,如果其中任何一個匹配硝训,則ACL進行匹配
- subdir match (-m dir) :查看提取出來的用斜線分隔( “/”)的字符串,如果其中任何一個匹配,則ACL進行匹配
- domain match (-m dom) :查找提取的用點(“.”)分隔 字符串窖梁,如果其中任何一個匹配赘风,則ACL進行匹配
? acl作為條件時的邏輯關(guān)系:
- 與:隱式(默認)使用
- 或:使用“or” 或 “||”表示
- 否定:使用“!“ 表示
示例: if invalid_src invalid_port 與關(guān)系
if invalid_src || invalid_port 或
if ! invalid_src 非
?<criterion>:各種條件
dst 目標(biāo)IP
dst_port 目標(biāo)PORT
src 源IP
src_port 源PORT
示例:acl invalid_src src 172.16.100.200
? base : string
返回第一個主機頭和請求的路徑部分的連接,該請求從第一個斜杠開始纵刘,并在問號之前結(jié)束,對虛擬主機有用
<scheme>://<user>:<passwd>@<host>:<port>/<path>;<params>?<query>#<frag>
base : exact string match
base_beg : prefix match
base_dir : subdir match
base_dom : domain match
base_end : suffix match
base_len : length match
base_reg : regex match
base_sub : substring match
? path : string
提取請求的URL路徑邀窃,該路徑從第一個斜杠開始,并在問號之 前結(jié)束(無主機部分)
<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>
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
? url : string
提取請求中的URL假哎。一個典型的應(yīng)用是具有預(yù)取能力的緩存瞬捕, 以及需要從數(shù)據(jù)庫聚合多個信息并將它們保存在緩存中的網(wǎng)頁門戶入 口
url : exact string match
url_beg : prefix match
url_dir : subdir match
url_dom : domain match
url_end : suffix match
url_len : length match
url_reg : regex match
url_sub : substring match
? req.hdr([<name>[,<occ>]]) : string
提取在一個HTTP請求報文的首部
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
示例:
acl bad_curl hdr_sub(User-Agent) -i curl
block if bad_curl
? status : integer
返回在響應(yīng)報文中的狀態(tài)碼
* 預(yù)定義ACL
? ACL名稱 等價于 說明
? TRUE always_true 總是匹配
? FALSE always_false 從不匹配
? HTTP req_proto_http 匹配HTTP協(xié)議
? HTTP_1.0 req_ver 1.0 匹配HTTP協(xié)議1.0
? HTTP_1.1 req_ver 1.1 匹配HTTP協(xié)議1.1
? HTTP_CONTENT hdr_val(content-length) gt 0 匹配已存在內(nèi)容長度
? HTTP_URL_ABS url_reg ^[^/:]*:// 匹配URL絕對路徑
? HTTP_URL_SLASH url_beg / 匹配URL相對路徑
? HTTP_URL_STAR url * 匹配 URL 等于 "*"
? LOCALHOST src 127.0.0.1/8 匹配從localhost來的連接
? METH_CONNECT method CONNECT 匹配HTTP CONNECT方法
* ACL
? METH_GET method GET HEAD match HTTP GET or HEAD method
? METH_HEAD method HEAD match HTTP HEAD method
? METH_OPTIONS method OPTIONS match HTTP OPTIONS method
? METH_POST method POST match HTTP POST method
? METH_TRACE method TRACE match HTTP TRACE method
? RDP_COOKIE req_rdp_cookie_cnt gt 0 match presence of an RDP cookie
? REQ_CONTENT req_len gt 0 match data in the request buffer
? WAIT_ENDwait_end wait for end of content analysis
19.配置
? use_backend <backend>[{if | unless} <condition>]
當(dāng)if/unless一個基于ACL的條件匹配時切換指定backend
? block { if | unless } <condition>
阻止7層請求if/unless一個條件匹配
? 示例:
acl invalid_src src 172.16.200.2
block if invalid_src
errorfile 403 /etc/fstab
? http-request { allow | deny |add-header <name> <fmt> |set-header <name> <fmt>} [ { if | unless } <condition> ]
對7層請求的訪問控制
? tcp-request connection {accept|reject} [{if | unless} <condition> ]
根據(jù)第4層條件對傳入連接執(zhí)行操作
? 示例:listen ssh
bind :22022
balance leastconn
acl invalid_src src 172.16.200.2
tcp-request connection reject if invalid_src
mode tcp
server sshsrv1 172.16.100.6:22 check
server sshsrv2 172.16.100.7:22 check backup
基于ACL的動靜分離示例
frontend web *:80
acl url_static path_beg -i /static /images /javascript /stylesheets
acl url_static path_end -i .jpg .gif .png .css .js .html .txt .htm
use_backend staticsrvs if url_static
default_backend appsrvs
backend staticsrvs
balance roundrobin
server stcsrv1 172.16.100.6:80 check
backend appsrvs
balance roundrobin
server app1 172.16.100.7:80 check
server app1 172.16.100.7:8080 check
listen stats
bind :9091
stats enable
stats auth admin:admin
stats admin if TRUE
20.支持https協(xié)議
? 配置HAProxy支持https協(xié)議:
? 1 支持ssl會話;
bind *:443 ssl crt /PATH/TO/SOME_PEM_FILE
crt 后證書文件為PEM格式位谋,且同時包含證書和所有私鑰
cat demo.crt demo.key > demo.pem
? 2 把80端口的請求重向定443
bind *:80
redirect scheme https if !{ ssl_fc }
? 3 向后端傳遞用戶請求的協(xié)議和端口(frontend或backend)
http_request set-header X-Forwarded-Port %[dst_port]
http_request add-header X-Forwared-Proto https if { ssl_fc }