Haproxy[轉載]

原文地址:http://www.javashuo.com/article/p-bvbyaiwl-cg.html

HAProxy

HAProxy介紹

HAProxy: 是法國人Willy Tarreau開發的一個開源軟件,是一款應對客戶端10000以上的同時鏈接的高性能的TCP和 HTTP負載均衡器。其功能是用來提供基於cookie的持久性, 基於內容的交換,過載保護的高級流量管制,自動故障切換 ,以正則表達式爲基礎的標題控制運行時間,基於Web的報表,高級日誌記錄以幫助排除故障的應用或網絡及其餘功能。javascript

相關概念

代理的做用

  1. 正向代理,反向代理
  2. 代理服務器,能夠提供緩存功能加速客戶端訪問,同時能夠對緩存數據進行有效性檢查
  3. 內容路由:根據流量以及內容類型將請求轉發至特定的服務器
  4. 轉碼器:支持壓縮功能,將數據以壓縮形式發送給客戶端

緩存的做用

  1. 減小訪冗餘內容傳輸
  2. 節省帶寬,緩解網絡瓶頸
  3. 下降了對原始服務器的請求壓力
  4. 下降了傳輸延遲

負載均衡集羣:

四層:
lvs, nginx(stream),haproxy(mode tcp)
七層:
http: nginx(http, ngx_http_upstream_module), haproxy(mode http), httpd, ats, perlbal, pound...css

HAProxy功能

HAProxy是TCP / HTTP反向代理服務器,尤爲適合於高可用性環境
能夠針對HTTP請求添加cookie,進行路由後端服務器
可平衡負載至後端服務器,並支持持久鏈接
支持基於cookie進行調度
支持全部主服務器故障切換至備用服務器
支持專用端口實現監控服務
支持不影響現有鏈接狀況下中止接受新鏈接請求
能夠在雙向添加,修改或刪除HTTP報文首部
支持基於pattern實現鏈接請求的訪問控制
經過特定的URI爲受權用戶提供詳細的狀態信息
版本:1.4 1.5 1.6 1.7 1.8
html

支持http反向代理
支持動態程序的反向代理
支持基於數據庫的反向代理前端

HAproxy組成

包名:haproxyjava

程序環境

主程序:/usr/sbin/haproxy
配置文件:/etc/haproxy/haproxy.cfg
Unit file:/usr/lib/systemd/system/haproxy.servicemysql

配置文件

haproxy.cfg主要有兩部分組成:global,和proxies配置段nginx

global:全局配置段

進程及安全配置相關的參數
性能調整相關參數
Debug參數web

proxies:代理配置段

defaults:爲frontend, backend, listen提供默認配置
fronted:前端,至關於nginx, server {}
backend:後端,至關於nginx, upstream {}
listen:同時擁有前端和後端,適用於一對一環境正則表達式

簡單前端調度實現

利用四臺虛擬機實現簡單的前端輪詢調度。
一臺客戶端,一臺haproxy調度器,兩臺RSredis

  1. 首先在後端部署兩臺http服務
  2. 編輯haproxy配置文件/etc/haproxy/haproxy.cfg
    默認設置不作修改

    [root@CentOS6 ~]# vim /etc/haproxy/haproxy.cfg frontend main *:80 #設置監聽ip:端口 default_backend websrvs #調用後端RS組名 backend websrvs balance roundrobin #輪詢算法 server web1 192.168.45.11:80 check server web2 192.168.45.12:80 check

配置

global配置參數:

global      # 全局參數的設置 log 127.0.0.1 local2 # log語法:log <address_1>[max_level_1] # 全局的日誌配置,使用log關鍵字,指定使用127.0.0.1上的syslog服務中的local0日誌設備,記錄日誌等級爲info的日誌 chroot /var/lib/haproxy #改變當前工做目錄 pidfile /var/run/haproxy.pid #當前進程id文件 maxconn 4000 #最大鏈接數 user haproxy #所屬用戶 group haproxy #所屬組 daemon #以守護進程方式運行haproxy stats socket /var/lib/haproxy/stats #基於本地的文件傳輸

實現日誌記錄:
haproxy配置文件中默認定義了log 127.0.0.1 local2 說明日誌將被記錄在本機的local2設施中。
編輯rsyslog配置文件:

[root@CentOS6 ~]#vim /etc/rsyslog.conf # Provides UDP syslog reception $ModLoad imudp #取消註釋 $UDPServerRun 514 #取消註釋 local2.* /var/log/haproxy.log #指定設備local2日誌存放位置

haproxy的日誌信息能夠設置存放在專門的日誌服務器中

proxies配置參數:

代理配置段:

  • defaults <name>
  • frontend <name>
  • backend <name>
  • listen <name>

Frontend段:指定接收客戶端鏈接偵聽套接字設置
Backend段:指定將鏈接請求轉發至後端服務器的相關設置
Listen段:指定完整的先後端設置,只對 TCP 有效
proxy 名稱:使用字母 數字 - _ . : 並區分字符大小寫

