Haproxy 使用攻略

前言

        HAProxy是法國人Willy Tarreau開發的一款可應對客戶端10000以上的同時連接的高性能的TCP和

HTTP負載均衡器。由於其豐富強大的功能在國內備受推崇,是目前主流的負載均衡器。本文介紹其功能特性並結合配置實例演示,如有錯誤敬請賜教。

Haproxy主要工作位置:

743f0304584c87cbedbe4c72fbc60c48.png

1. 支持http反向代理

2. 支持動態程序的反向代理

3. 支持基於數據庫的反向代理


Haproxy 程序組成:

程序環境:

    安裝:yum install haproxy -y

    主程序: /usr/sbin/haproxy

    配置文件: /etc/haproxy/haproxy.cfg

    主配置文件主要結構:1. global 全局配置段 2. proxies代理配置段

索引


1. global:全局配置段配置

        1.1 全局日誌配置

        1.2 性能調整常見參數

2.proxies:代理配置段結構

3.實現簡單proxy配置實驗

        3.1 方法1

        3.2 方法2

4.代理配置段常見配置參數

        4.1 Balance調度算法相關

        4.2 server:定義後端主機相關選項

        4.3 實現圖形化配置頁

        4.4 default默認配置中定義的內容

        4.5 forwardfor後端記錄真實請求配置

        4.6 自定義錯誤頁面

        4.7 自定義修改報文首部

        4.8 自定義連接超時相關配置

5. ACL靈活轉發詳解

        5.1 acl語法

        5.2 匹配條件<criterion>進階

        5.3 acl作爲條件時的邏輯關係

        5.4 系統預定義ACL(部分)

        5.5 配置block拒絕訪問

        5.6 指定backend組

        5.7 http 7層訪問控制

        5.8 tcp 4層連接控制

        5.9 配置HAProxy支持https協議

6. 附實現動靜分離實驗示例



1. global:全局配置段


1.1 log:全局日誌配置

默認發往本機的日誌服務器;

(1) 系統默認:log         127.0.0.1 local2

發往遠端可添加:log          遠端IP  local2

(2) 修改本機日誌配置文件:

vim  /etc/rsyslog.conf

$ModLoad imudp          #取消註釋

$UDPServerRun 514    #取消註釋

local2.*                                                /var/log/haproxy.log  #新增

(3) 遠端日誌配置(配合前端log配置)

vim  /etc/rsyslog.conf

local2.*                                                /var/log/haproxy.log  #新增


1.2 性能調整(依據生產環境適當調整):

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

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

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

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

    spread-checks <0..50, in percent> 健康檢測延遲時長比建議2-5之間

2.proxies:代理配置段結構


    (1). defaults:爲frontend, backend, listen提供默認配置

    (2). fronted:前端,指定接收客戶端連接偵聽套接字設置

    (3). backend:後端,指定將連接請求轉發至後端服務器的相關設置

    (4). listen:同時擁有前端和後端,適用於一對一環境

3.實現簡單proxy配置:


實驗拓撲:

188e49f54bfb5f396cb4b7f23b2cec2f.png

3.1  方法一:

配置 /etc/haproxy/haproxy.cfg :

將frontend段、backend段註釋,新建如下配置

frontend http *:80                #均衡器端採用http 協議,監聽80端口

       default_backend websrvs   #引用後端自定義服務器組名websrvs

backend websrvs                   #設定默認後端,自定義名字爲websrvs

       balance roundrobin        #輪詢方式爲加權輪詢

       server web1 192.168.43.61:80 check    #設定後端服務器IP ,並引入健康檢查

       server web2 192.168.43.63:80 check    #設定後端服務器IP ,並引入健康檢查


service haproxy start

在瀏覽器訪問http://172.18.43.62 刷新即可看到輪詢效果

314d10035417a3485601bf8f2020d70d.gif

3.2 方法2:

上面兩段配置也可以配置在一段實現相同功能,配置如下:

listen http

       bind :80

       balance roundrobin

       server web1 192.168.43.61:80 check

       server web2 192.168.43.63:80 check

配置參數 bind:指定一個或多個前端偵聽地址和端口

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

示例:

    listen http_proxy

    bind :80,:443

    bind 10.0.0.1:10080,10.0.0.1:10443

4.代理配置段常見配置參數


4.1Balance相關

balance:後端服務器組內的服務器調度算法

語法: balance <algorithm> [ <arguments> ]

           balance url_param <param> [check_post]

調度算法:

① roundrobin:基於權重輪詢,動態算法, 支持權重的運行時調整,支持慢啓動;每個後端backend中最多支持4095個server

    server options: weight #

② static-rr:基於權重輪詢,靜態算法,不支持權重的運行時調整及慢啓動;後端主機數量無上限

③ leastconn:加權最少連接,動態算法,最少連接的後端服務器優先分配接收新連接,相同連接時輪詢,推薦在較長會話的場景使用,例如MySQL、 LDAP等,不適合http。

