第一章 :haproxy介紹
1.1 簡介
- HAProxy 是一款提供高可用性、負載均衡以及基於TCP(第四層)和HTTP(第七層)應用的代理軟件,支持虛擬主機,它是免費、快速並且可靠的一種解決方案。 HAProxy特別適用於那些負載特大的web站點,這些站點通常又需要會話保持或七層處理。HAProxy運行在時下的硬件上,完全可以支持數以萬計的 並發連接。並且它的運行模式使得它可以很簡單安全的整合進您當前的架構中, 同時可以保護你的web服務器不被暴露到網絡上。
- HAProxy 實現了一種事件驅動、單一進程模型,此模型支持非常大的並發連接數。多進程或多線程模型受內存限制 、系統調度器限制以及無處不在的鎖限制,很少能處理數千並發連接。事件驅動模型因為在有更好的資源和時間管理的用戶端(User-Space) 實現所有這些任務,所以沒有這些問題。此模型的弊端是,在多核系統上,這些程序通常擴展性較差。這就是為什么他們必須進行優化以 使每個CPU時間片(Cycle)做更多的工作。
- HAProxy 支持連接拒絕 : 因為維護一個連接的打開的開銷是很低的,有時我們很需要限制攻擊蠕蟲(attack bots),也就是說限制它們的連接打開從而限制它們的危害。 這個已經為一個陷於小型DDoS攻擊的網站開發了而且已經拯救了很多站點,這個優點也是其它負載均衡器沒有的。
- HAProxy 支持全透明代理(已具備硬件防火牆的典型特點): 可以用客戶端IP地址或者任何其他地址來連接后端服務器. 這個特性僅在Linux 2.4/2.6內核打了cttproxy補丁后才可以使用. 這個特性也使得為某特殊服務器處理部分流量同時又不修改服務器的地址成為可能。
1.2 性能
- 單進程、事件驅動模型降低了上下文切換的開銷及內存占用。
- I/O事件檢查器允許其在高並發連接中對任何連接的任何事件實現即時探測。
- 在任何可用的情況下,單緩沖機制能以不復制任何數據的方式完成讀寫操作,這會節約大量 的cpu時鍾周期以及內存帶寬。
- 借助於Linux 2.6 (>= 2.6.27.19)上的splice()系統調用,HAProxy可以實現零復制轉發(Zero-copy forwarding),在Linux 3.5及以上的OS中還可以實現零復制啟動(zero-starting)
- 內存分配器在固定大小的內存池中可實現即時內存分配,這能夠顯著減少創建一個會話的時長。
- 樹型存儲:側重於使用作者多年前開發的彈性二叉樹,實現了以O(log(N))的低開銷來保持計時器命令、保持運行隊列命令及管理輪詢及最少連接隊列。
- 優化的HTTP首部分析:優化的首部分析功能避免了在HTTP首部分析過程中重讀任何內存區域。
- 精心地降低了昂貴的系統調用,大部分工作都在用戶空間完成,如時間讀取、緩沖聚合及文件描述符的啟用和禁用等
第二章 部署安裝
2.1 編譯安裝
打開IP轉發 echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf && sysctl -p yum -y install gcc systemd-devel #安裝依賴 tar xf haproxy-1.8.7.tar.gz #解壓 cd haproxy-1.8.7/ make TARGET=linux2628 PREFIX=/usr/local/haproxy make install PREFIX=/usr/local/haproxy cp /usr/local/haproxy/sbin/haproxy /usr/sbin/ cp ./examples/haproxy.init /etc/init.d/haproxy chmod 755 /etc/init.d/haproxy useradd -r haproxy mkdir /etc/haproxy
2.2 編寫配置文件
vim /etc/haproxy/haproxy.cfg # Global settings #--------------------------------------------------------------------- global #全局配置 log 127.0.0.1 local3 info #指定服務器的日志級別 chroot /usr/local/haproxy #改變工作目錄 user haproxy #用戶組和用戶 group haproxy daemon #以守護進程的方式運行 maxconn 4000 #最大連接數 defaults #默認配置 log global mode http #7層http;4層tcp 如果要讓haproxy支持虛擬主機,mode 必須設為http option httplog #http日志格式 timeout connect 5000 #連接超時(毫秒) timeout client 50000 #客戶端超時(毫秒) timeout server 50000 #服務器超時(毫秒) listen stats mode http bind 10.0.0.19:1080 stats enable stats hide-version stats uri /stats stats admin if TRUE frontend web_front #前端配置 web_front名稱可自定義 bind 10.0.0.19:80 #發起的http請求到80端口,會轉發到設置的ip及端口 mode http log global option httplog # 啟用http日志 default_backend http_back backend http_back #后端配置,http_back名稱可自定義 option httpchk GET /index.html #設置健康檢查頁面 option forwardfor header X-Forwarded-For #傳遞客戶端真實IP balance roundrobin #roundrobin 輪詢方式 # 需要轉發的ip及端口 server elk2 10.0.0.22:80 check inter 2000 rise 3 fall 3 weight 30 server elk1 10.0.0.21:80 check inter 2000 rise 3 fall 3 weight 30 server elk3 10.0.0.24:80 check inter 2000 rise 3 fall 3 weight 30
2.3 日志配置
打開rsyslog配置: vi /etc/rsyslog.conf 去掉下面兩行前面的#號 $ModLoad imudp $UDPServerRun 514 並添加下面一行 local3.* /var/log/haproxy.log 重啟rsyslog systemctl restart rsyslog
2.4 啟動haproxy
service haproxy start
第三章 配置文件詳解
- Global段:用來定義進程安全相關配置,性能參數調整,Debug等服務相關的配置。
- Proxy段:用來定義與調度的具體實現方式,Proxy段具體包括
- listen段:listen可以直接確定一種調度工作方式
- frontend段:定義與客戶端通信的工作方式
- backend段:定義與后端主機通信的工作方式
- defaults段:定義listen,frontend,backend中某些變量的默認值
3.1 進程及安全配置相關參數
chroot /usr/local/haproxy:禁錮根,haproxy進程以此目錄作為根目錄,防止haproxy進程被劫持而設定的安全性配置 user haproxy: 運行haproxy進程的用戶和組 group haproxy: daemon:表示haproxy運行於后台守護進程,而非前台(調試模式) log 127.0.0.1 local3 info #local3是設備,對應於 /etc/rsyslog.conf中的配置,默認回收info的日志級別 pidfile /var/run/haproxy.pid #將所有守護進程的PID寫入文件 maxconn 4000 #最大連接數
3.2log日志詳解
log <address> [len <length> ] [format <format> ] <facility> [max level [min level] ] 添加全局系統日志服務器。可以定義幾個全局服務器。他們將接收啟動和退出日志以及來自代理的所有日志
address
一個IPv4地址,可選地跟一個冒號和一個UDP端口。如果沒有指定端口,默認使用514(標准系統日志港口)。 IPv6地址,后跟冒號和可選的UDP端口。如果沒有指定端口,默認使用514(標准系統日志港口)。 記住一個UNIX域套接字的文件系統路徑chroot的注意事項(確保路徑可以在里面訪問chroot)和uid / gid(確保路徑適當可寫)。
length可選最大行長度
日志行大於此值在被發送之前將被截斷。原因是syslog服務器在日志行長度上的行為不同。所有的服務器都支持默認值為1024,但某些服務器只需放大較大的一行而其他人則會記錄它們。如果服務器支持長行,它可能會在這里設置這個值是有意義的,以避免截斷long線。同樣,如果一台服務器丟掉長線,最好是在發送它們之前截斷它們。可接受的值是80到65535包括的。默認值1024通常適用於所有標准用法。一些具體的長時間捕獲或者說JSON格式的日志可能需要較大的值。你可能也需要如果您的請求URI被截斷,請增“ tune.http.logurilen ”。
format生成系統日志消息時使用的日志格式
rfc3164 RFC3164系統日志消息格式。這是默認設置。
rfc5424 RFC5424系統日志消息格式。
facility必須是24個標准syslog工具之一
kern user mail daemon auth syslog lpr news uucp cron auth2 ftp ntp audit alert cron2 local0 local1 local2 local3 local4 local5 local6 local7
可以指定一個可選的級別來過濾傳出的消息。默認,所有消息都被發送。如果指定了最大級別,則只有帶有。的消息嚴重程度至少與本級別一樣重要。可選的最小值級別可以指定。如果設置了,日志會以更嚴厲的級別發出比這個水平還要高。這用於避免發送某些默認系統日志配置中的所有終端上的“emerg”消息。
3.3 proxies代理配置段
代理配置段:
defaults <name> #為frontend, backend, listen提供默認配置 frontend <name># 前端,相當於nginx, server {} backend <name>#后端,相當於nginx, upstream {} listen <name>同時擁有前端和后端,適用於一對一環境 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 #定義的多個后端
3.4 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分配請求
3.5 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最大值為256,0表示不參與負載均衡(不被調度) backlog <backlog>:當server的連接數達到上限后的后援隊列長度 backup:設定當前server為備用服務器 default-server [param*] 為backend中的各server設定默認選項
3.6 統計接口啟用相關的參數
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中的管理功能
3.7連接超時
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詳解
haproxy的ACL用於實現基於請求報文的首部、響應報文的內容或其他的環境狀態信息來做出轉發決策,這大大增加了其配置彈性。其配置法則一般分為兩部,首先定義ACL,既定義一個測試條件,而后在條件得到滿足時執行某特定動作,如阻止訪問或者轉發至某特定的后端。
4.1 ACL語法
acl <aclname> <criterion> [flags] [operator] [<value>] ...
4.2 語法詳解
1、aclname
ACL名稱,區分字符大小寫,且其只能包含大小寫字母、數字、-(連接線)、_(下划線)、.(點號)和:(冒號);haproxy中,acl可以重名,這可以把多個測試條件定義為一個共同的acl;
2、criterion
指明檢查條件,測試標准,即對什么信息發起測試;測試方式可以由[flags]指定的標志進行調整;而有些測試標准也可以需要為其在之前指定一個操作符[operator];
條件 dst 目標IP dst_port 目標PORT src 源IP src_port 源PORT ```shell ------------------------------------------------------------------------------------------------- **3、[flags]:標識位 ** ```shell -i:在匹配所有后續模式時忽略大小寫。 -f:從文件加載模式。 -m:使用特定的模式匹配方法 -n:禁止DNS解析 -M:像地圖文件一樣加載-f指向的文件。 -u:強制ACL的唯一標識 -- :強制結束標志。
4、value類型
- boolean:真假 - integer or integer range:整數值 - IP address / network:IP地址、網絡地址 - string (exact, substring, suffix, prefix, subdir, domain) 匹配指定的首部的值 exact:精確匹配 substring:子串匹配 suffix:后綴匹配 prefix:前綴匹配 subdir:子路徑匹配 domain:域名子串匹配 - regular expression:正則表達式匹配 - hex block:16進制數字塊
同一個acl中可以指定多個測試條件,這些測試條件需要由邏輯操作符指定其關系。條件間的組合測試關系有三種:“與”(默認即為與操作)、“或”(使用“||”操作符)以及“非”(使用“!”操作符)。
5、 [operator] 匹配整數值
eq、ge、gt、le、lt 匹配字符串: -m method : 指定模式匹配方法 其中flag中的 -m 選項可使用的模式匹配方法如下,需要說明的是有些方法已被默認指定無需聲明,例如int,ip "found" : 只是用來探測數據流中是否存在指定數據,不進行任何比較 "bool" : 檢查結果返回布爾值。匹配沒有模式,可以匹配布爾值或整數,不匹配0和false,其他值可以匹配 "int" : 匹配整數類型數據;可以處理整數和布爾值類型樣本,0代表false,1代表true "ip" : 匹配IPv4,IPv6地址類型數據。該模式僅被IP地址兼容,不需要特別指定 "bin" : 匹配二進制數據 "len" : 匹配樣本的長度的整數值 "str" : 精確匹配,根據字符串匹配文本 "sub" : 子串匹配,匹配文本是否包含子串 "reg" : 正則匹配,根據正則表達式列表匹配文本 "beg" : 前綴匹配,檢查文本是否以指定字符串開頭 "end" : 后綴匹配,檢查文本是否以指定字符串結尾 "dir" : 子目錄匹配,檢查部分文本中以" / "作為分隔符的內容是否含有指定字符串 "dom" : 域匹配。檢查部分文本中以" . "作為分隔符的內容是否含有指定字符串
第五章 配置HAProxy支持https協議
配置支持ssl會話 bind *:443 ssl crt /PATH/TO/SOME_PEM_FILE ssl:要求必須使用 ssl會話 crt:指明證書文件路徑 –> 證書和私鑰都在這個文件內 把80端口的請求重向定443 bind *:80 redirect scheme https if !{ ssl_fc } scheme:協議 ssl_fc:如果請求的是非ssl前端的,則重定向(無需定義,因為是內建的,直接調用 ssl_fc) 向后端傳遞用戶請求的協議和端口 http_request set-header X-Forwarded-Port %[dst_port] http_request add-header X-Forwared-Proto https if { ssl_fc }