HAproxy(反向代理)

1.HAProxy介紹

? HAProxy: 是法國人Willy Tarreau開發的一個開源軟件,是 一款應對客戶端10000以上的同時連接的高性能的TCP
和 HTTP負載均衡器。其功能是用來提供基于cookie持久性, 基于內容的交換,過載保護的高級流量管制,自動故障切換 ,
以正則表達式為基礎的標題控制運行時間,基于Web的報 表,高級日志記錄以幫助排除故障的應用或網絡及其他功能 
? 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反向代理服務器,尤其適合于高可用 性環境 
  ● 可以針對HTTP請求添加cookie,進行路由后端服務器 
  ● 可平衡負載至后端服務器,并支持持久連接 
  ● 支持基于cookie進行調度 
  ● 支持所有主服務器故障切換至備用服務器 
  ● 支持專用端口實現監控服務 
  ● 支持不影響現有連接情況下停止接受新連接請求
  ● 可以在雙向添加,修改或刪除HTTP報文首部 
  ●  支持基于pattern實現連接請求的訪問控制 
  ●  通過特定的URI為授權用戶提供詳細的狀態信息 
? 版本:1.4 1.5 1.6 1.7 1.8

clipboard.png

2.Haproxy功能

● 支持http反向代理
● 支持動態程序的反向代理
● 支持基于數據庫的反向代理


clipboard1.png

3. HAProxy組成

https://cbonte.github.io/haproxy-dconv/

clipboard2.png

? 程序環境: 
                  主程序:/usr/sbin/haproxy 
                   配置文件:/etc/haproxy/haproxy.cfg 
                   Unit file:/usr/lib/systemd/system/haproxy.service
? 配置段:
  ● global:全局配置段 
                       進程及安全配置相關的參數 
                         性能調整相關參數 
                         Debug參數 
  ● proxies:代理配置段
                        defaults:為frontend, backend, listen提供默認配置 
                         fronted:前端,相當于nginx, server {} 
                         backend:后端,相當于nginx, upstream {} 
                         listen:同時擁有前端和后端,適用于一對一環境 (最好前后端分開,以后 
                                                                                                                               好調整)
? 簡單的配置示例:
             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狀態

eg:


clipboard3.png

clipboard4.png
clipboard5.png

4.global配置 :

    global配置參數: 
            進程及安全管理:chroot, deamon,user, group, uid, gid 
nbproc  :要啟動的haproxy的進程數量,系統 默認單進程,要求使用daemon模式
ulimit-n :每個haproxy進程可打開的最大文件數,系統自動會指定,不建議設置 
daemon:后端方式運行,建議使用 
log:定義全局的syslog服務器;最多可以定義兩個
log <address> [len <length>] <facility>[max level [min level]] 
address: rsyslog服務器地址 
len: 記錄日志的長度,默認1024 10 

5.日志系統

log:  
        log global
        log <address> [len <length>] <facility>[<level>[<minlevel>]]
               no log 
               注意:                   
                      默認發往本機的日志服務器; 
                      (1) local2.* /var/log/local2.log 
                      (2)#vim /etc/rsyslog.conf
                           $ModLoad imudp
                           $UDPServerRun 514 
? log-format  <string>: 

課外實踐:參考文檔實現combined格式的記錄
記錄日志到本機


clipboard6.png
clipboard7.png
clipboard8.png
clipboard9.png

存放日志到遠程服務器


clipboard10.png
clipboard11.png
clipboard12.png
clipboard13.png

6.日志管理

將特定信息記錄在日志中

? capture cookie len <name> len <length>

捕獲請求和響應報文中的 cookie并記錄日志

? capture request header <name> len <length>

捕獲請求報文中指定的首部并記錄日志

示例: capture request header X-Forwarded-For len

? capture response header <name> len <length>

捕獲響應報文中指定的首部并記錄日志

示例: capture response header Content-length len 9

capture response header Location len 15

7.性能調整

性能調整:

maxconn <number>:設定每個haproxy進程所能接受的最大并發連接數

maxconnrate <number>:設置每個進程每秒種所能建立的最大連接數量

maxsessrate <number>:設置每個進程每秒種所能建立的最大會話數量

maxsslconn <number> : 每進程支持SSL的最大連接數量

spread-checks <0..50, in percent> 健康檢測延遲時長百分比

建議2%-5%之間

8.配置段

*   代理配置段:

- defaults

- frontend

- backend

- listen

? Frontend段:指定接收客戶端連接偵聽套接字設置

? Backend段:指定將連接請求轉發至后端服務器的相關設置

? Listen段:指定完整的前后端設置,只對 TCP 有效

? proxy 名稱:使用字母 數字 - _ . : 并區分字符大小寫

9.配置參數

? bind:指定一個或多個前端偵聽地址和端口

bind [<address>]:<port_range> [, ...] [param*]

? 示例:

listen http_proxy

bind :80,:443 監聽所有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:后端服務器組內的服務器調度算法

? 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分配 請求 16 Balance配置

