HAProxy系列文章:http://www.cnblogs.com/f-ck-need-u/p/7576137.html
haproxy幾乎每個大版本都提供了官方手冊(內容幾乎都相同),手冊非常詳細。例如haproxy 1.7版本關於配置文件的官方手冊:http://cbonte.github.io/haproxy-dconv/1.7/configuration.html。
haproxy的靈魂在於配置文件,眾多功能都通過配置文件來實現,配置文件中的關鍵詞非常多,各自的概念也較復雜。但實際上真正要配置它時是相當簡單的,因為除了自己的需求,很多功能官方都建議采用默認值。
配置文件的重點在於前端(frontend)和后端(backend)的定制。全局選項(global)的配置將默認提供的稍微修改下即可。
可以使用haproxy命令行檢查配置文件語法是否正確。
haproxy -f /etc/haproxy/phaproxy.cfg -c
或者使用sysv腳本的check參數。
service haproxy check
1.1 配置文件說明
HAProxy在啟動之前會解析配置文件,有3處配置信息來源:
- 最優先處理來自haproxy命令行給出的參數。
- "global"配置段的參數,設定為全局參數。
- 代理配置段。包括
defaults
,listen
,frontend
和backend
段。
另外haproxy配置文件引入了引號和轉義符:反斜線表示轉義符;單引號表示強引用;雙引號表示弱引用。如果字符串內需要輸入空格,則空格需要進行轉義或者通過引號包圍,不轉義時在配置文件中表示分隔符。
如:
\ 標記一個空白字符以區分它的本義和用作分隔符時的空白符
\# to mark a hash and differentiate it from a comment
\\ to use a backslash
\' to use a single quote and differentiate it from strong quoting \" to use a double quote and differentiate it from weak quoting
下面幾種情況是等價的:
log-format %{+Q}o\ %t\ %s\ %{-Q}r
log-format "%{+Q}o %t %s %{-Q}r"
log-format '%{+Q}o %t %s %{-Q}r'
log-format "%{+Q}o %t"' %s %{-Q}r'
log-format "%{+Q}o %t"' %s'\ %{-Q}r
在配置文件中,一些包含了數值的參數表示時間,如timeout。這些值默認以毫秒為單位,但也可以使用其它的時間單位后綴。
- us: 微秒(microseconds),即1/1000000秒;
- ms: 毫秒(milliseconds),即1/1000秒;
- s: 秒(seconds);
- m: 分鍾(minutes);
- h:小時(hours);
- d: 天(days);
1.2 簡單配置示例
以下是一個簡單的配置文件,該配置文件代理模式為http,frontend定義的是監聽在前端所有網卡的80端口上,此文件中只定義了一個后端服務器組backend,該backend只包含一台監聽在127.0.0.1:8000的服務器。在haproxy的術語中,frontend表示的是監聽套接字,用於等待客戶端的連接。
global
daemon
maxconn 256
defaults
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
frontend http-in
bind *:80
default_backend web_servers
backend web_servers
server server1 127.0.0.1:8000 maxconn 32
如果使用listen配置方式替換backend和frontend,則更簡單,以下是等價配置:
global
daemon
maxconn 256
defaults
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
listen http-in
bind *:80
server server1 127.0.0.1:8000 maxconn 32
1.3 全局配置參數
全局配置參數設定haproxy進程運行環境,一般和操作系統指定的值有關,配置正確后一般都不會去修改。全局配置參數一般都有對應的命令行選項。
1.進程管理及安全相關的參數。
haproxy是單進程、事件驅動、非阻塞模型的調度器。雖然是單進程,但官方強烈建議不要設置為多進程,因為單進程可以處理很多個代理連接請求且性能極好(官方手冊說30W個代理實例都能良好運行),設置為多進程反而有一些限制。
- chroot :修改haproxy工作目錄至指定目錄,可提升haproxy安全級別,但要確保必須為空且任何用戶均不能有寫權限;
- daemon:讓haproxy以守護進程的方式工作於后台,等同於命令行的"-D"選項,當然,也可以在命令行中以"-db"選項將其禁用;(建議設置項)
- uid/user:以指定的UID或用戶名身份運行haproxy進程;
- gid/group:以指定的GID或組名運行haproxy,建議使用專用於運行haproxy的GID,以免因權限問題帶來風險;
- log:定義全局的syslog服務器,接收haproxy啟動和停止的日志。最多可以定義兩個;
log <address> <facility> [max level [min level]]
- log-send-hostname [string]:在日志的最前面記錄本機主機名或string。遠程發送到日志服務器時可由此知道是haproxy主機發送的。
- pidfile:等同於命令行的"-p"選項。使用服務啟動腳本啟動haproxy時建議不要設置該項,以保證腳本能正確獲取pid文件。
- nbproc :指定啟動的haproxy進程個數,只能用於守護進程模式的haproxy;默認只啟動一個進程,一般只在單進程僅能打開少數文件描述符的場景中才使用多進程模式;(官方強烈建議不要設置該選項)
- ulimit-n:設定每進程能夠打開的最大文件描述符數量,默認haproxy會自動進行計算,因此不推薦修改此選項;(不建議設置項)
- stats:和多進程haproxy有關,由於不建議使用多進程,所以也不建議設置此項。但建議設置為"stats socket"將套接字和本地文件進行綁定,如"stats socket /var/lib/haproxy/stats"。
- node:定義當前節點的名稱,用於HA場景中多haproxy進程使用相同IP地址時分辨哪個node正處於使用狀態;
2.性能調整相關的參數。
- maxconn :設定每haproxy進程所接受的最大並發連接數,當達到此限定連接數后將不再接受新的連接。該參數特指和客戶端的連接數,不包括和服務端的連接。等同於命令行選項"-n";"ulimit -n"就是根據此值進行自動調整的;
- maxpipes :haproxy在使用splice()在內核中零復制時,是使用pipe傳遞進行報文粘接重組的,此選項用於設定每進程所允許使用的最大pipe個數;每個pipe會打開兩個文件描述符,因此"ulimit -n"自動計算時會按需調大此值;默認值為maxconn/4。調小時會影響一定的性能;
- noepoll:在Linux系統上禁用epoll機制;(不建議設置此項)
- nokqueue:在BSD系統上禁用kqueue機制;
- nopoll:禁用poll機制;
- nosplice:禁止在Linux套接字上使用內核tcp重組,這會導致更多的recv/send系統調用;(在內核版本2.6.28之后極度不建議設置此項)
- spread-checks <0..50, in percent>:在haproxy后端有着眾多服務器的場景中,在精確的時間間隔后統一對眾服務器進行健康狀況檢查可能會帶來意外問題;此選項用於將其檢查的時間間隔長度上增加或減小一定的隨機時長;默認為0,官方建議設置為2到5之間。(建議設置項)
- tune.bufsize :設定buffer的大小,同樣的內存條件下,較小的值可以讓haproxy有能力接受更多的並發連接,較大的值可以讓某些應用程序使用較大的cookie信息;默認為16384,可在編譯時修改,不過強烈建議使用默認值;(不建議設置項)
- tune.chksize :設定檢查緩沖區的大小,單位為字節;更大的值有助於在較大的頁面中完成基於字符串或正則pattern的文本查找,但也會占用更多的系統資源;(不建議設置項)
- tune.maxaccept :設定haproxy進程內核調度運行時一次性可以接受的連接的個數,較大的值可以帶來較大的吞吐率,默認在單進程模式下為100,多進程模式下為8,設定為-1可以禁止此限制;(不建議設置項)
- tune.maxpollevents :設定一次io復用時系統調用可以處理的事件最大數,默認值取決於OS;其值小於200時可節約帶寬,但會略微增大網絡延遲,而大於200時會降低延遲,但會稍稍增加網絡帶寬的占用量;(不建議設置項)
- tune.maxrewrite :設定為首部重寫或追加而預留的緩沖空間,建議使用1024左右的大小;在需要使用更大的空間時,haproxy會自動增加其值;(不建議設置項)
- tune.rcvbuf.client :設定兩端的recv_buff大小(haproxy和客戶端建立tcp,和后端服務器建立tcp,共兩端,因此有兩個recv_buff和兩個send_buff)。單位為字節;(強烈推薦使用默認值)
- tune.rcvbuf.server :(強烈推薦使用默認值)
- tune.sndbuf.client:設定兩端的send_buff大小(強烈推薦使用默認值)
- tune.sndbuf.server:(強烈推薦使用默認值)
因此,拋去不建議設置的項后,global段的設置大致如下:這也是yum安裝haproxy時默認提供的配置
global
daemon
log 127.0.0.1 local2
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
user haproxy
group haproxy
stats socket /var/lib/haproxy/stats
注意上面配置了使用local2記錄log,因此還需去rsyslogd的配置文件中添加該設備以及記錄的日志位置。如下:
cat <<eof>>/etc/rsyslog.conf
local2.* /var/log/haproxy.log
eof
1.4 proxy配置段和常用配置選項
proxy配置部分是haproxy最重要的配置部分,包含下面四種配置段:
- defaults []:設置frontend/backend/listen配置段的默認值。
- frontend :配置監聽客戶端連接的套接字。
- backend :配置haproxy所代理的后端服務器組。
- listen :定義一個完整的前端和后端代理,但后端可以不定義。所以有時候等價於frontend+backend。它常用於綁定前后端1對1的情況。
所有代理的名稱只能使用大寫字母、小寫字母、數字、-(中線)、_(下划線)、.(點號)和:(冒號)。此外,ACL名稱會區分字母大小寫。
目前,有兩種主流的代理模式:tcp代理(即所謂的4層代理)和http代理(即所謂的7層代理)。在4層代理模式下,haproxy簡單的在兩端進行雙向轉發。在7層代理模式下,haproxy會對協議進行分析,可以根據協議來允許、阻塞、切換、增加、修改和移除request或response中的屬性內容。
1.4.1 http事務模型相關設置
- (no) option http-keep-alive
啟用或禁用客戶端和服務端到haproxy之間的長連接。haproxy將處理所有請求和響應報文,請求完后haproxy兩端的連接都處於空閑狀態。由於和后端保持了連接,可以以最快的方式重用會話。 - (no) option http-server-close
啟用或禁用在haproxy處理完第一次響應之后關閉haproxy到服務端之間長連接的功能,但客戶端的長連接還保持,后續的每次請求都重新建立和后端的連接,每次響應后都關閉和后端的連接。啟用該選項時,haproxy將會在轉發給后端server的request數據包中添加一個"Connection:Close"標記,后端Server看到此標記就會在響應后關閉tcp連接。 - (no) option http-tunnel
啟用或禁用在haproxy處理完第一次請求和響應后關閉haproxy兩端長連接的功能。在1.0-1.5.21版本該項是默認項,但現在不建議使用,因為會產生一些問題。 - (no) option forceclose
啟用或禁用傳輸完響應報文后關閉兩端的連接。 - (no) option htthttpcloseose(廢棄選項)
- (no) option http-pretend-keepalive
有些服務器會無視帶有"Connection:Close"標記的請求,從而http-server-close的后端發送響應后不會關閉tcp連接。設置該選項時,haproxy在收到響應后會主動關閉和后端的連接。不建議設置該選項,因為絕大多數服務器都能正常工作並且有很好的調整能力。
一般來說,對於高速局域網絡來說,如果后端響應的速度非常快(比如后端是靜態服務器響應小文件、后端是靜態緩存服務器),這時建立tcp連接的代價就比較大,維持空閑連接的優勢會非常明顯。如果后端是動態應用程序,響應給haproxy的速度相對較慢,維持空閑連接的代價非常大,完全可以先釋放長連接以騰出資源,在需要連接的時候再建立新tcp連接。因此:
(1).后端是靜態內容緩存服務器時,或者就是靜態服務器時,首選使用http-keep-alive模式;
(2).后端是動態應用程序服務器時,首選使用http-server-close模式。
默認情況下,如果客戶端請求根據調度算法被調度到另一台后端服務器時,http-keep-alive模式下和后端服務器的空閑連接會立即斷開,並重新和被調度選中的后端服務器建立連接。可以使用"prefer-last-server"選項,使得haproxy先查看當前保持的空閑連接是否可用,如果可用,則繼續使用該空閑連接,但是這樣會影響調度性能。
frontend和backend都可以設置這些模式選項,如果它們交叉設置了,最終何種模式會生效?例如,frontend設置了http-keep-alive,而bakcend設置了http-server-close時,取何種模式?計算方式采用如下矩陣:keepalive優先級是最弱的,forceclose是優先級是最高的。
1.4.2 balance
balance <algorithm>
可用於default、listen、backend配置段。
指定代理時負載均衡算法,支持的算法有:
- roundrobin(默認):根據權重進行輪詢,在服務器的處理時間保持均勻分布時,這是最平衡、最公平的算法。此算法是動態的,表示權重可以在haproxy運行時調整后端服務器的權重並生效;
- static-rr:基於權重進行輪詢,與roundrobin類似,但是為靜態方法,在haproxy運行時調整其服務器權重不會生效;
- leastconn:新的連接請求被派發至具有最少連接數目的后端服務器;在有着較長時間會話的場景中推薦使用此算法,如LDAP、SQL等,其並不太適用於較短會話的應用層協議,如HTTP;此算法是動態的,可以在運行時調整其權重;
- source:將請求的源地址進行hash運算,使得同一個客戶端IP的請求始終被派發至某特定的服務器;但當服務器權重總數發生變化時,如某服務器宕機或添加了新的服務器,許多客戶端的請求可能會被派發至與此前請求不同的服務器;類似於nginx的ip_hash,可用於負載均衡無cookie功能的基於TCP的協議。默認為靜態;
- uri:對URI的左半部分("?"標記之前的部分)進行hash運算,並除以服務器的總權重來計算派發至某匹配服務器;這可以使得對同一個URI的請求總是被派發至某特定的服務器,除非服務器的權重總數發生了變化;此算法常用於代理緩存以提高緩存的命中率;但此算法僅應用於提供http服務的后端服務器;默認為靜態算法;缺點是后端server宕機會造成嚴重抖動,可以通過hash-type設置hash算法為一致性哈希解決。
- url_param:一般用於將同一用戶ID轉發至同一服務器的情況。在使用了basic認證時,url中的param一般都會使用user=XXX。使用該算法會對該參數進行hash運算,然后除以總權重以決定分配到哪台后端server。
- hdr(name):基於指定的請求首部名稱進行調度。首部中指定名稱相同的調度至同一服務器。一般使用"hdr(host)"根據請求首部中的host即目標主機來進行hash運算。使用use_domain_only選項可以基於域名來哈希,使得訪問www.longshuai.com和web.longshuai.com的請求都調度至同一服務器。
- rdp-cookie
- rdp-cookie(name)
roundrobin和static-rr是有區別的,roundrobin是動態慢輪詢,不用重啟服務即可調整其權重,而static-rr必須重啟服務修改的權重才生效。例如原有2台后端server,新添加一台后,roundrobin會從此時開始慢慢的將請求輪詢至此新服務器,而static-rr由於需要重啟,所以重啟前新server不會被調度到,重啟后新server和舊server平均調度。一般來說,考慮加權輪詢的時候,roundrobin要比static-rr好。
一般可納入考慮的算法有roundrobin/static-rr/leastconn/uri,其中leastconn算法用於代理ldap、mysql等長時間會話連接的情況,uri算法用於代理后端為緩存服務器的情況。
(1). 用於調度MySQL服務器,使用何種算法?答:leastconn
(2). 用於調度靜態服務器組,使用何種算法?答:roundrobin
(3). 調度動態應用程序服務器組,使用何種算法?答:通常客戶端需要和后端應用程序服務器保持聯系,一般會使用cookie或者session來實現,但如果特殊情況下無法通過它們實現,則可以使用source作為最后"親和性"手段。注意,使用source算法時,后端服務器數量一改變,就會導致大量的會話斷開。
(4). 調度緩存服務器,使用何種算法?答:uri,且設置hash-type為一致性哈希算法。
1.4.3 hash-type
hash-type <method>
不能用於frontend區段
定義用於將hash碼映射至后端服務器的方法;可用方法有map-based和consistent,一般情況推薦使用默認的map-based方法。
- map-based:hash表是一個包含了所有在線服務器的靜態數組。其hash值將會非常平滑,會將權重考慮在列,但其為靜態方法,對在線服務器的權重進行調整將不會生效,這意味着其不支持慢速啟動。此外,挑選服務器是根據其在數組中的位置進行的,因此,當一台服務器宕機或添加了一台新的服務器時,大多數連接將會被重新派發至一個與此前不同的服務器上。對於緩存服務器的工作場景來說,此方法不適用。
- consistent:(一致性哈希算法)hash表是一個由各服務器填充而成的樹狀結構;基於hash鍵在hash樹中查找相應的服務器時,最近的服務器將被選中。此方法是動態的,支持在運行時修改服務器權重,因此兼容慢速啟動的特性。添加一個新的服務器時,僅會對一小部分請求產生影響,因此,適用於后端服務器為cache的場景。不過,此算法不甚平滑,派發至各服務器的請求未必能達到理想的均衡效果,因此,可能需要不時的調整服務器的權重以獲得更好的均衡性。
1.4.4 bind
bind [<address>]:<port_range> [, ...]
bind [<address>]:<port_range> [, ...] interface <interface>
能用於frontend和listen段
用於定義一個或幾個監聽的套接字。
<address>
:可選項,可以為主機名、IPv4地址、IPv6地址或*;省略此選項、將其指定為*或0.0.0.0時,將監聽當前系統的所有IPv4地址;<port_range>
:可以是一個特定的TCP端口,也可是一個端口范圍(如5005-5010),代理服務器將通過指定的端口來接收客戶端請求;注意,小於1024的端口需要有特定權限的用戶才能使用;<interface>
:指定物理接口的名稱;
例如:
bind :80,:443
bind 10.0.0.1:10080,10.0.0.1:10443
1.4.5 mode
指定haproxy實例運行模式。可為tcp、http。tcp為4層代理模式,不會對協議進行任何分析,只是單純地轉發數據包,如HTTPS/MYSQL等,http為7層代理模式。如果所有配置區段都沒有設置mode,則默認為tcp模式。
1.4.6 log
log global
log <address> <facility> [<level> [<minlevel>]]
為每個實例啟用事件和流量日志,因此可用於所有區段。每個實例最多可以指定兩個log參數。配置方法和意義同前文全局配置參數的log。
如果使用log global,則表示從全局繼承日志設置。另外,如果全局已經定義過兩個log了,此處除引用global外還自定義了一個log,則此自定義的log失效,因為只支持兩個日志設置。
1.4.7 capture request header和capture response header
capture request header <name> len <length>
capture response header <name> len <length>
僅能用於"frontend"和"listen"區段
捕獲並記錄最近一次出現的指定請求首部或響應首部。請求首部是從客戶端發起的請求首部,響應首部是從后端server響應並在haproxy准備發送給客戶端前捕獲的。捕獲的首部值使用大括號{}
括起來后會添加進日志中。如果需要捕獲多個首部值,它們將以指定的秩序出現在日志文件中,並以豎線"|"作為分隔符。不存在的首部記錄為空字符串。
最常需要捕獲的請求首部包括:在虛擬主機環境中使用的"Host"、上傳請求首部中的"Content-length"、快速區別真實用戶和網絡機器人的"User-agent",以及代理環境中記錄請求真實來源的"X-Forward-For"。
一般需要捕獲的響應首部為:記錄還有多少內容需要接收的"Content-length"、跟蹤重定向路徑的"Location"。
<name>
:要捕獲的首部的名稱,此名稱不區分字符大小寫,但建議與它們出現在首部中的格式相同,比如大寫首字母。需要注意的是,記錄在日志中的是首部對應的值,而非首部名稱。<length>
:指定記錄首部值時所記錄的精確長度,超出的部分將會被忽略。
可以捕獲的請求首部的個數沒有限制,但每個捕獲最多只能記錄64個字符。為了保證同一個frontend中日志格式的統一性,首部捕獲僅能在frontend中定義。
例如:
capture request header Host len 15
capture request header X-Forwarded-For len 15
capture request header Referer len 15
capture response header Content-length len 9
capture response header Location len 15
1.4.8 maxconn
maxconn <conns>
不能用於backend區段
設定一個前端的最大並發連接數。對於大型站點來說,可以盡可能提高此值以便讓haproxy管理連接隊列,從而避免無法應答用戶請求。當然,此最大值不能超出"global"段中的定義。此外,haproxy會為每個連接維持兩個緩沖,每個緩沖的大小為16KB,再加上其它的數據,每個連接將大約占用33KB的RAM空間。這意味着經過適當優化后,有着1GB的可用RAM空間時將能維護20000-25000並發連接。
如果為指定了一個過大值,極端場景下,其最終占據的空間可能會超出當前主機的可用內存,這可能會帶來意想不到的結果;因此,將其設定了一個可接受值方為明智決定。默認為2000。
1.4.9 use_backend
use_backend <backend> [{if | unless} <condition>]
定義當滿足或不滿足什么條件時使用哪個backend。條件判斷是可選的,並且condition是基於acl的條件。
1.4.10 default_backend
default_backend <backend>
不可應用於backend區段。
在沒有匹配的"use_backend"規則時為實例指定默認后端。在"frontend"和"backend"之間進行內容交換時,通常使用"use-backend"定義匹配規則;而沒有被規則匹配到的請求將由此參數指定的后端接收。
例如,已有兩組backend,名稱分別為dynamic和static,當不匹配use_backend時將默認使用dynamic作為轉發后端。
use_backend dynamic if url_dyn
use_backend static if url_css url_img extension_img
default_backend dynamic
1.4.11 server和default-server
server <name> <address>[:port] [param*]
聲明后端server,因此不能用於defaults和frontend區段。
default-server [param*]
指定server的默認參數值,不能用於frontend區段
-<name>
:為此服務器指定的內部名稱,將出現在日志及警告信息中;
<address>
:此服務器的IPv4地址,也支持使用可解析的主機名;[:port]
:haproxy將請求轉發至后端服務器的哪個端口,為可選項;未設定時,將使用客戶端請求時的同一端口;[param*]
:為此服務器設定的一系列參數;可用的參數非常多,下面是幾個常用的參數;
服務器或默認服務器參數:
backup
:設定為備用服務器,當其它所有后端server均不可用時將啟用此server;disabled
:禁用此后端服務器。check
:啟動對此server執行健康狀態檢查,但需要配合定義在backend的具體檢查方法(如httpcheck,mysql-check)才會進行指定的檢查方式,不指定檢查方法時將默認以tcp方式檢查。check可以借助於額外的參數完成更精細的設定,如:inter <delay>
:設定健康狀態檢查的時間間隔,單位為毫秒,默認為2000;rise <count>
:設定server從離線狀態重新上線需要成功檢查的次數;不指定默認為2,一般可設置為1。fall <count>
:確認server從正常狀態轉換為不可用狀態需要檢查的次數;默認為3。
cookie <value>
:為指定server設定cookie值,指定的值將在請求入站時被檢查,第一次為此值挑選的server將在后續的請求中被選中,其目的在於實現基於客戶端cookie的持久連接;maxconn <maxconn>
:指定此后端服務器接受的最大並發連接數(不同於全局設置的maxconn,全局的maxconn是面向客戶端的);如果發往此服務器的連接數高於指定的值,將被放於請求隊列以等待其它連接釋放;maxqueue <maxqueue>
:設定請求隊列的最大長度;observe <mode>
:通過觀察服務器的通信狀況來判定其健康狀態,默認禁用,支持的類型有"layer4"和"layer7",layer4表示檢查tcp連接是否正常,layer7僅用於http代理場景,通過后端server發送的response來判斷,例如可以判斷狀態碼,響應報文頭部是否無法解析等;redir <prefix>
:啟用重定向功能,將發往此服務器的GET和HEAD請求均以302狀態碼響應,意味着不會將請求轉發至后端服務器;在prefix后面不能使用/,且不能使用相對地址;例如:server srv1 192.168.1.1:80 redir http://image1.mydomain.com check
weight <weight>
:權重,默認為1,最大值為256,0表示不參與負載均衡,即認為下線了不進行調度;
關於maxconn和maxqueue,這兩個值都是此后端服務器的值。它們的大小和全局定義的maxconn是有一定大小比較關系的。如果沒有定義maxqueue,則全局maxconn應該小於或等於后端所有服務器的maxconn之和,如果定義了maxqueue,則需要小於或等於后端所有服務器的maxconn和maxqueue之和。否則haproxy接收進來的請求超過后端服務器的壓力極限,可能壓垮后端。
例如:
server first 10.1.1.1:1080 cookie first check inter 1000 server second 10.1.1.2:1080 cookie second check inter 1000 server backup "${SRV_BACKUP}:1080" backup server www1_dc1 "${LAN_DC1}.101:80" server www1_dc2 "${LAN_DC2}.101:80" default-server inter 1000 weight 13
1.4.12 option httpchk
option httpchk
option httpchk <uri>
option httpchk <method> <uri>
option httpchk <method> <uri> <version>
不能用於frontend段。
此指令表示基於http協議來做健康狀況檢查,只有返回狀態碼為2xx或3xx的才認為是健康的,其余所有狀態碼都認為不健康。不設置該選項時,默認采用tcp做健康檢查,只要能建立tcp就表示健康。
uri
:檢查的uri路徑,默認為"/"。接受帶有查詢參數的urimethod
:http檢查時使用的METHOD。不指定時默認為"OPTIONS"方法,也建議采用此方法,因為該請求方法對服務器造成的資源損耗最小。version
:檢查的http協議版本,默認為http/1.0,但現在很多都采用HTTP/1.1,因此此處檢查版本需要修改為HTTP/1.1,但對於該版本的HTTP協議來說,還強制要求指定Host,中間使用\r\n
隔離。
例如下面的配置,會將健康檢查時的頁面請求發送至后端192.168.1.1的80端口來確定該后端是正常的,但客戶端的請求將轉發至該后端的443端口。
backend https_relay
mode tcp
option httpchk
option httpchk OPTIONS * HTTP/1.1\r\nHost:\ www
server apache1 192.168.1.1:443 check port 80
1.4.13 stats相關
stats enable
:啟用基於程序編譯時默認設置的統計報告,不能用於"frontend"區段。
只要沒有另外的其它設定,默認就會使用如下的配置:
- stats uri : /haproxy?stats
- stats realm : "HAProxy Statistics"
- stats auth : no authentication
- stats scope : no restriction
盡管"stats enable"一條就能夠啟用統計報告,但還是建議設定其它所有的參數,以免依賴於默認設定而帶來非預期后果。
例如:
backend public_www
server websrv1 172.16.100.11:80
stats enable
stats hide-version
stats scope .
stats uri /haproxyadmin?stats
stats realm Haproxy\ Statistics
stats auth statsadmin:password
stats auth statsmaster:password
stats hide-version
:啟用統計報告並隱藏HAProxy版本報告,不能用於"frontend"區段。stats realm
:stats auth身份認證時的提示信息。設置的提示信息中,如果有空白字符,則需要轉義。僅在與"stats auth"配合使用時有意義。stats auth
:啟用帶認證的統計報告功能並授權一個用戶帳號和對應的密碼(明文)。也就是說,想要查看統計報告需要提供身份和密碼。不能用於"frontend"區段。stats admin
:滿足指定條件時啟用統計報告頁面的管理功能,它允許通過web接口啟用或禁用后端服務器。stats admin { if | unless } <cond>
下面是兩個案例,第一個限制了僅能在本機打開報告頁面時啟用管理功能,第二個定義了僅允許通過認證的用戶使用管理功能。
backend stats_localhost
stats enable
stats admin if LOCALHOST
backend stats_auth
stats enable
stats auth haproxyadmin:password
stats admin if TRUE
1.4.14 option forwardfor
option forwardfor [ except <network> ] [ header <name> ] [ if-none ]
允許在發往服務器的請求首部中插入"X-Forwarded-For"首部。
except <network>
:可選參數,當指定時表示請求中的源地址能匹配此網絡時禁用此功能。header <name>
:可選參數,自定義首部名,如"X-Client"來替代"X-Forwarded-For"。有些獨特的web服務器的確需要一個獨特的首部。if-none
:僅在此首部不存在時才將其添加至請求報文問道中。
HAProxy工作於反向代理模式,其發往服務器的請求中的客戶端IP均為HAProxy主機的地址而非真正客戶端的地址,這會使得服務器端的日志信息記錄不了真正的請求來源,"X-Forwarded-For"首部則可用於解決此問題。HAProxy可以向每個發往服務器的請求上添加此首部,並以客戶端IP為其value。
下面是一個例子。
frontend www
mode http
option forwardfor except 127.0.0.1
1.4.15 錯誤頁面相關
- errorfile
在用戶請求不存在的頁面時,返回一個頁面文件給客戶端而非由haproxy生成的錯誤代碼;可用於所有段中。errorfile <code> <file>
<code>
:指定對HTTP的哪些狀態碼返回指定的頁面;這里可用的狀態碼有200、400、403、408、500、502、503和504;<file>
:指定用於響應的頁面文件;
例如:errorfile 400 /etc/haproxy/errorpages/400badreq.http errorfile 403 /etc/haproxy/errorpages/403forbid.http errorfile 503 /etc/haproxy/errorpages/503sorry.http
- errorloc和errorloc302
請求錯誤時,返回一個HTTP重定向至某URL的信息;可用於所有配置段中。errorloc <code> <url> errorloc302 <code> <url>
<code>
:指定對HTTP的哪些狀態碼返回指定的頁面;這里可用的狀態碼有200、400、403、408、500、502、503和504;<url>
:Location首部中指定的頁面位置的具體路徑,可以是在當前服務器上的頁面的相對路徑,也可以使用絕對路徑;需另外,這兩個關鍵字都會返回302狀態嗎,這將使得客戶端使用同樣的HTTP方法獲取指定的URL,對於非GET方法的場景(如POST)來說會產生問題,因為返回客戶端的URL是不允許使用GET以外的其它方法的。如果的確有這種問題,可以使用errorloc303來返回303狀態碼給客戶端。
- errorloc303
請求錯誤時,返回一個HTTP重定向至某URL的信息給客戶端;可用於所有配置段中。errorloc303 <code> <url>
<code>
:指定對HTTP的哪些狀態碼返回指定的頁面;這里可用的狀態碼有400、403、408、500、502、503和504;<url>
:Location首部中指定的頁面位置的具體路徑,可以是在當前服務器上的頁面的相對路徑,也可以使用絕對路徑;需要注意的是,如果URI自身錯誤時產生某特定狀態碼信息的話,有可能會導致循環定向;
例如:
backend webserver
server 172.16.100.6 172.16.100.6:80 check maxconn 3000 cookie srv01
server 172.16.100.7 172.16.100.7:80 check maxconn 3000 cookie srv02
errorloc 403 /etc/haproxy/errorpages/sorry.htm
errorloc 503 /etc/haproxy/errorpages/sorry.htm
1.4.16 cookie和option redispatch
在backend服務器組啟用cookie功能,以便實現cookie綁定。需要同時設置server指令中的cookie選項。
后端為靜態服務器設置:
cookie NAME insert nocache PHP做后端時設置: cookie SESSION_COOKIE insert indirect nocache
當客戶端綁定cookie對應的后端服務器宕機后,應該為此客戶端重新調度一個后端server,否則將打不開頁面。這時需要使用option redispatch,表示當找不到cookie對應的服務器時分配新的服務器給客戶端。
1.4.17 reqadd和rspadd
reqadd <string> [{if | unless} <cond>]
rspadd <string> [{if | unless} <cond>]
滿足條件時向請求首部或響應首部的尾端添加自定義的字段。條件可選,當不給定條件時表示所有的請求首部或響應首部尾端都添加字段。
其中string包含了字段名和字段值,當然,既然是自定義,值肯定是可以省略的。注意,空白字符需要轉義。
例如:
acl is-ssl dst_port 443
reqadd X-Proto:\ SSL if is-ssl
1.4.18 超時時間相關
時間單位默認都是毫秒。
- timeout http-request
haproxy等待客戶端請求發送完整的超時時長。如果一開始發送了一部分,后續沒有再發送,或者后續發送的一直是請求的某一部分,等達到超時時間將斷開此連接。這可以防止DoS攻擊。 - timeout queue
當調度的后端服務器已經滿負載了,即達到了該backend的最大並發連接數時,后續要調度到此backend的請求將進入隊列等待后端服務器釋放可用。該超時時間設置的就是某一請求在隊列中的最大等待時長,當達到此時長后將被認為該請求永遠無法到達服務端,haproxy會丟棄該請求並向客戶端返回503狀態碼。 - timeout connect 和retries
haproxy要和后端服務器建立連接時等待超時時間。一般如果haproxy和后端服務器處於局域網中,建立連接是瞬間的,所以該值可以設置的小一些。
retries表示和服務端建立連接失敗時重試連接的次數。
注意:在健康檢查時,將取timeout connect和inter的較小者作為檢查時建立tcp連接的超時時間。 - timeout client
客戶端和haproxy之間非活動連接保持的最大時長,達到此時長haproxy將斷開和此客戶端的連接。非活動表示客戶端沒有請求報文發送給haproxy。 - timeout server
服務端和haproxy之間非活動連接保持的最大時長,達到此時長haproxy將斷開和此服務器的連接。非活動表示服務端沒有響應報文發送給haproxy。 - timeout http-keep-alive
等待出現http請求報文出現的最大時長,即和客戶端保持長連接的時長。建議設置小一些,以盡快釋放連接,例如設置為2-3秒鍾。
如果此項未設置,則使用timeout http-request值,如果timeout http-request也沒設置,則使用timeout client的值。 - timeout check
在和服務端建立連接后,健康狀況檢查判斷的超時時長(意思是,在建立TCP連接后,后端節點需要響應消息給haproxy,響應的消息可能是(1)httpcheck方式時,經過hash計算的http頁面(2)tcp檢查方式時的回復消息。如果haproxy隔了一段時間,都沒有接收完這些消息,就認為這次檢查不健康。因此timeout check是read回應消息的超時時長。而min("timeout connect","inter")則是建立tcp連接的超時時間,它們之和才是一次不健康檢查的總時間)。
1.4.19 http協議過濾:http-request
http-request {allow | auth [realm <realm>] | redirect <rule> | deny [deny_status <status>]} [{if | unless} <condition>]
做7層http協議過濾。當http協議相關項滿足條件時執行一個action,可以執行的action非常多,此處只列出了幾項。
allow
:表示接受該http請求。auth
:表示提示輸入用戶認證信息,指定realm時將給出提示信息。redirect
:重定向功能。deny
:表示拒絕該http請求。
acl nagios src 192.168.129.3
acl local_net src 192.168.0.0/16
acl auth_ok http_auth(L1)
http-request allow if nagios
http-request allow if local_net auth_ok
http-request auth realm Gimme if local_net auth_ok
http-request deny
1.4.20 tcp請求和響應過濾
tcp-request content <action> [{if | unless} <condition>]
tcp-response content <action> [{if | unless} <condition>]
做4層協議過濾。當滿足條件時,haproxy對tcp請求或響應報文執行某個action。
對於request而言,只能用於listen和frontend。常用的action是accept和reject,表示滿足條件時haproxy接受或拒絕該請求報文。
對於response而言,只能用於listen和backend。常用的action是accept、reject和close,前兩者表示滿足條件時接受或拒絕該響應報文,close表示滿足條件時立即關閉和服務端的連接。
1.5 ACL
1.5.1 ACL語法
acl <aclname> <criterion> [flags] [operator] [<value>] ...
aclname:指定acl的名稱,在引用時區分大小寫。可隨意指定,且多個acl指令可以指定同一個aclname,這表示"或"的邏輯關系。
flags:可選項,表示標識位。一般會用到的標識位只有"-i",表示不區分大小寫。
operator:可選項,某些操作符,有"eq"、"ge"、"gt"、"le"、"lt",表示數學上的等於、大於、小於。
<criterion>:指定檢查標准,即檢查方法。見下文給出的常用4層標准和7層標准
value:根據criterion的不同,值的類型不同。
(1).4層常用檢查標准,官方手冊:https://cbonte.github.io/haproxy-dconv/1.7/configuration.html#7.3.3
src <ip_addr>
src_port <PORT or PORT_ranges>
dst <ip_addr>
dst_port <PORT or PORT_ranges>
其中src、src_port、dst和dst_port就是檢查標准creiterion,其后的值就是value。
例如:
acl accept_clients src 192.168.100.0/24
acl reject_clients src 172.16.0.0/16
tcp-request content accept if accept_clients
tcp-request content reject if reject_clients
tcp-request content reject # 此項表明不匹配前兩項的默認都拒絕
(2).7層常用檢查標准,官方手冊:https://cbonte.github.io/haproxy-dconv/1.9/configuration.html#7.3.6
- hdr(HEADER):檢查首部字段的值是否為指定的值,如
hdr(Connection) -i close
表示首部字段Connection的值是否為不區分大小寫的close。hdr(Host) -i www.longshuai.com
表示首部字段Host的值是否為www.longshuai.com
,即請求的主機是否是指定的值。 - hdr_reg(HEADER):檢查首部字段是否匹配指定的模式。如
hdr_reg(Host) -i .*\.longshuai\.com
。 - http_first_req:當正處理的請求是第一個請求時返回true。
- method:請求的方法為指定的方法時返回方法對應的數值,也就表示true。例如"method GET"。
acl valid_method method GET http-request deny if ! valid_method
- path:匹配uri的path部分,一般用來匹配精確的文件資源。例如
path -i /a.png
。 - path_beg:匹配path的前綴部分。
- path_end:匹配path的后綴部分。
- path_reg:使用正則表達式來匹配path。
- url:對整個url進行匹配。
- url_beg:對url的前綴進行匹配。
還有很多很多檢查方法,更多的查詢官方手冊,太多了。一般4層的檢查標准和7層對路徑path和首部hdr的標准就夠了。
多個條件使用"AND"、"OR"、"!"操作符表示邏輯與、邏輯或和取反,不寫時默認的操作符是"AND"。
1.5.2 ACL實現動靜分離示例
acl url_static path_beg /static /images /img /css /viedo /download # 定義靜態檢查標准
acl url_static path_end .gif .png .jpg .css .js .bmp # 定義靜態檢查標准
acl host_www path /index.html # 為主頁專門定制acl
acl url_dynamic path_end .php .php5 # 定義動態檢查標准
acl host_www hdr_beg(Host) -i www.longshuai.com # 定位到主頁
use_backend static if url_static
use_backend dynamic if url_dynamic
use_backend www if host_www