④ first:根據服務器在列表中的位置,自上而下進行調度;前面服務器的連接數達到上限,新請求才會分配給下一臺服務器。

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

例:hdr(host)     hdr(Cookie)

⑤ rdp-cookie 遠程桌面相關

hash類算法:

需配合參數:hash-type <method> <function> <modifier>

method:

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

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

⑥ source:源地址hash,新連接先按權重分配,後續連接按source分配請求

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

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

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

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

⑧ url_param:對用戶請求的uri聽<params>部分中的參數的值(通常爲用戶ID)作hash計算,並由服務器總權重相除以後派發至某挑出的服務器;通常用於追蹤用戶,以確保來自同一個用戶的請求始終發往同一個Backend Server。


4.2 server:定義後端主機相關選項

語法:

server <name> <address>[:[port]] [param*]

    <name>:服務器在haproxy上的自定義名稱;出現在日誌及警告信息

    <address>:服務器地址,支持使用主機名

    [:[port]]:端口映射;省略時,表示同bind中綁定的端口

[param*]:server後可加的參數

weight <weight>:權重,默認爲1

maxconn <maxconn>:當前server的最大併發連接數

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

backup:設定當前server爲備用服務器

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

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

        addr :檢測時使用的IP地址(檢測的不一定是vip)

        port :針對此端口進行檢測

        inter <delay>:連續兩次檢測之間的時間間隔,默認單位爲毫秒,默認爲2000ms

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

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

disabled:標記爲不可用

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

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

基於cookie的session sticky的實現:

frontend http

bind 172.18.43.62:80              

       default_backend websrvs  

backend websrvs                  

       balance roundrobin

cookie SRV insert nocache

#自定義會話添加cookie信息SRV,insert:插入 nocache:不緩存增加保密性    

       server web1 192.168.43.61:80 check   weight 2 cookie srv1 #自定義該server添加cookie信息爲srv1

       server web2 192.168.43.63:80 check   maxconn 5000 cookie srv2 #自定義該server添加cookie信息爲srv2

server sorroyserver 192.168.43.62:80 backup

4.3 實現圖形化配置頁面

stats enable 添加這條參數後會在web頁面啓用統計頁;參數可放置位置。

4d877418400ed79dc2bb3414a3ea8595.png

我們在frontend段添加stats enable ,重啓haproxy。瀏覽器訪問172.18.43.62/haproxy?stats即可

4f35e774e33d534d823369112f870fb4.png

相關參數:

① stats refresh <delay>設定自動刷新時間間隔

若服務器出現故障,默認手動刷新才能才能看到狀態的變化,可設置自動刷新

    例:添加stats refresh 2s

② stats uri <prefix> 自定義stats page uri

默認爲/haproxy?stats 可自定義uri

    例:stats uri  /hastas

重啓後訪問http://172.18.43.62/hastas即可

③ stats hide-version

如上圖所示界面會顯示haproxy版本信息,若想隱藏版本加上此參數即可

④ stats auth <user>:<passwd> 認證時的賬號和密碼,可使用多次。如多個用戶定義多行即可,例:

    stats auth ha1:centos1

    stats auth ha2:centos2

⑤ stats realm <realm> 認證時瀏覽器彈出對話框的提示信息

    例:stats realm "haproxy info"

⑥ stats admin { if | unless } <cond> 啓用stats page中的管理功能

    例:stats  admin  if TRUE

將stats分離出單獨語句塊,採用內網的6666端口提高訪問安全性示例:

listen admin

       bind 192.168.43.62:6666

       stats enable

       stats uri /status

       stats realm "haproxy info"

       stats auth ha1:centos

       stats hide-version

       stats refresh 5s

       stats admin if TRUE

從內網訪問界面:

f04748c9dbe47de2f754f15fe1103c62.png


4.4 default中定義的內容

可以在frontend、backend、listen中分別進行定義,如沒有指定將默認default中設置,如:

    maxconn <conns>:爲指定的frontend定義其最大併發連接數;默認爲3000

    mode { tcp|http|health } 定義haproxy的工作模式(默認http)

        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


4.5 forwardfor配置

語法 :option forwardfor [ except <network> ] [ header <name> ] [ if-none ]

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

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

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

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

默認defaults中有一條配置option forwardfor       except 127.0.0.0/8

若想後端日誌記錄真實請求客戶端IP,需更改後端兩臺服務器配置文件:

vim /etc/httpd/conf/httpd.conf

LogFormat "%{x-forwarded-for}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" haformat

#添加日誌格式

CustomLog logs/access_log haformat #修改記錄日誌

重載客戶端httpd服務,瀏覽器刷新請求。在客戶端觀看日誌即可看到真實請求服務器

tail -f /var/log/httpd/access_log


4.6 自定義錯誤頁面

① errorfile <code> <file> 自定義錯誤頁

        <code>: HTTP status code.  支持200, 400, 403, 408, 500, 502, 503, 504.

        <file>:錯誤頁文件路徑

    例:errorfile 400 /etc/haproxy/errorfiles/400badreq.http

