Haproxy
時間: 20181121
目錄
SRE(Site Reliability Engineer)
不同的調度器的特點
Haproxy.cfg
主配置段defaults
後端配置
session sticky會話保持方式
HAProxy功能
HAProxy組成
global配置
日誌系統
性能調整
配置段
配置參數
哈希算法
健康狀態檢測server後check的參數
cookie配置
統計監控接口配置stats
HAProxy sock文件通信管理後端主機(命令行)
工作模式mode
健康狀態檢測
forwardfor配置
爲指定的MIME類型啓用壓縮傳輸功能
錯誤頁配置
修改報文首部
連接超時
ACL
base
url
req.hdr
預定義ACL
配置ACL
基於ACL的動靜分離示例
配置4層轉發
配置HAProxy支持https協議
總結
SRE(Site Reliability Engineer)網站可靠性工程師
不同的調度器的特點
nginx向後調度時需要消耗額外端口
nginx可以直接提供後端服務器監控,查看其是否正常
lvs不會消耗端口
Haproxy.cfg
Global Settings
Proxies
frontend
backend
listen
defaults
主配置段defaults
maxconn <number> 最大併發連接
connections to <number>
maxconnrate <number> 最大連接速率
maxsslcoon <number> 最大ssl連接
spread-checks 分散檢查
後端配置
frontend, backend
bind 綁定地址
server 定義後端服務器
server <name> address <params>
[param*]
maxconn 定義當前server最大併發連接數
backlog 後端隊列
backup 後端備用服務器,一般用來顯示say sorry
check
addr
port
inter 檢測時間間隔,默認爲2s
rise 連續多少次成功會將後端fail的服務器標記爲可用
fail 連續多少次結果爲失敗時才標記爲不可用默認爲3
注意: option httpck, "smtpchk", "mysql-check", "pgsql-check"
and "ssl-hello-check" 用於定義應用層檢測方法默認爲tcp握手檢測
cookie 定義是否要給客戶端添加所定義的cookie信息
disabled 標記爲可用
on-error <mode> 後端服務故障時的行動策略
- fastinter 強制快速間隔檢測後端服務器狀態
- fail-check
- sudden-death
- mark-down
redir 重定向
weight
balance
roundrobin最多支持4095個後端server (適用於短連接)
static-rr 需要重啓纔可生效 (適用於短連接)
leastconn 最少連接(適用於長連接)
支持加權時運行時調整
first優先使用,即當第一個請求滿時,才往第二個轉發請求
source 源hash 是否支持運行時調整權重受限於hash-type
uri uri-hash 是否支持運行時調整權重受限於hash-type 非常適合後端爲緩存服務器
url_param 可以通過參數實現定向向後端調用
hdr 其於首部參數實現調用特定的後端或持續
rdp
status enable
status uri /customize
status auth name:password
status admin if true|LOCALHOST 在web界面可以管理後端服務器設置其狀態
maxcoon
mode
http
tcp
health
cookie <name> insert nocache indirect
option forwardfor
errorfile <code> <file>
errorfile 400 /path/400badreq.html
errorfile 403 /path/forbidden.html
errorloc <code> <url>
reqadd 添加向後端請求的http首部
rspadd 添加向客戶端響應的http首部
reqdel
reqidel
log
global
<address>
no log
compression
option httpchk <method> <uri> <version>
http-check expect [!] <match>
acl <acl_name> <criterior> [flags] [operator] <value>
<value>的類型
- boolean
- integer or integer range
- IP address / network
- string (exact, substring, suffix, prefix, subdir, domain)
- regular expression
- hex block
<flags>
-i 忽略大小寫
-m 使用指定的模式匹配方式
-n 禁用dns反解其域名
-u
--
[operator]
<criterian>
timeout
session sticky會話保持方式
session sticky: ip_hash, sh, source
session replication cluster
session server
haproxy 不支持緩存
HAProxy功能
HAProxy是TCP / HTTP反向代理服務器,尤其適合於高可用性環境
可以針對HTTP請求添加cookie,進行路由後端服務器
可平衡負載至後端服務器,並支持持久連接
支持基於cookie進行調度
支持所有主服務器故障切換至備用服務器
支持專用端口實現監控服務
支持不影響現有連接情況下停止接受新連接請求
可以在雙向添加,修改或刪除HTTP報文首部
支持基於pattern實現連接請求的訪問控制
通過特定的URI爲授權用戶提供詳細的狀態信息
支持http反向代理
支持動態程序的反向代理
支持基於數據庫的反向代理
HAProxy組成
程序環境:
主程序:/usr/sbin/haproxy
配置文件:/etc/haproxy/haproxy.cfg
Unit file:/usr/lib/systemd/system/haproxy.service
配置段:
global:全局配置段
進程及安全配置相關的參數
性能調整相關參數
Debug參數
proxies:代理配置段
defaults:爲frontend, backend, listen提供默認配置
frontend:前端,相當於nginx中的server {}
backend:後端,相當於nginx中的upstream {}
listen:同時擁有前端和後端,適用於一對一環境
簡單的配置示例
frontend web
bind *:80
default_backend websrvs
backend websrvs
balance roundrobin
server srv1 192.168.0.101:80 check
server srv2 192.168.0.102:80 check
global配置
global配置參數:
進程及安全管理:chroot, deamon,user, group, uid, gid
nbproc <number> 要啓動的haproxy的進程數量,系統默認單進程,要求使用daemon模式
ulimit-n <number> 每個haproxy進程可打開的最大文件數,系統自動會指定,不建議設置
daemon 後端方式運行,建議使用
log 定義全局的syslog服務器;最多可以定義兩個
log <address> [len <length>] <facility> [max level [min level]]
address: rsyslog服務器地址
len: 記錄日誌的長度,默認1024
日誌系統
log:
log global
log <address> [len <length>] <facility> [<level> [<minlevel>]]
length 日誌行的長度,默認1024
no log
注意:
默認發往本機的日誌服務器
(1) local2.* /var/log/local2.log
(2) $ModLoad imudp
$UDPServerRun 514
log-format <string>:
課外實踐:參考文檔實現combined格式的記錄
將特定信息記錄在日誌中
capture cookie <name> len <length>
捕獲請求和響應報文中的 cookie並記錄日誌
capture request header <name> len <length>
捕獲請求報文中指定的首部並記錄日誌
示例:
capture request header X-Forwarded-For len 15
capture response header <name> len <length>
捕獲響應報文中指定的首部並記錄日誌
示例:
capture response header Content-length len 9
capture response header Location len 15
性能調整:
maxconn <number>:設置每個haproxy進程所能接受的最大併發連接數
maxconnrate <number>:設置每個進程每秒種所能建立的最大連接數量
maxse***ate <number>:設置每個進程每秒種所能建立的最大會話數量
maxsslconn <number>: 每進程支持SSL的最大連接數量
spread-checks <0..50, in percent> 健康檢測延遲時長百分比,建議2-5之間
配置段
代理配置段:
- defaults <name>
- frontend <name>
- backend <name>
- listen <name>
Frontend段:指定接收客戶端連接偵聽套接字設置
Backend段:指定將連接請求轉發至後端服務器的相關設置
Listen段:指定完整的前後端設置
proxy 名稱:使用字母 數字 - _ . : 並區分字符大小寫
配置參數:
bind:指定一個或多個前端偵聽地址和端口
bind [<address>]:<port_range> [, ...] [param*]
示例:
listen http_proxy
bind :80,:443
bind 10.0.0.1:10080,10.0.0.1:10443
bind /run/ssl-frontend.sock user root mode 600 accept-proxy
Balance配置
balance:後端服務器組內的服務器調度算法
balance <algorithm> [ <arguments> ]
balance url_param <param> [check_post]
調度算法:
roundrobin:基於權重輪詢,動態算法,支持權重的運行時調整,支持慢啓動;
每個後端backend中最多支持4095個server,此爲默認調度算法
server options: weight #
static-rr:基於權重輪詢,靜態算法,不支持權重的運行時調整及慢啓動;後端
主機數量無上限
leastconn:加權最少連接,動態算法,最少連接的後端服務器優先分配接收新
連接,相同連接時輪詢,推薦在較長會話的場景使用,例如MySQL,LDAP等
,不適合http
first:根據服務器在列表中的位置,自上而下進行調度;前面服務器的連接數達
到上限,新請求才會分配給下一臺服務,不支持權重
source:源地址hash,新連接先按權重分配,後續連接按source分配請求,實
現會話綁定
uri:
對URI的左半部分或整個uri做hash計算,併除以服務器總權重取模,
以後派發至某挑出的服務器,適用於後端緩存服務器
<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<q
uery>#<frag>
左半部分:/<path>;<params>
整個uri:/<path>;<params>?<query>#<frag>
url_param:
對用戶請求的uri中的<params>部分中的參數的值作hash計算,並由服
務器總權重相除以後派發至某挑出的服務器;通常用於追蹤用戶,以
確保來自同一個用戶的請求始終發往同一個Backend Server
http://www.winthcloud.com/bbs/hello;type=title
hdr(<name>):對於每個http請求,此處由<name>指定的http首部將會
被取出做hash計算; 並由服務器總權重相除以後派發至某挑出的服務
器;無有效值的會被輪詢調度hdr(Cookie)
rdp-cookie 遠程桌面相關
rdp-cookie(<name>)
哈希算法
hash-type:哈希算法
hash-type <method> <function> <modifier>
method:
map-based:除權取餘法,哈希數據結構是靜態數組
consistent:一致性哈希,哈希數據結構是一棵樹
function : 哈希函數,取值:sdbm,djb2,wt6
modifier: 取值avalanche時,將修改哈希值,而非直接使用
default_backend <backend>
無use_backend 匹配時,使用默認的backend,用於frontend中
default-server [param*]
爲backend中的各server設定默認選項
server <name> <address>[:[port]] [param*]
定義後端主機的各服務器及其選項
server <name> <address>[:port] [settings ...]
default-server [settings ...]
<name>:後端服務器在haproxy上的內部名稱;出現在日誌及警告信息
<address>:後端服務器地址,支持使用主機名
[:[port]]:端口映射;省略時,表示同bind中綁定的端口
[param*]:參數
weight <weight>:權重,默認爲1
maxconn <maxconn>:當前後端server的最大併發連接數
backlog <backlog>:當server的連接數達到上限後的後援隊列長度
backup:設定當前server爲備用服務器Sorry Server
健康狀態檢測server後check的參數
check:對當前server做健康狀態檢測,只用於四層檢測
addr :檢測時使用的IP地址
port :針對此端口進行檢測
inter <delay>:檢測之間的時間間隔,默認爲2000ms
rise <count>:連續多少次檢測結果爲“成功”才標記爲可用;默認爲2
fall <count>:連續多少次檢測結果爲“失敗”才標記爲不可用;默認爲3
注意:option後面加httpchk,smtpchk, mysql-check, pgsql-check,ssl-hellochk
方法,可用於實現應用層檢測
disabled:標記爲不可用
redir <prefix>:將發往此server的所有GET和HEAD類的請求重定向至指定的URL
cookie配置
cookie <value>:爲當前server指定cookie值,實現基於cookie的會話黏性
cookie <name> [ rewrite | insert | prefix ] [ indirect ] [ nocache ]
[ postonly ] [ preserve ] [ httponly ] [ secure ] [ domain <domain> ]*
[ maxidle <idle> ] [ maxlife <life> ]
<name>:cookie名稱,用於實現持久連接
rewrite:重寫
insert:插入
prefix:前綴
nocache:當client和hapoxy之間有緩存時,不緩存cookie
cookie配置示例
基於cookie的session sticky的實現
backend websrvs
cookie WEBSRV insert nocache
server srv1 172.16.0.6:80 weight 2 check rise 1 fall 2 cookie srv1
server srv2 172.16.0.7:80 weight 1 check rise 1 fall 2 cookie srv2
統計接口啓用相關的參數
stats enable 啓用統計頁;基於默認的參數啓用stats page
stats hide-version 隱藏版本
stats refresh <delay> 設定自動刷新時間間隔
stats uri <prefix> 自定義stats page uri,默認值:/haproxy?stats
stats realm <realm> 認證時的realm,示例:stats realm : HAProxy\ Statistics
stats auth <user>:<passwd>認證時的賬號和密碼,可使用多次默認:no authentication
stats admin { if | unless } <cond> 啓用stats page中的管理功能
配置示例
listen stats
bind :9527
stats enable
stats hide-version
stats uri /hastats
stats realm HAPorxy\ Stats\ Page
stats auth admin1:password1
stats auth admin1:password2
stats refresh 3s
stats admin if TRUE (這裏只是測試使用,真環境要配置acl)
HAProxy sock文件通信管理後端主機(命令行)
首先需要設置socket支持管理
global
stats socket /var/run/haproxy.sock mode 600 level admin
stats timeout 2m
stats socket /var/lib/haproxy/stats level admin
安裝通信軟件
yum install socat
echo "help"| socat stdio /usr/local/haproxy/stats
然後根據提示就可以設置相應的主機了 如將server設置爲drain模式
echo "set server bktest/web1 state drain" | socat stdio
/var/lib/haproxy/stats
工作模式mode
maxconn <conns>:爲指定的frontend定義其最大併發連接數;默認爲3000
mode { tcp|http|health }
定義haproxy的工作模式
tcp:基於layer4實現代理;可代理mysql, pgsql, ssh, ssl等協議,https時使用
此模式,默認模式
http:僅當代理協議爲http時使用,CentOS中haproxy實際的默認模式
health:工作爲健康狀態檢查的響應模式,當連接請求到達時迴應“OK”
後即斷開連接,較少使用
TCP模式示例:
listen ssh
bind :22022
balance leastconn
mode tcp
server sshsrv1 172.16.0.6:22 check
server sshsrv2 172.16.0.7:22 check
健康狀態檢測
對後端服務器做http協議健康狀態檢測:通常用於backend
option httpchk 默認向後端服務器發請求:OPTIONS / HTTP/1.0
option httpchk <uri>
option httpchk <method> <uri>
option httpchk <method> <uri> <version>
定義基於http協議的7層健康狀態檢測機制
http-check expect [!] <match> <pattern>
http協議健康狀態檢測響應內容或指定響應碼
forwardfor配置
option forwardfor [ except <network> ] [ header <name> ] [ if-none ]
在由haproxy發往後端主機的請求報文中添加“X-Forwarded-For”首部,
其值爲前端客戶端的地址;用於向後端主發送真實的客戶端IP
[ except <network> ]:請求報請來自此處指定的網絡時不予添加此首部
如haproxy自身所在網絡
[ header <name> ]:使用自定義的首部名稱,而非“X-Forwarded-For”
[ if-none ] 如果沒有首部才添加首部,如果有使用默認值
爲指定的MIME類型啓用壓縮傳輸功能
compression algo <algorithm> ...:啓用http協議的壓縮機制,指明壓縮算
法gzip, deflate
compression type <mime type> ...:指明壓縮的MIMI類型
錯誤頁配置
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 pre-connect bug
errorfile 403 /etc/haproxy/errorfiles/403forbid.http
errorfile 503 /etc/haproxy/errorfiles/503sorry.http
errorloc <code> <url>
相當於errorloc302 <code> <url>,利用302重定向至指URL
示例:errorloc 503 http://www.winthcloud.com/error_pages/503.html
修改報文首部
在請求報文尾部添加指定首部
reqadd <string> [{if | unless} <cond>]
在響應報文尾部添加指定首部
rspadd <string> [{if | unless} <cond>]
示例:rspadd X-Via:\ HAPorxy
從請求報文中刪除匹配正則表達式的首部
reqdel <search> [{if | unless} <cond>]
reqidel <search> [{if | unless} <cond>] 不分大小寫
從響應報文中刪除匹配正則表達式的首部
rspdel <search> [{if | unless} <cond>]
rspidel <search> [{if | unless} <cond>] 不分大小寫
示例: rspidel server.*
連接超時
timeout client <timeout> 客戶端最長空閒連接超時時長 默認單位是毫秒
timeout server <timeout> 後端服務器最長空閒連接超時時長
timeout http-keep-alive <timeout> 持久連接的持久時長
timeout http-request <timeout> 一次完整的HTTP請求的最大等待時長
timeout connect <timeout> 成功連接後端服務器的最大等待時長
timeout client-fin <timeout> 客戶端半連接的空閒時長
timeout server-fin <timeout> 後端服務器半連接的空閒時長
ACL
acl:訪問控制列表(ACL)的使用提供了一個靈活的解決方案來執行內容交換,並且通
常基於從請求中提取的內容、響應或任何環境狀態進行決策
acl <aclname> <criterion> [flags] [operator] [<value>] ...
<aclname>:ACL名稱,可使用字母 數字 : . - _ ,區分字符大小寫
<criterion>: 比較的標準和條件
<value>的類型:
- boolean
- integer or integer range
- IP address / network
- string (exact, substring, suffix, prefix, subdir, domain)
- regular expression
- hex block
<flags>
-i 不區分大小寫
-m 使用指定的pattern匹配方法
-n 不做DNS解析
-u 強制每個ACL必須唯一ID,否則多個同名ACL或關係
-- 強制flag結束. 當字符串和某個flag相似時使用
[operator]
匹配整數值:eq、ge、gt、le、lt
匹配字符串:
- exact match (-m str) :字符串必須完全匹配模式
- substring match (-m sub)
在提取的字符串中查找模式,如果其中任何一個被發現,ACL將匹配
- prefix match (-m beg)
在提取的字符串首部中查找模式,如果其中任何一個被發現,ACL將匹配
- suffix match (-m end)
將模式與提取字符串的尾部進行比較,如果其中任何一個匹配則ACL進行匹配
- subdir match (-m dir)
查看提取出來的用斜線分隔(“/”)的字符串,如果其中任何一個匹配,
則ACL進行匹配
- domain match (-m dom)
查找提取的用點(“.”)分隔字符串,如果其中任何一個匹配則ACL進行匹配
acl作爲條件時的邏輯關係:
- 與:隱式(默認)使用
- 或:使用“or” 或 “||”表示
- 否定:使用“!“ 表示
示例:if invalid_src invalid_port 與關係
if invalid_src || invalid_port 或
if ! invalid_src 非
<criterion> :各種條件
dst 目標IP
dst_port 目標PORT
src 源IP
src_port 源PORT
示例:acl invalid_src src 172.16.100.200
base : string
返回第一個主機頭和請求的路徑部分的連接,該請求從第一個斜槓開始
並在問號之前結束,對虛擬主機有用
<scheme>://<user>:<password>@<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_beg /images/
path_end .jpg .jpeg .png .gif
path_reg ^/images.*\.jpeg$
path_sub image
path_dir jpegs
path_dom winthcloud
/images/jpegs/20180123/logo.jpg
url : string
提取請求中的URL。一個典型的應用是具有預取能力的緩存,以及需要從數據庫聚合多個
信息並將它們保存在緩存中的網頁門戶入口,推薦使用path
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_agent hdr_sub(User-Agent) -i curl wget
block if bad_agent
status : integer
返回在響應報文中的狀態碼
預定義ACL
ACL名稱等價於說明
TRUE always_true 總是匹配
FALSE always_false 從不匹配
HTTP req_proto_http 匹配HTTP協議
HTTP_1.0 req_ver 1.0 匹配HTTP協議1.0
HTTP_1.1 req_ver 1.1 匹配HTTP協議1.1
HTTP_CONTENT hdr_val(content-length) gt 0 匹配已存在內容長度
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方法
METH_GET method GET HEAD match HTTP GET or HEAD method
METH_HEADmethod 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_END wait_end wait for end of content analysis
配置ACL
use_backend <backend> [{if | unless} <condition>]
當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 /usr/share/haproxy/403.http
http-request { allow | deny |add-header <name> <fmt> |setheader
<name> <fmt> } [ { if | unless } <condition> ]
對7層請求的訪問控制
基於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 staticsrv1 192.168.0.100:80 check
backend appsrvs
balance roundrobin
server app1 192.168.0.101:80 check
server app1 192.168.0.102:8080 check
配置4層轉發
tcp-request connection {accept|reject} [{if | unless} <condition>]
根據第4層條件對傳入連接執行操作
示例:
listen ssh
bind :22222
mode tcp
balance leastconn
acl invalid_src src 172.16.0.200
tcp-request connection reject if invalid_src
server sshsrv1 192.168.1.101:22 check
server sshsrv2 192.168.1.102:22 check backup
配置HAProxy支持https協議
支持ssl會話;
bind *:443 ssl crt /PATH/TO/SOME_PEM_FILE
crt 後證書文件爲PEM格式,且同時包含證書和所有私鑰
cat demo.crt demo.key > demo.pem
把80端口的請求重向定443
bind *:80
redirect scheme https if !{ ssl_fc }
向後端傳遞用戶請求的協議和端口(frontend或backend)
http_request set-header X-Forwarded-Port %[dst_port]
http_request add-header X-Forwared-Proto https if { ssl_fc }
總結
1. 爲什麼建立連接協議三次握手,而關閉連接卻是四次揮手
因爲斷開時客戶端主動向服務器發送斷開請求,服務器有可能還有數據未發送完
成所以只回復了一個確認包,等其發送完成後才發送了FIN=1所以就變成了4次
2. haproxy無法實現直接與動態服務器交互,中間必須有web-server,因爲haproxy
其最主要的目標是實現後端代理,還有就是對http協議請求向後端代理時,更優化
向後端代理時調度更細化,不過越分析的細化,其消耗cpu計算能力也越多