Haproxy

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計算能力也越多


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