② rrorloc <code> <url>       相當於errorloc302 <code> <url>,利用302重定向至指URL

    例:errorloc 503 http://www.magedu.com/error_pages/503.html

4.7修改報文首部

① reqadd <string> [{if | unless} <cond>]    在請求報文尾部添加指定首部(用於web端區分從哪個調度器發來請求)

例:在frontend中添加  reqadd  X-via:\  haproxy1

後端修改httpd.conf中logformat添加%{X-via}i

再次訪問日誌就會看到是通過哪個調度器調度到本機

② rspadd <string> [{if | unless} <cond>]  在響應報文尾部添加指定首部 (用於haproxy之前的調度器查看用於排錯)

示例: 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.*  用於隱藏web服務器版本信息

rspadd Server:\ Apache 15.1 結合上例可僞造server信息

4.8 定義連接超時

① 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>     後端服務器半連接的空閒時長

5. ACL靈活轉發詳解


    acl:訪問控制列表(ACL)的使用提供了一個靈活的解決方案來執行內容交換,並且通常基於從請求中提取的內容、響應或任何環境狀態進行決策,是haproxy的重要特色。

5.1 語法

acl <aclname> <criterion> [flags] [operator] [<value>]...

<aclname>: ACL名稱,可使用字母 數字 : . - _區分字符大小寫

<criterion>: 比較的標準和條件

        dst 目標IP

        dst_port 目標PORT

        src 源IP

        src_port 源PORT

        示例: acl invalid_src src 172.16.100.200

<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進行匹配

<value>的類型:

    - boolean

    - integer or integer range

    - IP address / network

    - string (exact, substring, suffix, prefix, subdir,domain)

    - regular expression

    - hex block

5.2 匹配條件<criterion>進階:

(1)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

(2)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

例:acl adminpath path_beg  -i  /admin

acl imagefile  path_end  .jpg  .png   .bmp

(3)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

(4)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

(5)status : integer

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

5.3 acl作爲條件時的邏輯關係:

    - 與:隱式(默認)使用

    - 或:使用“or” 或 “||”表示

    - 否定:使用“!“ 表示

    同一個組名可定義多次

示例: if invalid_src invalid_port 與關係

    if invalid_src || invalid_port 或

    if ! invalid_src 非

5.4 預定義ACL(部分)


ACL名稱


等價於


說明

TRUE

always_true

總是匹配

FALSE

always_false

從不匹配

HTTP_1.1

req_ver 1.1

匹配HTTP協議1.1

HTTP

req_proto_http

匹配HTTP協議


LOCALHOST


src 127.0.0.1/8


匹配從localhost來的連接


METH_CONNECT


method CONNECT


匹配HTTP CONNECT方法


5.5 配置block拒絕訪問

語法:block { if | unless } <condition>   阻止7層請求if/unless一個條件匹配

例1:

frontend http

acl deny_src src 172.18.0.108

#自定義源地址爲172.18.0.108的acl組deny_src

acl deny_port dst_port 80:100

#自定義目標端口爲80到100的acl組deny_port

block if deny_src || deny_port

#如果屬於deny_src組或deny_port組則拒絕訪問

block unless deny_src #如果不屬於acl組deny_src則拒絕訪問

例2(阻止curl訪問):

acl bad_curl hdr_sub(User-Agent) -i curl

block if bad_curl

5.6 指定backend組

語法:use_backend <backend> [{if | unless} <condition>]

當if/unless一個基於ACL的條件匹配時切換指定backend(可實現動靜分離)

例1:

acl imagefile path_end .jpg .png .bmp

acl appfile path_end .php

use_backend websrvs1 if imagefile

use_backend websrvs2 if appfile

例2:

c5fef4468179549fcf11189ba91dd2a7.png

例3:

acl webhost hdr(host) web.51cto.com

acl apphost hdr(host) app.51cto.com

use_backend websrvs if webhost

use_backend appsrvs if apphost

5.7 http 7層訪問控制

語法:http-request { allow | deny |add-header <name> <fmt>|set-header <name> <fmt> } [ { if | unless }<condition> ]

對7層請求的訪問控制

5.8 tcp4層連接控制

語法: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

5.9 配置HAProxy支持https協議:

① 支持ssl會話;

bind *:443 ssl crt /PATH/TO/SOME_PEM_FILE

crt 後證書文件爲PEM格式,且同時包含證書和所有私鑰

爲實驗方便自簽證書方法:

在etc/pki/tls/certs/目錄下執行make命令可獲得同時包含證書和所有私鑰的證書

cd /etc/pki/tls/certs/

make /etc/haproxy/haproxy.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 }

例:

7dab8d539d8a4950e699f5d01aefcb2b.png

測試:

d8ee09f8d38dd3c8eba108dc29dcdd21.png

向後端傳遞用戶請求:

1951c8ca50aada1346d93e331448c3dc.png

修改後端httpd.conf中日誌格式即可

004ef390aaebed03cbd503241ae56f6f.png

6. 附基於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



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章