HAProxy代理
javascript
---------------------------------------------------------------------------------------------------------------------------------------------css
一、應對客戶端c10k以上同時鏈接的高性能的TCP和HTTP負載均衡器,其功能是用來提供基於cookie的持久性,基於內容的交換,過載保護的高級流浪管制,自動故障切換,以正則表達式爲基礎的控制運行時間,基於web的報表,高級日誌記錄以幫助排除故障的應用或網絡及其餘功能前端
四層:lvs,nginx(stream),haproxy(mode tcp)mysql
七層:http:ngxin(http),haproxy(mode httpd),httpdnginx
官網:www.haproxy.org,www.haproxy.comgithub
文檔:https://cbonte.github.io/haproxy-dconv/web
HAProxy是TCP/HTTP反向代理服務器,尤爲適合於高可用環境
一、光盤base源有安裝包,安裝好後服務名稱叫haproxy,systemctl start haproxy打開5000端口
Unit file:/usr/lib/systemd/system/haproxy.service
defaults:爲frontend, backend, listen提供默認配置
frontend:前端,至關於nginx中的server {}
backend:後端,至關於nginx中的upstream {}
default_backend websrvs 這個請求就會調度到後端的某個名叫websrvs的backend服務器上
server srv1 192.168.0.101:80 check 健康性檢查
server srv2 192.168.0.102:80 check 健康性檢查
進程及安全管理:chroot, deamon,user, group, uid, gid
nbproc <number> 要啓動的haproxy的進程數量,系統默認單進程,要求使用daemon模式,通常而言,幾個cpu就創建幾個進程
ulimit-n <number> 每一個haproxy進程可打開的最大文件數,系統自動會指定,不建議設置
log <address> [len <length>] <facility> [max level [min level]]
log <address> [len <length>] <facility> [<level> [<minlevel>]]
(1) local2.* /var/log/local2.log
三、log-format:自定義log格式,https://cbonte.github.io/haproxy-dconv/1.9/configuration.html#8.2.4
(1)capture cookie <name> len <length>
(2)capture request header <name> len <length>
capture request header X-Forwarded-For len 15
(3)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之間
三、Backend段:指定將鏈接請求轉發至後端服務器的相關設置
五、proxy 名稱:使用字母 數字 - _ . : 並區分字符大小寫
bind:指定一個或多個前端偵聽地址和端口,只能放在frontend和listen
bind [<address>]:<port_range> [, ...] [param*]
bind 10.0.0.1:10080,10.0.0.1:10443
bind /run/ssl-frontend.sock user root mode 600 accept-proxy ---->對本地的用戶root,用套接字提供服務,權限是600
注意:listen只能實現一對一的方式,一對多,多對多仍是用frontend和backend,但在一對一的方式中推薦仍是用frontend和backend方式,便於修改和拓展
一、balance:後端服務器組內的服務器調度算法,不能放在frontend,可放在defaults、listen和 backend
balance <algorithm> [ <arguments> ]
balance url_param <param> [check_post]
(1)roundrobin:基於權重輪詢,動態算法,支持權重的運行時調整,支持慢啓動;每一個後端backend中最多支持4095個server
(2)static-rr:基於權重輪詢,靜態算法,不支持權重的運行時調整及慢啓動;後端主機數量無上限
(3)leastconn:加權最少鏈接,動態算法,最少鏈接的後端服務器優先分配接收新鏈接,相同鏈接時輪詢,推薦在較長會話的場景使用,例如MySQL,LDAP等,不適合http
(4)first:根據服務器在列表中的位置,自上而下進行調度;前面服務器的鏈接數達到上限,新請求才會分配給下一臺服務,不支持權重
(5)source:源地址hash,新鏈接先按權重分配,後續鏈接按source分配請求,實現會話綁定
舉例:除權取餘法說明,對ip作哈希運算並對3進行取模,值只會出現0、一、2,當三臺設備權重同樣時,就能夠將取模值爲0的調入rs1,取模爲1時調入rs2,取模爲2時調入rs3
當權重不同時,對於取模的值進行權重的累加,計算後按比例分配,取模值爲0時調入rs1,取模爲一、2 時調入rs2,取模爲三、四、5時調入rs3
缺點:增長rs服務器後一切都須要從新計算;也有可能一個外網ip後面有不少私網ip設備,形成設備分配很粗糙
(6)uri:對URI的左半部分或整個uri作hash計算,併除以服務器總權重取模,之後派發至某挑出的服務器,適用於後端緩存服務器,通常配合varnish緩存服務器
<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>
整個uri:/<path>;<params>?<query>#<frag>
(7)url_param:對用戶請求的uri中的<params>部分中的參數的值做hash計算,並由服務器總權重相除之後派發至某挑出的服務器;一般用於追蹤用戶,以確保來自同一個用戶的請求始終發往同一個Backend Server
http://www.chenux.com/bbs/hello;type=title
(8)hdr(<name>):根據主機頭調度,對於每一個http請求,此處由<name>指定的http首部將會被取出作hash計算; 並由服務器總權重相除之後派發至某挑出的服務器;無有效值的會被輪詢調度
hash-type <method> <function> <modifier>
map-based:除權取餘法,哈希數據結構是靜態數組,剛纔上述的舉例已說明
function : 哈希函數,取值:sdbm,djb2,wt6
modifier: 取值avalanche時,將修改哈希值,而非直接使用
無use_backend 匹配時,使用默認的backend,用於frontend中
爲backend中的各server設定默認選項,爲後端服務器定義默認值
一致性哈希算法說明:在除權取餘法的例子中,若是3臺服務器忽然故障一臺變成2臺或者3臺服務器不夠用須要增長1臺,以前該服務器上的文件的緩存位置一定發生改變,之前緩存的圖片也失去緩存的做用和意義。若是是服務器故障,因爲大量緩存同一時間失效,形成了緩存的雪崩,此時前端緩存已經沒法起到承擔部分壓力的做用,後端服務器將會承受巨大壓力,整個系統也頗有可能崩潰。該種狀況是沒法避免,一致性哈希算法就是來解決這種問題的。
一致性哈希仍是取餘的作法,只不過是對ip進行hash後,再對2^32進行取餘,若是有3臺服務器,咱們將這3臺服務器映射到hash環上,當某個緩存服務器的緩存文件被訪問時,該文件也是通過了hash後對2^32取餘
被訪問的文件通過hash取餘運算後,從被緩存對象的位置出發,沿順時針方向遇到的第一個服務器,將會是該文件將要緩存與服務器,在服務器不變狀況下,一個文件一定會被 緩存到固定的服務器上,當下次想要訪問這個文件時,再次使用相同的算法便可算出這個圖片被緩存在哪一個服務器上,圖中所示file將被緩存到B上
假如B和C之間也有個file2,file2將會緩存到C上,當B被移除,file2的緩存不變,file1緩存將會移動至C,服務器數量發生改變,並非全部緩存都失效,而是隻有部分會失效,前端仍然能分擔整個系統的壓力
因爲實際狀況不可能說三臺設備均勻分佈在環上,因此引入虛擬節點,虛擬節點越多緩存被均勻分佈的機率越大
server <name> <address>[:[port]] [param*]
server <name> <address>[:port] [settings ...]
<name>:後端服務器在haproxy上的內部名稱;出如今日誌及警告信息
[:[port]]:端口映射;省略時,表示同bind中綁定的端口
maxconn <maxconn>:當先後端server的最大併發鏈接數
backlog <backlog>:當server的鏈接數達到上限後的後援隊列長度
backup:設定當前server爲備用服務器Sorry Server
在配置文件中更改監聽端口,80被haproxy監聽,須要更改不被監聽的端口
一、check:對當前server作健康狀態檢測,只用於四層檢測
注意:httpchk,「smtpchk」, 「mysql-check」, 「pgsql-check」 and 「ssl-hello-chk」 用於定義應用層檢測方法
inter <delay>:檢測之間的時間間隔,默認爲2000ms
rise <count>:連續多少次檢測結果爲「成功」才標記爲可用;默認爲2
fall <count>:連續多少次檢測結果爲「失敗」才標記爲不可用;默認爲3
二、disabled:標記爲不可用,加入此項後將不往標記該臺的後端設備調度
三、redir <prefix>:將發往此server的全部GET和HEAD類的請求重定向至指定的URL,用戶發請求,發到其它服務器,後面的地址必須是外網ip地址
一、cookie <value>:爲當前server指定cookie值,實現基於cookie的會話黏性
cookie <name> [ rewrite | insert | prefix ] [ indirect ] [ nocache ] [ postonly ] [ preserve ] [ httponly ] [ secure ] [ domain <domain> ]* [ maxidle <idle> ] [ maxlife <life> ]
nocache:當client和hapoxy之間有緩存時,不緩存cookie
server srv1 172.16.0.6:80 weight 2 check rise 1 fall 2 maxconn 3000 cookie srv1
server srv2 172.16.0.7:80 weight 1 check rise 1 fall 2 maxconn 3000 cookie srv2
以後訪問http://ip/haproxy?stats,即出現
自定義stats page uri,默認值:/haproxy?stats
認證時的realm,示例:stats realm : HAProxy\ Statistics
認證時的帳號和密碼,可以使用屢次,默認:no authentication
七、stats admin { if | unless } <cond>
stats realm HAPorxy\ Stats\ Page
一、maxconn <conns>:爲指定的frontend定義其最大併發鏈接數;默認爲3000
tcp:基於layer4實現代理;可代理mysql, pgsql, ssh, ssl等協議,https時使用此模式,默認模式
http:僅當代理協議爲http時使用,CentOS中haproxy實際的默認模式
health:工做爲健康狀態檢查的響應模式,當鏈接請求到達時迴應「OK」後即斷開鏈接,較少使用
server sshsrv1 172.16.0.6:22 check
server sshsrv2 172.16.0.7:22 check
對後端服務器作http協議健康狀態檢測:一般用於bendend
option httpchk 默認向後端服務器發請求:OPTIONS / HTTP/1.0
option httpchk <method> <uri> <version>
http-check expect [!] <match> <pattern>
一、option forwardfor [ except <network> ] [ header <name> ] [ if-none ]
在由haproxy發日後端主機的請求報文中添加「X-Forwarded-For」首部,其值爲前端客戶端的地址;用於向後端主發送真實的客戶端IP
在後端RS服務器上/etc/httpd/conf/httpd.conf中,添加X-Forwarded-For
[ except <network> ]:請求報請來自此處指定的網絡時不予添加此首部,
[ header <name> ]:使用自定義的首部名稱,而非「X-Forwarded-For」
[ if-none ] 若是沒有首部才添加首部,若是有使用默認值
compression algo <algorithm> ...:啓用http協議的壓縮機制,指明壓縮算法gzip, deflate
compression type <mime type> ...:指明壓縮的MIMI類型
一、errorfile <code> <file> 自定義錯誤頁
支持200, 400, 403, 408, 500, 502, 503, 504.
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
至關於errorloc302 <code> <url>,利用302重定向至指URL
示例:errorloc 503 http://www.chenux.com/error_pages/503.html
reqadd <string> [{if | unless} <cond>]
rspadd <string> [{if | unless} <cond>]
reqdel <search> [{if | unless} <cond>]
reqidel <search> [{if | unless} <cond>] 不分大小寫
rspdel <search> [{if | unless} <cond>]
rspidel <search> [{if | unless} <cond>] 不分大小寫
三、timeout http-keep-alive <timeout>
四、timeout http-request <timeout>
六、timeout client-fin <timeout>
七、timeout server-fin <timeout>
一、acl:訪問控制列表(ACL)的使用提供了一個靈活的解決方案來執行內容交換,而且一般基於從請求中提取的內容、響應或任何環境狀態進行決策
二、acl <aclname> <criterion> [flags] [operator] [<value>] ...
<aclname>:ACL名稱,可以使用字母 數字 : . - _ ,區分字符大小寫
- string (exact, substring, suffix, prefix, subdir, domain)
-u 強制每一個ACL必須惟一ID,不然多個同名ACL或關係
- 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進行匹配
示例:if invalid_src invalid_port 與關係
if invalid_src || invalid_port 或
示例:acl invalid_src src 172.16.100.200
返回第一個主機頭和請求的路徑部分的鏈接,該請求從第一個斜槓開始,並在問號以前結束,對虛擬主機有用
<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>
(7)path : string,官方建議最好用path,比url好用
提取請求的URL路徑,該路徑從第一個斜槓開始,並在問號以前結束(無主機部分) <scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>
/images/jpegs/20180123/logo.jpg
提取請求中的URL。一個典型的應用是具備預取能力的緩存,以及須要從數據庫聚合多個信息並將它們保存在緩存中的網頁門戶入口,推薦使用path
(9)req.hdr([<name>[,<occ>]]) : string
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 wegt
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_HEAD |
method HEAD |
match HTTP GET 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 |
(1)use_backend <backend> [{if | unless} <condition>]
當if/unless一個基於ACL的條件匹配時切換指定backend
(2)block { if | unless } <condition>
acl invalid_src src 172.16.200.2
errorfile 403 /usr/share/haproxy/403.http
(3)http-request { allow | deny |add-header <name> <fmt> |set-header <name> <fmt> } [ { if | unless } <condition> ]
(4)tcp-request connection {accept|reject} [{if | unless} <condition>]
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
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
server staticsrv1 192.168.0.100:80 check
server app1 192.168.0.101:80 check
server app1 192.168.0.102:8080 check
bind *:443 ssl crt /PATH/TO/SOME_PEM_FILE
cat demo.crt demo.key > demo.pem
redirect scheme https if !{ ssl_fc }
四、向後端傳遞用戶請求的協議和端口(frontend或backend),加入此項意義在於抓取log時便於查看
http_request set-header X-Forwarded-Port %[dst_port]
http_request add-header X-Forwared-Proto https if { ssl_fc }
注意:若是按照以往方法是生成a.key和a.crt,將它們用cat a.key a.crt > a.pem就能夠合到一塊兒,a.pem裏面包含證書和私鑰
二、更改haproxy配置文件,此時curl -k http和https都能通,但curl -k http時沒有實現跳轉