*   uri: 對URI的左半部分或整個uri做hash計算,并除以服務器總權 重取模,以后派發至某挑出的服務器,適用于后端緩存服務器

<scheme>://<user>:<passwd>@<host>:<port>/<path>;<params>?<query>#<frag>

左半部分:/<path>;<params>

整個uri:/<path>;<params>?<query>#<frag>

*   url_param: 對用戶請求的uri聽部分中的參數的值作hash計算,并由服務器總權重相除以后派發至某挑出的服務器;通常用于追蹤用 戶,以確保來自同一個用戶請求始終發往同一個Backend Server

*   hdr():對于每個http請求,此處由<name>指定的 http首部將會被取出做hash計算; 并由服務器總權重相除以后派發至某挑出的服務器;無有效值的會被輪詢調度

hdr(Cookie)

*   rdp-cookie 遠程桌面相關

*   rdp-cookie()

11.哈希算法

? hash-type:哈希算法

hash-type <method> <function> <modifier>

method:

map-based:除權取余法,哈希數據結構是靜態數組

consistent:一致性哈希,哈希數據結構是一棵樹

<function> : 哈希函數

sdbm djb2 wt6

? 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 :權重,默認為1

maxconn :當前server的最大并發連接數

backlog :當server的連接數達到上限后的后援隊列長度

backup:設定當前server為備用服務器 20 健康狀態檢測

? check:對當前server做健康狀態檢測,只用于四層檢測

注意:httpchk, “smtpchk”, “mysql-check”, “pgsql-check” and “sslhello-chk” 用于定義應用層檢測方法

addr :檢測時使用的IP地址

port :針對此端口進行檢測

inter <delay> :連續兩次檢測之間的時間間隔,默認為2000ms

rise <count>:連續多少次檢測結果為“成功”才標記服務器為可用 ;默認為2

fall <count>:連續多少次檢測結果為“失敗”才標記服務器為不可 用;默認為3

cookie <value>:為當前server指定cookie值,實現基于cookie的會話黏性

disabled:標記為不可用

redir <prefix>:將發往此server的所有GET和HEAD類的請求重定向至指定的URL

12.cookie配置

? cookie <name> [ rewrite | insert | prefix ] [ indirect ] [ nocache ] [ postonly ] [ preserve ] [ httponly ] [ secure ] [ domain ]* [ maxidle ] [ maxlife <life> ]

<name> :cookie名稱,用于實現持久連接

rewrite:重寫

insert:插入

prefix:前綴

配置示例

? 基于cookie的session sticky的實現:

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. 統計接口啟用相關的參數

? stats enable

啟用統計頁;基于默認的參數啟用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>

設定自動刷新時間間隔

? 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定義其最大并發連接 數;默認為2000

? mode { tcp|http|health }

定義haproxy的工作模式

tcp:基于layer4實現代理;可代理mysql, pgsql, ssh, ssl等協議,https時使用此模式,默認模式

http:僅當代理協議為http時使用,centos實際默認模式

health:工作為健康狀態檢查的響應模式,當連接請求到達時回應“OK”后即斷開連接,較少使用

TCP模式的健康狀態檢測示例
? 示例:

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.健康狀態檢測

? 對后端服務器做http協議的健康狀態檢測:

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協議健康狀態檢測響應內容或指定響應碼

16.forwardfor配置

? option forwardfor [ except <network> ] [ header <name> ] [ if-none ]

在由haproxy發往后端主機的請求報文中添加“X-ForwardedFor”首部,其值為前端客戶端的地址;用于向后端主發送真實的客戶端IP

[ except <network> ]:請求報請來自此處指定的網絡時不予 添加此首部,如haproxy自身所在網絡

[ header <name> ]:使用自定義的首部名稱,而非“XForwarded-For”

[ if-none ] 如果沒有首部才添加首部,如果有使用默認值

? 為指定的MIME類型啟用壓縮傳輸功能

compression algo ...:啟用http協議的壓縮機 制,指明壓縮算法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>

相當于errorloc302 ,利用302重定向至指URL

errorloc 503 http://www.magedu.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> ] (ignore case) 不分大小寫

從請求報文中刪除匹配正則表達式的首部

*   rspdel <search> [{if | unless} <cond> ]

*   rspidel <search> [{if | unless} <cond> ] (ignore case) 不分大小寫

從響應報文中刪除匹配正則表達式的首部

示例: 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> 后端服務器半連接的空閑時長

18.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

?<flag>

-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>:<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路徑,該路徑從第一個斜杠開始,并在問號之 前結束(無主機部分)

<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。一個典型的應用是具有預取能力的緩存, 以及需要從數據庫聚合多個信息并將它們保存在緩存中的網頁門戶入 口

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

返回在響應報文中的狀態碼

*   預定義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方法

*   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>]

當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> ]

根據第4層條件對傳入連接執行操作

? 示例: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協議

? 配置HAProxy支持https協議:

? 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 向后端傳遞用戶請求的協議和端口(frontend或backend)

http_request set-header X-Forwarded-Port %[dst_port]

http_request add-header X-Forwared-Proto https if { ssl_fc }
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容