mode        http             
#默認的模式mode { tcp|http|health },tcp是4層,http是7層,health只會返回OK log global #應用全局的日誌配置 option httplog # 啓用日誌記錄HTTP請求,默認haproxy日誌記錄是不記錄HTTP請求日誌 option dontlognull # 啓用該項,日誌中將不會記錄空鏈接。所謂空鏈接就是在上游的負載均衡器或者監控系統爲了探測該服務是否存活可用時,須要按期的鏈接或者獲取某一固定的組件或頁面,或者探測掃描端口是否在監聽或開放等動做被稱爲空鏈接;官方文檔中標註,若是該服務上游沒有其餘的負載均衡器的話,建議不要使用該參數,由於互聯網上的惡意掃描或其餘動做就不會被記錄下來 option http-server-close #每次請求完畢後主動關閉http通道 option forwardfor except 127.0.0.0/8 #若是服務器上的應用程序想記錄發起請求的客戶端的IP地址,須要在HAProxy上配置此選項, 這樣 HAProxy會把客戶端的IP信息發送給服務器,在HTTP請求中添加"X-Forwarded-For"字段。啓用X-Forwarded-For,在requests頭部插入客戶端IP發送給後端的server,使後端server獲取到客戶端的真實IP。 option redispatch #當使用了cookie時,haproxy將會將其請求的後端服務器的serverID插入到cookie中,以保證會話的SESSION持久性;而此時,若是後端的服務器宕掉了, 可是客戶端的cookie是不會刷新的,若是設置此參數,將會將客戶的請求強制定向到另一個後端server上,以保證服務的正常。 retries 3 # 定義鏈接後端服務器的失敗重連次數,鏈接失敗次數超過此值後將會將對應後端服務器標記爲不可用 timeout http-request 10s #http請求超時時間 timeout queue 1m #一個請求在隊列裏的超時時間 timeout connect 10s #鏈接超時 timeout client 1m #客戶端超時 timeout server 1m #服務器端超時 timeout http-keep-alive 10s #設置http-keep-alive的超時時間 timeout check 10s #檢測超時 maxconn 3000 #每一個進程可用的最大鏈接數 frontend main *:80 #監聽地址爲80 acl url_static path_beg -i /static /images /javascript /stylesheets acl url_static path_end -i .jpg .gif .png .css .js use_backend static if url_static default_backend my_webserver #定義一個名爲my_app前端部分。此處將對應的請求轉發給後端 backend static #使用了靜態動態分離(若是url_path匹配 .jpg .gif .png .css .js靜態文件則訪問此後端) balance roundrobin #負載均衡算法(#banlance roundrobin 輪詢,balance source 保存session值,支持static-rr,leastconn,first,uri等參數) server static 127.0.0.1:80 check #靜態文件部署在本機(也能夠部署在其餘機器或者squid緩存服務器) backend my_webserver #定義一個名爲my_webserver後端部分。PS:此處my_webserver只是一個自定義名字而已,可是須要與frontend裏面配置項default_backend 值相一致 balance roundrobin #負載均衡算法 server web01 172.31.2.33:80 check inter 2000 fall 3 weight 30 #定義的多個後端 server web02 172.31.2.34:80 check inter 2000 fall 3 weight 30 #定義的多個後端 server web03 172.31.2.35:80 check inter 2000 fall 3 weight 30 #定義的多個後端

Balance配置

balance:後端服務器組內的服務器調度算法
balance <algorithm> [ <arguments> ]
balance url_param <param> [check_post]
haproxy中調度算法一樣分爲動態調度算法和靜態調度算法,與nginx調度算法中區分動靜態調度算法的概念不一樣,nginx用能不能根據後端服務器的負載情況進行調度來區分動靜態調度算法的差異,而haproxy中則根據該算法支不支持運行時即時生效來區分動靜態算法。

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

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

leastconn:加權最少鏈接,動態算法,最少鏈接的後端服務器優先分配接收新鏈接,相同鏈接時輪詢,適用於長鏈接場景,例如 MySQL、LDAP等,不適合http

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

source:源地址hash,新鏈接先按權重分配,後續鏈接按source分配請求
動靜態取決於hash type
hash-type:哈希算法
hash-type <method> <function> <modifier>
method:
map-based:除權取餘法,哈希數據結構是靜態數組(不支持權重動態調整)
consistent:一致性哈希,哈希數據結構是一棵樹 (支持權重動態調整)
<function> : 哈希函數
sdbm djb2 wt6

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

hash-type map-based consistent

<scheme>://<user>:<password>@<host>:<port>/<path> ;<params>?<query>#<frag>
左半部分:/<path>;<params>
整個uri:/<path>;<params>?<query>#<frag>

url_param:
對用戶請求的uri聽<params>部分中的參數的值做hash計算, 並由服務器總權重相除之後派發至某挑出的服務器;一般用於追蹤用戶,以確保來自同一個用戶的請求始終發往同一個Backend Server
動靜態取決於hash type

