一、HAProxy概述
1.haproxy簡介
HAProxy主要提供兩個功能:http協議反向代理(不提供緩存功能)、基於tcp層的負載均衡(如https、mysql協議)。適用於需要會話保持或七層處理的且負載特別大的站點。可支持數以萬計的併發連接。
代理作用:web緩存(加速)、反向代理、內容路由(根據流量及內容類型等將請求轉發至特定服務器)、轉碼器;
HAProxy基於一種事件驅動(event-driven)、單一進程模型和ebtree彈性二叉樹機制。
多進程或多線程模型受內存限制、系統調度器限制以及無處不在的鎖限制,很少能處理數千併發連接。事件驅動模型有更好的資源和時間管理的用戶端(User-Space) 實現所有這些任務,所以併發響應能特別大。但在多核系統上此模型通常擴展性較差
2.性能優勢
HAProxy藉助於OS上幾種常見的技術來實現性能的最大化。
單進程、事件驅動模型顯著降低了上下文切換的開銷及內存佔用。
O(1)事件檢查器(eventchecker)允許其在高併發連接中對任何連接的任何事件實現即時探測。
在任何可用的情況下,單緩衝(singlebuffering)機制能以不復制任何數據的方式完成讀寫操作,這會節約大量的CPU時鐘週期及內存帶寬;
藉助於Linux 2.6 (>=2.6.27.19)上的splice()系統調用,HAProxy可以實現零複製轉發(Zero-copy forwarding),在Linux3.5及以上的OS中還可以實現零複製啓動(zero-starting);
內存分配器在固定大小的內存池中可實現即時內存分配,這能夠顯著減少創建一個會話的時長;
樹型存儲:側重於使用作者多年前開發的彈性二叉樹,實現了以O(log(N))的低開銷來保持計時器命令、保持運行隊列命令及管理輪詢及最少連接隊列;
優化的HTTP首部分析:優化的首部分析功能避免了在HTTP首部分析過程中重讀任何內存區域;
精心地降低了昂貴的系統調用,大部分工作都在用戶空間完成,如時間讀取、緩衝聚合及文件描述符的啓用和禁用等;
3.HAProxy目前主要版本
1.4版本——提供較好的彈性:衍生於1.2版本,並提供了額外的新特性,其中大多數是期待已久的。
客戶端側的長連接(client-side keep-alive)
TCP加速(TCP speedups)
響應池(response buffering)
RDP協議
基於源的粘性(source-based stickiness)
更好的統計數據接口(a much better stats interfaces)
更詳細的健康狀態檢測機制(more verbose health checks)
基於流量的健康評估機制(traffic-based health)
支持HTTP認證
服務器管理命令行接口(server management from the CLI)
基於ACL的持久性(ACL-based persistence)
日誌分析器
1.3版本——內容交換和超強負載:衍生於1.2版本,並提供了額外的新特性。
內容交換(content switching):基於任何請求標準挑選服務器池;
ACL:編寫內容交換規則;
負載均衡算法(load-balancing algorithms):更多的算法支持;
內容探測(content inspection):阻止非授權協議;
透明代理(transparentproxy):在Linux系統上允許使用客戶端IP直接連入服務器;
內核TCP拼接(kernel TCPsplicing):無copy方式在客戶端和服務端之間轉發數據以實現數G級別的數據速率;
分層設計(layereddesign):分別實現套接字、TCP、HTTP處理以提供更好的健壯性、更快的處理機制及便捷的演進能力;
快速、公平調度器(fast and fairscheduler):爲某些任務指定優先級可實現理好的QoS;
會話速率限制(session rate limiting):適用於託管環境;
注意:
1)1.1、1.2、1.3的poll和epoll機制對性能影響
1.1l版本默認使用的polling系統爲select(),其處理的文件數達數千個時性能便會急劇下降。
1.2和1.3版本默認的爲poll(),在有些操作系統上可會也會有性能方面的問題,但在Solaris上表現相當不錯。
HAProxy1.3在Linux 2.6及打了epoll補丁的Linux2.4上默認使用epoll,在FreeBSD上使用kqueue,這兩種機制在任何負載上都能提供恆定的性能表現。
2) 高性能選型方案
Linux 2.6.32及之後版本上運行HAProxy 1.4;
打了epoll補丁的Linux2.4上運行HAProxy 1.4;
FreeBSD上運行HAProxy1.4;
Solaris10上運行HAProxy 1.4;
3)splice()調用機制
在較新版本的Linux2.6(>=2.6.27.19)上,HAProxy還能夠使用splice()系統調用在接口間無複製地轉發任何數據,甚至可以達到10Gbps的性能。
二、HAProxy安裝配置
1.程序包安裝
[root@localhost~]# yum install -y haproxy
主配置文件:/etc/haproxy/haproxy.cfg
主程序:/usr/sbin/haproxy
2.配置文件格式
(1) "global”配置段,用於設定全局配置參數
該配置段中的參數爲進程級別的參數,且通常與其運行的OS相關。
chroot /var/lib/haproxy | 指定haproxy工作目錄,修改可以提高安全性;指定目錄爲空且任何用戶不能有寫權限 |
pidfile /var/run/haproxy.pid | 指定程序進程運行文件 |
maxconn 4000 | 設定每個haproxy進程所接受的最大併發連接數 |
user haproxy | 指明程序運行的屬主 |
group haproxy | 指明程序運行的屬組 |
daemon | 指明haproxy以守護進程的形式運行 |
… ... |
(2) proxy相關配置段,如 "defaults"、" listen"、"frontend" 和 "backend"
defaults段 | 爲所有其它配置段提供默認參數,這配置默認配置參數可由下一個“defaults”所重新設定 |
frontend段 | 定義監聽的套接字(可接受客戶端請求並與之建立連接) |
backend段 | 定義“後端”服務器,代理將會將對應客戶端的請求轉發至這些服務器。 |
listen段 | 通過關聯“前端”和“後端”定義了一個完整的代理,通常只對TCP流量有用。 |
說明:defaults段相關參數
mode http | 設定實例的運行模式或協議,tcp|http|health |
log global | 啓用事件和流量日誌,因此可用於所有區段。每個實例最多可以指定兩個log參數 |
option httplog | 啓用記錄HTTP請求、會話狀態和計時器的功能 |
option dontlognull
optionhttp-server-close
option forwardfor except 127.0.0.0/8 允許在發往服務器的請求首部中插入“X-Forwarded-For”首部,除了本機
option redispatch
retries 3
timeouthttp-request 10s
timeoutqueue 1m
timeoutconnect 10s
timeoutclient 1m
timeoutserver 1m
timeouthttp-keep-alive 10s
timeoutcheck 10s
maxconn 3000 設定一個前端的最大併發連接數,一般1GB內存空間能維護40000-50000併發連接
實例一:
frontend main *:5000
acl url_static path_beg -i /static /p_w_picpaths /javascript/stylesheets
acl url_static path_end -i .jpg .gif .png .css .js
use_backend static if url_static
default_backend app
backendstatic
balance roundrobin
server static 127.0.0.1:4331 check
backendapp
balance roundrobin
server app1 127.0.0.1:5001 check
server app2 127.0.0.1:5002 check
server app3 127.0.0.1:5003 check
server app4 127.0.0.1:5004 check
實例二:
frontendmain
bind *:80
default_backendwebsrvs
backendwebsrvs
balanceroundrobin
server web1 172.16.49.102:80 check
server web2 172.16.49.103:80 check
三、HAProxy代理相關參數
1.balance
定義負載均衡算法,可用於"defaults"、"listen"和"backend"配置段
可用算法:
static-rr | 輪詢、靜態算法,每個後端主機支持的數量無上限 |
roundrobin: | 基於權重輪詢算法,每個後端主機最多支持4128個連接 |
leastconn: | 根據後端主機的負載數量進行調度;僅適用長連接的會話(LDAP、SQL...),動態、可在運行時調整權重 |
source | 將請求的源地址進行hash運算,並由後端服務器的權重總數相除後派發至某匹配的服務器,使得同一個客戶端IP的請求始終被派發至某特定的服務器,可指明hash-type(map-based、consistent) map-based:取模法;靜態;默認 consistent:一致性哈希法;動態;支持權重的調整,影響是局部的 |
uri | 對URI的左半部分(?<QUERY>之前)或整個URI進行hash運算,對同一個URI的請求總是被派發至某特定的服務器,可以指明hash-type(map-based、consistent)。 即第一次請求一個URL分發到一個主機,則之後再次請求相同URL則使用一臺主機響應 |
url_param | 根據url中的指定的參數的值進行調度;把值做hash計算,併除以總權重; 可以指明hash-type(map-based、consistent) |
hdr(<name>) | 根據請求報文中指定的header(如use_agent, referer, hostname)進行調度;把指定的header的值做hash計算;可以指明hash-type(map-based、consistent) |
注意:
(1)當使用uri算法時,第一次請求一個URL分發到一個主機,則之後再次請求相同URL則使用一臺主機響應。當第一次請求之後,若響應該請求的主機服務出現故障,則haproxy或將其調度到其他主機,此主機修復後再次調度回來
(2)URI:統一資源標識符;格式如下:
<SCHEME>://<USER>:<PASSWORD>@<HOST>:<PORT>/<PATH>;<PARAMS>?<QUERY>#<FRAG>
方案://用戶:密碼@主機:端口/路徑;參數(鍵值數據、可以多個參數字段)?查詢語句#片段顯示
2.hash-type
格式:hash-type <method>
定義用於將hash碼映射至後端服務器的方法;不能用於frontend區段;可用方法有map-based和consistent
說明:
(1) map-based:hash表是一個包含了所有在線服務器的靜態數組。其hash值將會非常平滑,會將權重考慮在列,但其爲靜態方法,對在線服務器的權重進行調整將不會生效,這意味着其不支持慢速啓動。此外,挑選服務器是根據其在數組中的位置進行的,因此,當一臺服務器宕機或添加了一臺新的服務器時,大多數連接將會被重新派發至一個與此前不同的服務器上,對於緩存服務器的工作場景來說,此方法不甚適用。
(2) consistent:hash表是一個由各服務器填充而成的樹狀結構;基於hash鍵在hash樹中查找相應的服務器時,最近的服務器將被選中。此方法是動態的,支持在運行時修改服務器權重,因此兼容慢速啓動的特性。添加一個新的服務器時,僅會對一小部分請求產生影響,因此,尤其適用於後端服務器爲cache的場景。不過,此算法不甚平滑,派發至各服務器的請求未必能達到理想的均衡效果,因此,可能需要不時的調整服務器的權重以獲得更好的均衡性。
3.bind
定義一個或者幾個監聽的套接字、只能用於frontend, listen;
bind[<address>]:<port_range> [, ...]
bind[<address>]:<port_range> [, ...] interface <interface>
<address> | 可以爲主機名、IPv4地址、IPv6地址或*;省略、*或0.0.0.0時,表示監聽所有IPv4地址 |
<port_range> | 特定的TCP端口,或者端口範圍;小於1024需要特定用戶才能使用 |
<interface> | 指定物理接口的名稱,不能使用接口別名 |
4.default_backend
爲frontend指明使用的默認後端;default_backend<backend>
實例:
use_backend dynamic if url_dyn
use_backend static if url_css url_img extension_img
default_backend dynamic
注意:use_backend: 條件式後端調用;
5.server
server <name> <addr>[:port][param*];用於爲後端聲明一個server
<name>:名稱,標識符
<addr>[:port]:設定後端真實服務器監聽的端口和地址
[param*]:參數
backup: 設定爲備用服務器,僅在負載均衡場景中的其它server均不可用於啓用此server;
check:健康狀態檢測;
inter<delay>:檢測時間間隔;單位爲ms, 默認爲2000;
rise<count>:設定健康狀態檢查中,某離線的server從離線狀態轉換至正常狀態需要成功檢查的次數;
fall<count>:確認server從正常狀態轉換爲不可用狀態需要檢查的次數;
cookie <value>:爲指定server設定cookie值,用於實現持久連接的功能;
maxconn:此服務接受的併發連接的最大數量;
maxqueue:請求隊列的最大長度;
observe:根據流量判斷後端server的健康狀態;
weight #: 指定權重,#默認爲1,最大爲256;0表示不被調度;
redir<prefix>: 重定向;所有發往此服務器的請求均以302響應;
注意:
健康監測的方式有多種,具體服務可能檢測方法的配置指令不同;此處爲後端http服務時的健康狀態的檢測方法,在defaults配置段定義了" option httpchk "。
"httpchk"、"smtpchk"、"mysql-check"、"pgsql-check"、"ssl-hello-chk"
實例:基於瀏覽器cookie實現sessionsticky(會話綁定)
backendwebsrvs
balance roundrobin
cookie SERVERID insert # 報文首部插入標識
server web1 172.16.49.102:80 check weight 1 cookie websrv1 # cookie綁定名稱參數標識
server web2 172.16.49.103:80 check weight 3 cookie websrv2
註釋:每個server有自己惟一的cookie標識、在backend中定義爲用戶請求調度完成後操縱其cookie
6.向日志中記錄額外信息:
(1) capture requestheader
格式:capture request header <name> len <length>
捕獲並記錄指定的請求首部最近一次出現時的第一個值,僅能用於“frontend”和“listen”區段
<name>:要捕獲的首部的名稱,此名稱不區分字符大小寫,但建議與它們出現在首部中的格式相同,比如大寫首字母。需要注意的是,記錄在日誌中的是首部對應的值,而非首部名稱。
<length>:指定記錄首部值時所記錄的精確長度,超出的部分將會被忽略。
注意:
可以捕獲的請求首部的個數沒有限制,但每個捕獲最多隻能記錄64個字符。爲了保證同一個frontend中日誌格式的統一性,首部捕獲僅能在frontend中定義。
(2)captureresponse header;捕獲並記錄響應首部,其格式和要點同請求首部。
格式:capture response header <name> len <length>
四、HAProxy狀態監控頁配置
1.配置監控頁信息
(1)stats enable
啓用基於程序編譯時默認設置的統計報告,不能用於“frontend”區段。
(2)stats hide-version
啓用統計報告並隱藏HAProxy版本報告,不能用於“frontend”區段。
(3)stats realm
格式:stats realm <realm>
<realm>:實現HTTP基本認證時顯示在瀏覽器中的領域名稱,用於提示用戶輸入一個用戶名和密碼。
啓用統計報告並高精認證領域,不能用於“frontend”區段。haproxy在讀取realm時會將其視作一個單詞,因此,中間的任何空白字符都必須使用反斜線進行轉義。此參數僅在與“statsauth”配置使用時有意義。
(4)stats scope
stats scope {<name> | "." }
<name>:可以是“listen”、“frontend”或“backend”區段的名稱,而“.”則表示statsscope語句所定義的當前區段。
啓用統計報告並限定報告的區段,不能用於“frontend”區段。當指定此語句時,統計報告將僅顯示其列舉出區段的報告信息,所有其它區段的信息將被隱藏。如果需要顯示多個區段的統計報告,此語句可以定義多次。需要注意的是,區段名稱檢測僅僅是以字符串比較的方式進行,它不會真檢測指定的區段是否真正存在。
(5)stats auth
格式:stats auth <user>:<passwd>
<user>:授權進行訪問的用戶名;
<passwd>:此用戶的訪問密碼,明文格式;
啓用帶認證的統計報告功能並授權一個用戶帳號,其不能用於“frontend”區段。
(6)stats admin
格式:stats admin {if | unless } <cond>
在指定的條件滿足時啓用統計報告頁面的管理級別功能,它允許通過web接口啓用或禁用服務器。
2.配置案例:stats狀態監控頁
(1)在配置文件/etc/haproxy/haproxy.cfg中配置代理和監控配置信息
listenstatistics
bind *:9090
stats enable
stats hide-version
stats uri /haproxyadmin?stats
stats realm "HAPorxy\Statistics"
stats auth admin:xuding
stats admin if TRUE
(2)訪問URL:http://172.16.49.101:9090/haproxyadmin?stats
(3)此時即可進入管理頁面進行對後端服務器的管理和頁面監控數據監控
說明:
此時可以管控後端主機的啓停操作,所以演注意安全性
五、錯誤頁面重定向
errorfile:使用haproxy主機本地文件進行響應;
errorloc,errorloc302: 使用指定的url進行響應,響應狀態碼爲302;不適用於GET以外的其它請求方法;
errorloc303:返回303狀態碼;
1.errorfile
格式:errorfile <code> <file>
<code>:指定對HTTP的哪些狀態碼返回指定的頁面;這裏可用的狀態碼有200、400、403、408、500、502、503和504;
<file>:指定用於響應的頁面文件
在用戶請求不存在的頁面時,返回一個頁面文件給客戶端而非由haproxy生成的錯誤代碼;可用於所有段中。
實例:
errorfile400 /etc/haproxy/errorpages/400badreq.http
errorfile403 /etc/haproxy/errorpages/403forbid.http
errorfile503 /etc/haproxy/errorpages/503sorry.http
2.errorloc 和 errorloc302
請求錯誤時,返回一個HTTP重定向至某URL的信息;可用於所有配置段中。
errorloc<code> <url>
errorloc302<code> <url>
<code>:指定對HTTP的哪些狀態碼返回指定的頁面;這裏可用的狀態碼有200、400、403、408、500、502、503和504;
<url>:Location首部中指定的頁面位置的具體路徑,可以是在當前服務器上的頁面的相對路徑,也可以使用絕對路徑;需要注意的是,如果URI自身錯誤時產生某特定狀態碼信息的話,有可能會導致循環定向;
注意:
這兩個關鍵字都會返回302狀態嗎,這將使得客戶端使用同樣的HTTP方法獲取指定的URL,對於非GET廣場法的場景(如POST)來說會產生問題,因爲返回客戶的URL是不允許使用GET以外的其它方法的。如果的確有這種問題,可以使用errorloc303來返回303狀態碼給客戶端。
3. errorloc303
errorloc303 <code> <url>;請求錯誤時,返回一個HTTP重定向至某URL的信息給客戶端;可用於所有配置段中。
<code>:指定對HTTP的哪些狀態碼返回指定的頁面;這裏可用的狀態碼有400、403、408、500、502、503和504;
<url>:Location首部中指定的頁面位置的具體路徑,可以是在當前服務器上的頁面的相對路徑,也可以使用絕對路徑;需要注意的是,如果URI自身錯誤時產生某特定狀態碼信息的話,有可能會導致循環定向;
實例:
backendwebserver
server 172.16.100.6 172.16.100.6:80 checkmaxconn 3000 cookie srv01
server 172.16.100.7 172.16.100.7:80 checkmaxconn 3000 cookie srv02
errorfile 403/etc/haproxy/errorpages/sorry.htm
errorfile 503/etc/haproxy/errorpages/sorry.htm