hash-type map-based consistent

hdr(<name>):根據請求報文中指定的header(如use_agent,referer,hostname)將該hesder作hash計算進行調度
動靜態取決於hash type

hash-type map-based consistent

hdr(Cookie)

rdp-cookie 遠程桌面相關

rdp-cookie(<name>)

default_backend <backend>

無use_backend 匹配時,使用默認的backend,用於 frontend中

server

server <name> <address>[:[port]] [param*]
定義後端主機的各服務器及其選項 server <name> <address>[:port] [settings ...] default-server [settings ...]

<name>:服務器在haproxy上的內部名稱;出如今日誌及警告信息

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

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

[param*]:參數
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
weight <weight>:權重,默認爲1
maxconn <maxconn>:當前server的最大併發鏈接數
backlog <backlog>:當server的鏈接數達到上限後的後援隊列長度
backup:設定當前server爲備用服務器

default-server [param*] 爲backend中的各server設定默認選項

bind配置

bind:指定一個或多個前端偵聽地址和端口
只用於frountend配置段和listen配置段
bind [<address>]:<port_range> [, ...] [param*]
示例:

listen http_proxy bind :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

maxconn

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

mode { tcp|http|health }

定義haproxy的工做模式
tcp:基於layer4實現代理;可代理mysql, pgsql, ssh, ssl等協議,https時使用此模式,默認模式
http:僅當代理協議爲http時使用,centos實際默認模式
health:工做爲健康狀態檢查的響應模式,當鏈接請求到達時迴應「OK」後即斷開鏈接,較少使用

基於cookie的會話綁定

cookie <name> [ rewrite | insert | prefix ] [ indirect ] [ nocache ] [ postonly ] [ preserve ] [ httponly ] [ secure ] [ domain <domain> ]* [ maxidle <idle> ] [ maxlife <life> ]
<name>:cookie名稱,用於實現持久鏈接
rewrite:重寫
insert:插入
prefix:前綴
配置示例:

backend websrvs balance roundrobin cookie WEBSRV insert nocache indirect server web1 192.168.45.11:80 check cookie srv1 server web2 192.168.45.12:80 check cookie srv2 #每一個server有本身的惟一的cookie標識 #在backend中爲用戶請求調度完成後操縱其cookie

統計接口啓用相關的參數

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 用戶名:密碼 stats admin if TRUE #在frountend中單獨定義一個stats服務,監聽9099端口 #若是認證成功就開啓管理功能

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 <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>:錯誤頁文件路徑

示例:
使用haproxy主機本地的文件進行響應

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 

使用url進行響應,響應狀態碼爲302,不適用於GET之外的其餘請求方法:
errorloc <code> <url> 至關於errorloc302 <code> <url>,利用302重定向至指URL

errorloc 503 http://www.a.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> 後端服務器半鏈接的空閒時長

ACL

acl:haproxy的ACL用於實現基於請求報文的首部、響應報文的內容或其餘的環境狀態信息來作出轉發決策,這大大增長了其配置彈性。其配置法則通常分爲兩部,首先定義ACL,既定義一個測試條件,然後在條件獲得知足時執行某特定動做,如阻止訪問或者轉發至某特定的後端,
定義ACL的語法格式以下:
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

<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 非 

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 : 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
path_sub : substring match

url : string

提取請求中的URL。一個典型的應用是具備預取能力的緩存, 以及須要從數據庫聚合多個信息並將它們保存在緩存中的網頁門戶入口
url : exact string match
url_beg : prefix match URL開頭,匹配協議
url_dir : subdir match
url_dom : domain match
url_end : suffix match URL結尾
url_len : length match
url_reg : regex match 正則表達式匹配一類url
url_sub : substring match

req.hdr([

提取在一個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_SLASHurl_beg / 匹配URL相對路徑
HTTP_URL_STAR url * 匹配 URL 等於 "*"
LOCALHOST src 127.0.0.1/8 匹配從localhost來的鏈接
METH_CONNECT method CONNECT 匹配HTTP CONNECT方法
METH_GETmethod 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

acl配置

基於IP的訪問控制

use_backend <backend> [{if | unless} <condition>]
當if/unless一個基於ACL的條件匹配時切換指定backend

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

四層請求訪問控制

tcp-request connection {accept|reject} [{if | unless} <condition>]
示例:

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 #一個ACL定義了兩個條件,若是用戶的請求知足PATH中帶有/static /images /javascript /stylesheets 這些字符的,或者path是以.jpg .gif .png .css .js .html .txt .htm 這些字符結尾的就匹配ACL定義 #知足ACL定義的請求爲靜態請求,被調度到後端的staticsrvs機組上 #不滿組以上兩個條件的請求默認調度都後端包含兩臺服務器輪詢的appsrvs機組上

支持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 }

相關文章
相關標籤/搜索