本文首發於我的個人網站: https://hewanyue.com/
本文作者: Hechao
本文鏈接: https://hewanyue.com/blog/5aeb7732.html
HAProxy是法國開發者 威利塔羅(Willy Tarreau) 在2000年使用C語言開發的一個開源軟件,是一款具備高併發(一萬以上)、高性能的TCP和HTTP負載均衡器,支持基於cookie的持久性,自動故障切換,支持正則表達式及web狀態統計。
HAProxy特別適用於那些負載特大的web站點,這些站點通常又需要會話保持或七層處理。HAProxy運行在當前的硬件上,完全可以支持數以萬計的併發連接。並且它的運行模式使得它可以很簡單安全的整合進您當前的架構中, 同時可以保護你的web服務器不被暴露到網絡上。
包括 GitHub、Bitbucket、Stack Overflow、Reddit、Tumblr、Twitter和 Tuenti[7]在內的知名網站,及亞馬遜網絡服務系統都使用了HAProxy。
HAProxy功能
HAProxy功能:
- TCP和HTTP反向代理
- SSL/TSL服務器
- 可以針對HTTP請求添加cookie,進行路由後端服務器
- 可平衡負載至後端服務器,並支持持久連接
- 支持所有主服務器故障切換至備用服務器
- 支持專用端口實現監控服務
- 支持不影響現有連接情況下停止接受新連接請求
- 可以在雙向添加,修改或刪除HTTP報文首部
- 響應報文壓縮
- 支持基於pattern實現連接請求的訪問控制
- 通過特定的URI爲授權用戶提供詳細的狀態信息
不具備的功能:
- 正向代理–squid,nginx
- 緩存代理–varnish
- web服務–nginx、tengine、apache、php、tomcat
- UDP–目前不支持UDP協議,2.1版本會支持UDP協議代理
- 單機性能–LVS
HAProxy安裝
HAProxy 支持基於lua實現功能擴展,lua是一種小巧的腳本語言,於1993年由巴西里約熱內盧天主教大學(Pontifical Catholic University of Rio de Janeiro)裏的一個研究小組開發,其設計目的是爲了嵌入應用程序中,從而爲應用程序提供靈活的擴展和定製功能。
由於centos自帶的lua版本比較低並不符合HAProxy要求的lua最低版本(5.3)的要求,因此需要編譯安裝較新版本的lua環境,然後才能編譯安裝HAProxy。
安裝lua環境
配置lua環境
yum install libtermcap-devel ncurses-devel libevent-devel readline-devel gcc make
下載lua源碼tar包
wget http://www.lua.org/ftp/lua-5.3.5.tar.gz
編譯安裝lua
tar xvf lua-5.3.5.tar.gz
cd lua-5.3.5
make linux test
安裝HAProxy
下載haproxy源碼包
wget http://www.haproxy.org/download/2.0/src/haproxy-2.0.8.tar.gz
安裝依賴包
yum install gcc gcc-c++ glibc glibc-devel pcre pcre-devel openssl openssl-devel systemd-devel
(附加工具包net-tools vim iotop bc zip unzip zlib-devel lrzsz tree screen lsof tcpdump wget ntpdate
)
編譯安裝haproxy
cd haproxy-2.0.8
HAProxy 1.8及1.9版本編譯參數:
make ARCH=x86_64 \
TARGET=linux2628 \
USE_PCRE=1 \
USE_OPENSSL=1 \
USE_ZLIB=1 \
USE_SYSTEMD=1 \
USE_CPU_AFFINITY=1 \
PREFIX=/apps/haproxy
HAProxy 2.0編譯參數:
make ARCH=x86_64 \
TARGET=linux-glibc USE_PCRE=1 \
USE_OPENSSL=1 \
USE_ZLIB=1 \
USE_SYSTEMD=1 \
USE_CPU_AFFINITY=1 \
USE_LUA=1 \
LUA_INC=/data/tar/lua-5.3.5/src/ \
LUA_LIB=/data/tar/lua-5.3.5/src/ \
PREFIX=/apps/haproxy
make install PREFIX=/apps/haproxy
cp haproxy /usr/sbin/
haproxy啓動腳本
vim /usr/lib/systemd/system/haproxy.service
[Unit]
Description=HAProxy Load Balancer
After=syslog.target network.target
[Service]
ExecStartPre=/usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -c -q
ExecStart=/usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /var/lib/haproxy/haproxy.pid
ExecReload=/bin/kill -USR2 $MAINPID
[Install]
WantedBy=multi-user.target\
haproxy配置文件(基本配置文件)
mkdir /etc/haproxy
vim /etc/haproxy/haproxy.cfg
global
chroot /apps/haproxy #鎖定運行目錄
stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin #socket文件
uid 99 #運行haproxy的用戶身份,也可設user,group
gid 99
daemon #以守護進程運行
# nbproc 4 #指定每個haproxy進程開啓的線程數,默認爲每個進程一個線程
# cpu-map 1 0 #綁定haproxy 進程至指定CPU
# cpu-map 2 1
# cpu-map 3 2
# cpu-map 4 3
maxconn 100000 #每個haproxy進程的最大併發連接數
#maxsslconn #每個haproxy進程ssl最大連接數,用於haproxy配置了證書的場景下
#spread-checks #後端server狀態check隨機提前或延遲百分比時間,建議2-5(20%-50%)之間
pidfile /var/lib/haproxy/haproxy.pid
log 127.0.0.1 local3 info #定義全局的syslog服務器;最多可以定義兩個
defaults
option http-keep-alive
option forwardfor
maxconn 100000
mode http
timeout connect 300000ms
timeout client 300000ms
timeout server 300000ms
listen stats
mode http
bind 0.0.0.0:9999
stats enable
log global
stats uri /haproxy-status
stats auth haadmin:q1w2e3r4ys
listen web_port
bind 192.168.32.84:80
mode http
log global
server web1 127.0.0.1:8080 check inter 3000 fall 2 rise 5
設置haproxypid及socket創建權限
useradd -s /sbin/nologin -r -u 99 haproxy
mkdir /var/lib/haproxy
chown 99.99 /var/lib/haproxy/ -R
至此,才完成haproxy的安裝與配置,啓動並查看haproxy的狀態是否正常吧。
systemctl enable --now haproxy
systemctl status haproxy
配置web均衡
haproxy最主要的功能就是爲後端服務器做反向代理,例如我們要爲後面的四個web服務器做反向代理,配置文件如下:
global
maxconn 100000
chroot /apps/haproxy
stats socket /var/lib/haproxy/haproxy.sock1 mode 600 level admin process 1
stats socket /var/lib/haproxy/haproxy.sock2 mode 600 level admin process 2
uid 99
gid 99
daemon
nbproc 2 #指定每個haproxy進程開啓的線程數,默認爲每個進程一個線程
cpu-map 1 0 #cpu工作線程綁定
cpu-map 2 1
# cpu-map 3 2
# cpu-map 4 3
pidfile /var/lib/haproxy/haproxy.pid
log 127.0.0.1 local3 info
defaults
option redispatch #當server Id對應的服務器掛掉後,強制定向到其他健康的服務器
option abortonclose #當服務器負載很高的時候,自動結束掉當前隊列處理比較久的鏈接
option http-keep-alive #開啓與客戶端的會話保持
option forwardfor #透傳客戶端真實IP至後端web服務器
mode http #默認工作類型
timeout connect 600s #客戶端請求到後端server的最長連接等待時間(TCP之前)
timeout server 600s #客戶端請求到後端服務端的超時超時時長(TCP之後)
timeout client 600s #與客戶端的最長非活動時間
timeout http-keep-alive 120s #session會話保持超時時間,範圍內會轉發到相同的後端服務器
timeout check 50s #對後端服務器的檢測超時時間option http-keep-alive
#frontend WEB_PORT_80
# bind 192.168.32.84:80
# mode http
# use_backend web_prot_http_nodes
#backend web_prot_http_nodes
# mode http
# option forwardfor
# balance static-rr
# server web0 192.168.32.8:80 check inter 3000 fall 3 rise 5
# server web3 192.168.32.83:80 check inter 3000 fall 3 rise 5
# server web2 192.168.32.82:80 check inter 3000 fall 3 rise 5
# server web1 192.168.32.81:80 check inter 3000 fall 3 rise 5
listen stats
bind 0.0.0.0:9999
mode http
stats enable
log global
stats uri /proxy_status #進入後臺狀態頁url路徑
stats auth haadmin:hapasswd #進入後臺的賬號密碼
listen web_host #使用listen替換frontend+backend的配置方式
bind 192.168.32.84:80
mode http
log global
balance roundrobin #定義調度算法爲roundrobin
server web0 192.168.32.8:80 weight 1 check addr 192.168.32.8 port 9000 inter 3000 fall 2 rise 5
server web1 192.168.32.81:80 weight 1 check ddpr 192.168.32.81 port 9000 inter 3000 fall 2 rise 5
server web2 192.168.32.82:80 weight 1 check addr 192.168.32.82 port 9000 inter 3000 fall 2 rise 5
server web3 192.168.32.83:80 weight 1 check addr 192.168.32.83 port 9000 inter 3000 fall 2 rise 5
重啓服務systemctl restart haproxy
,便可登陸本機的狀態頁(haadmin:hapasswd)查看後端服務器狀態。
刷新幾次可以看到,不同pid也就是不同線程提供的status頁面。
配置詳解
globe 全局配置段
進程及安全配置相關的參數
性能調整相關參數
Debug參數
全局配置一般大多類似不用多說,須注意的是nbproc若開啓多線程,socket設置最好也分開設置,最好每個線程用process #指定固定的socket,方便後期用命令行socat工具管理(echo "disable server web_host/web1" | socat stdio /var/lib/haproxy/haproxy.sock2
),例如:
global
maxconn 100000
chroot /apps/haproxy
stats socket /var/lib/haproxy/haproxy.sock1 mode 600 level admin process 1
stats socket /var/lib/haproxy/haproxy.sock2 mode 600 level admin process 2
uid 99
gid 99
daemon
nbproc 2 #指定每個haproxy進程開啓的線程數,默認爲每個進程一個線程
cpu-map 1 0 #cpu工作線程綁定
cpu-map 2 1
pidfile /var/lib/haproxy/haproxy.pid
log 127.0.0.1 local3 info
其他詳細信息參見官方文檔:https://cbonte.github.io/haproxy-dconv/2.0/intro.html
proxies:代理配置段
defaults [<name>] #默認配置項,針對以下的frontend、backend和lsiten生效,可以多個name
frontend <name> #前端servername,類似於Nginx的一個虛擬主機 server。
backend <name> #後端服務器組,等於nginx的upstream
listen <name> #將frontend和backend合併在一起配置
注:name字段只能使用”-”、”_”、”.”、和”:”,並且嚴格區分大小寫,例如:Web和web是完全不同的兩組服務器。
- defaults
option redispatch #當server Id對應的服務器掛掉後,強制定向到其他健康的服務器
option abortonclose #當服務器負載很高的時候,自動結束掉當前隊列處理比較久的鏈接
option http-keep-alive #開啓與客戶端的會話保持
option forwardfor #透傳客戶端真實IP至後端web服務器
mode http #默認工作類型
timeout connect 120s #客戶端請求到後端server的最長連接等待時間(TCP之前)
timeout server 600s #客戶端請求到後端服務端的超時超時時長(TCP之後)
timeout client 600s #與客戶端的最長非活動時間
timeout http-keep-alive 120s #session 會話保持超時時間,範圍內會轉發到相同的後端服務器
timeout check 5s #對後端服務器的檢測超時時間 - frontend
bind:指定HAProxy的監聽地址,可以是IPV4或IPV6,可以同時監聽多個IP或端口,可同時用於listen字段中
bind [<address>]:<port_range> [, ...] [param*]
listen http_proxy #監聽http的多個IP的多個端口和sock文件
bind :80,:443,:8801-8810
bind 10.0.0.1:10080,10.0.0.1:10443
bind /var/run/ssl-frontend.sock user root mode 600 accept-proxy
listen http_https_proxy #https監聽
bind :80
bind :443 ssl crt /etc/haproxy/site.pem
listen http_https_proxy_explicit #監聽ipv6、ipv4和unix sock文件
bind ipv6@:80
bind ipv4@public_ssl:443 ssl crt /etc/haproxy/site.pem
bind [email protected] user root mode 600 accept-proxy
listen external_bind_app1 #監聽file descriptor
bind "fd@${FD_APP1}"
企業生產示例:
frontend WEB_PORT
bind :80,:8080
bind 192.168.7.102:10080,:8801-8810,192.168.7.101:9001-9010
mode http/tcp #指定負載協議類型
use_backend backend_name #調用的後端服務器組名稱
- backend
定義一組後端服務器,backend服務器將被frontend進行調用。
mode http/tcp #指定負載協議類型
option #配置選項
server #定義後端real server
注意:mode要與frontend一致。option後面加httpchk,smtpchk,mysql-check,pgsql-check,ssl-hello-chk方法,可用於實現更多應用層檢測功能。
check #對指定real進行健康狀態檢查,默認不開啓
addr IP #可指定的健康狀態監測IP
port num #指定的健康狀態監測端口
inter num #健康狀態檢查間隔時間,默認2000 ms
fall num #後端服務器失效檢查次數,默認爲3
rise num #後端服務器從下線恢復檢查次數,默認爲2
weight #默認爲1,最大值爲256,0表示不參與負載均衡
backup #將後端服務器標記爲備份狀態
disabled #將後端服務器標記爲不可用狀態
redirect prefix http://www.example.net/ #將請求臨時重定向至其它URL,只適用於http模式
maxconn <maxconn>:當前後端server的最大併發連接數
backlog <backlog>:當server的連接數達到上限後的後援隊列長度
frontend+backend配置實例:
#官網業務訪問入口======================================
frontend WEB_PORT_80
bind 192.168.7.248:80
mode http
use_backend web_prot_http_nodes
backend web_prot_http_nodes
mode http
option forwardfor
server 192.168.7.101 192.168.7.101:8080 check inter 3000 fall 3 rise 5
server 192.168.7.102 192.168.7.102:8080 check inter 3000 fall 3 rise 5
- listen
listen相當於frontend+backend的結合,即定義前端監聽代理,又定義了後端服務器,例如上面的frontend+backend組合可用下面這種listen方式代替:
#官網業務訪問入口=====================================
listen WEB_PORT_80
bind 192.168.7.102:80
mode http
option forwardfor
server web1 192.168.7.101:80 check inter 3000 fall 3 rise 5
server web2 192.168.7.101:80 check inter 3000 fall 3 rise 5
haproxy調度算法
HAProxy通過固定參數balance指明對後端服務器的調度算法,該參數可以配置在listen或backend選項中。
HAProxy的調度算法分爲靜態和動態調度算法,但是有些算法可以根據參數在靜態和動態算法中相互轉換。
靜態算法
- static-rr
基於權重的輪詢調度,不支持權重的運行時調整及後端服務器慢啓動,其後端主機數量沒有限制 - first
根據服務器在列表中的位置,自上而下進行調度,但是其只會當第一臺服務器的連接數達到上限,新請求才會分配給下一臺服務,因此會忽略服務器的權重設置。(生產不常用)
動態算法
- roundrobin
基於權重的輪詢動態調度算法,支持權重的運行時調整,不完全等於lvs中的rr輪訓模式,HAProxy中的roundrobin支持慢啓動(新加的服務器會逐漸增加轉發數),其每個後端backend中最多支持4095個real server,roundrobin爲默認調度算法,且支持對real server權重動態調整。 - leastconn
加權的最少連接的動態,支持權重的運行時調整和慢啓動,即當前後端服務器連接最少的優先調度(新客戶端連接),比較適合長連接的場景使用,比如MySQL等場景。
其他算法
source
源地址hash,基於用戶源地址hash並將請求轉發到後端服務器,默認爲靜態即取模方式,但是可以通過hash-type支持的選項更改,後續同一個源地址請求將被轉發至同一個後端web服務器,比較適用於session保持/緩存業務等場景。
源地址有兩種轉發客戶端請求到後端服務器的服務器選取計算方式,分別是取模法和一致性hash
- map-base取模法
map-based:取模法,基於服務器總權重的hash數組取模,該hash是靜態的即不支持在線調整權重,不支持慢啓動,其對後端服務器調度均衡,缺點是當服務器的總權重發生變化時,即有服務器上線或下線,都會因權重發生變化而導致調度結果整體改變。
所謂取模運算,就是計算兩個數相除之後的餘數,10%7=3, 7%4=3,(2^32-1)%(1+1+2)
取模法示意圖:
取模法配置示例:
listen web_host
bind 192.168.7.101:80,:8801-8810,192.168.7.101:9001-9010
mode tcp
log global
balance source
server web1 192.168.7.103:80 weight 1 check inter 3000 fall 2 rise 5
server web2 192.168.7.104:80 weight 1 check inter 3000 fall 2 rise 5
- 一致性hash
一致性哈希,該hash是動態的,支持在線調整權重,支持慢啓動,優點在於當服務器的總權重發生變化時,對調度結果影響是局部的,不會引起大的變動,hash(o)mod n 。
Hash對象到後端服務器的映射關係:
一致性hash後端服務器在線與離線的調度方式示意圖:
一致性hash配置示例:
listen web_host
bind 192.168.7.101:80,:8801-8810,192.168.7.101:9001-9010
mode tcp
log global
balance source
hash-type consistent
server web1 192.168.7.103:80 weight 1 check inter 3000 fall 2 rise 5
server web2 192.168.7.104:80 weight 1 check inter 3000 fall 2 rise 5
uri
基於對用戶請求的uri做hash並將請求轉發到後端指定服務器,也可以通過map-based和consistent定義使用取模法還是一致性hash。
uri 取模法配置示例:
listen web_host
bind 192.168.7.101:80,:8801-8810,192.168.7.101:9001-9010
mode http
log global
balance uri
server web1 192.168.7.103:80 weight 1 check inter 3000 fall 2 rise 5
server web2 192.168.7.104:80 weight 1 check inter 3000 fall 2 rise 5
uri 一致性hash配置示例:
listen web_host
bind 192.168.7.101:80,:8801-8810,192.168.7.101:9001-9010
mode http
log global
balance uri
hash-type consistent
server web1 192.168.7.103:80 weight 1 check inter 3000 fall 2 rise 5
server web2 192.168.7.104:80 weight 1 check inter 3000 fall 2 rise 5
url_param
url_param對用戶請求的url中的 params 部分中的參數name作hash計算,並由服務器總權重相除以後派發至某挑出的服務器;通常用於追蹤用戶,以確保來自同一個用戶的請求始終發往同一個real server
假設url = http://www.example.com/foo/bar/index.php?k1=v1&k2=v2
則:
host = "www.example.com"
url_param = "k1=v1&k2=v2"
url_param取模法配置示例:
listen web_host
bind 192.168.7.101:80,:8801-8810,192.168.7.101:9001-9010
mode http
log global
balance url_param name,age #支持對單個及多個url_param 值hash
server web1 192.168.7.103:80 weight 1 check inter 3000 fall 2 rise 5
server web2 192.168.7.104:80 weight 1 check inter 3000 fall 2 rise 5
url_param一致性hash配置示例:
listen web_host
bind 192.168.7.101:80,:8801-8810,192.168.7.101:9001-9010
mode http
log global
balance url_param name,age #支持對單個及多個url_param 值hash
hash-type consistent
server web1 192.168.7.103:80 weight 1 check inter 3000 fall 2 rise 5
server web2 192.168.7.104:80 weight 1 check inter 3000 fall 2 rise 5
hdr
針對用戶每個http頭部(header)請求中的指定信息做hash,此處由 name 指定的http首部將會被取出並做hash計算,然後由服務器總權重相除以後派發至某挑出的服務器,假如無有效的值,則會使用默認的輪詢調度。
hdr取模法配置示例:
listen web_host
bind 192.168.7.101:80,:8801-8810,192.168.7.101:9001-9010
mode http
log global
balance hdr(User-Agent)
server web1 192.168.7.103:80 weight 1 check inter 3000 fall 2 rise 5
server web2 192.168.7.104:80 weight 1 check inter 3000 fall 2 rise 5
一致性hash配置示例:
listen web_host
bind 192.168.7.101:80,:8801-8810,192.168.7.101:9001-9010
mode http
log global
balance hdr(User-Agent)
hash-type consistent
server web1 192.168.7.103:80 weight 1 check inter 3000 fall 2 rise 5
server web2 192.168.7.104:80 weight 1 check inter 3000 fall 2 rise 5
rdp-cookie
rdp-cookie對遠程桌面的負載,使用cookie保持會話
rdp-cookie取模法配置示例:
listen RDP
bind 192.168.7.101:3389
balance rdp-cookie
mode tcp
server rdp0 172.18.132.20:3389 check fall 3 rise 5 inter 2000 weight 1
rdp-cookie一致性hash配置示例:
listen RDP
bind 192.168.7.101:3389
balance rdp-cookie
hash-type consistent
mode tcp
server rdp0 172.18.132.20:3389 check fall 3 rise 5 inter 2000 weight 1
基於iptables實現:
net.ipv4.ip_forward = 1
# iptables -t nat -A PREROUTING -d 192.168.7.101 -p tcp --dport 3389 -j DNAT --todestination 172.18.139.20:3389
# iptables -t nat -A POSTROUTING -s 192.168.0.0/21 -j SNAT --to-source 192.168.7.101
random
在1.9版本開始增加一個叫做random的負載平衡算法,其基於一個隨機數作爲一致性hash的key,隨機負載平衡對於大型服務器場或經常添加或刪除服務器非常有用,因爲它可以避免在這種情況下由roundrobin或leastconn導致的錘擊效應。
random配置實例:
listen web_host
bind 192.168.7.101:80,:8801-8810,192.168.7.101:9001-9010
mode http
log global
balance random
server web1 192.168.7.103:80 weight 1 check inter 3000 fall 2 rise 5
server web2 192.168.7.104:80 weight 1 check inter 3000 fall 2 rise 5
算法總結
static-rr--------->tcp/http 靜態
first------------->tcp/http 靜態
roundrobin-------->tcp/http 動態
leastconn--------->tcp/http 動態
random------------>tcp/http 動態
source------------>tcp/http
Uri--------------->http
url_param--------->http 取決於hash_type是否consistent
hdr--------------->http
rdp-cookie-------->tcp
first #使用較少
static-rr #做了session共享的web集羣
roundrobin
random
leastconn #數據庫
source #基於客戶端公網IP的會話保持
Uri--------------->http #緩存服務器,CDN服務商,藍汛、百度、阿里雲、騰訊
url_param--------->http
hdr #基於客戶端請求報文頭部做下一步處理
rdp-cookie #很少使用
詳細可參見官方文檔:https://cbonte.github.io/haproxy-dconv/2.0/configuration.html#4
haproxy工作模式
tcp:四層負載
在四層負載設備中,把client發送的報文目標地址(原來是負載均衡設備的IP地址),根據均衡設備設置的選擇web服務器的規則選擇對應的web服務器IP地址,這樣client就可以直接跟此服務器建立TCP連接併發送數據。
四層工作模式的IP透傳:
haproxy配置中在後端服務器定義中加入關鍵字send-proxy
(注意不要加在check關鍵字屬性的中間了),並重啓服務。
在後端nginx服務器配置中監聽端口處也加上協議名proxy_protocol
,並修改日誌格式,在開頭加入變量$proxy_protocol_addr
,重啓服務後即可在日誌中看到訪問的源地址。
send-proxy
是haproxy後端設置的關鍵字,寫錯會報錯,可以用來啓用代理協議Proxy protocol
。Proxy protocol是HAProxy的作者Willy Tarreau於2010年開發和設計的一個Internet協議,通過爲tcp添加一個很小的頭信息,來方便的傳遞客戶端信息(協議棧、源IP、目的IP、源端口、目的端口等),在網絡情況複雜又需要獲取用戶真實IP時非常有用。
haproxy 配置:
listen web_prot_http_nodes
bind 172.18.32.249:80
mode tcp
balance roundrobin
server web1 192.168.32.81:80 send-proxy check inter 3000 fall 3 rise 5
nginx配置:
http {
log_format main '$proxy_protocol_addr $remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" ';
server {
listen 80 proxy_protocol;
#listen 80;
內核參數優化
haproxy在做四層負載時,如果要監聽bind由keepalived生成的虛擬IP(VIP)時,需要修改內核參數,支持監聽非本機IP,否則監聽VIP的80端口時會導致haproxy服務無法啓動。。
vim /etc/sysctl.conf
net.ipv4.ip_nonlocal_bind = 1
如果多網卡,且VIP與後端VIP不在一個網段,還需要加上地址轉發參數。
net.ipv4.ip_forward = 1
然後sysctl -p
使配置文件生效。
[root@CentOS8 ~]#sysctl -p
net.ipv4.ip_nonlocal_bind = 1
net.ipv4.ip_forward = 1
[root@CentOS8 ~]#
當然,也可以將haproxy改爲監聽0.0.0.0:80,表示監聽本機所有網卡的IP的80端口,當keepalived的VIP漂到本機是,自然也可以被haproxy監聽,沒有時也不影響啓動。不過這樣的話,haproxy只能對一個項目集羣做負載均衡了,而我們實際生產中,都是同時代理多個服務項目集羣的轉發,需通過bind不同IP的80/443端口來實現,如果直接一個服務bind0.0.0.0:80,佔用了所有的80/443端口,顯然就沒法和其他項目共存了。
所以我們建議在四層負載工作模式下,不要監聽0.0.0.0:80,而是監聽指定的VIP。
http:七層代理
七層負載均衡服務器起了一個反向代理服務器的作用,服務器建立一次TCP連接要三次握手,而client要訪問webserver要先與七層負載設備進行三次握手後建立TCP連接,把要訪問的報文信息發送給七層負載均衡;然後七層負載均衡再根據設置的均衡規則選擇特定的webserver,然後通過三次握手與此臺webserver建立TCP連接,然後webserver把需要的數據發送給七層負載均衡設備,負載均衡設備再把數據發送給client;所以,七層負載均衡設備起到了代理服務器的作用。
七層工作模式的IP透傳:
defaults配置中加入選項option forwardfor(四層工作模式下,option forwardfor選項會被忽略[WARNING] : config : 'option forwardfor' ignored for proxy 'web_host' as it requires HTTP mode.
,不影響正常運轉)
haproxy 配置:
defaults
option forwardfor
或者:
option forwardfor header X-Forwarded-xxx #自定義傳遞IP參數,後端web服務器寫X-Forwardedxxx
#如果寫option forwardfor則後端服務器web格式爲X-Forwarded-For
listen配置:
listen web_host
bind 192.168.7.101:80
mode http
log global
balance random
server web1 192.168.32.81:80 weight 1 check inter 3000 fall 2 rise 5
server web2 192.168.32.82:80 weight 1 check inter 3000 fall 2 rise 5
配置web服務器,記錄負載均衡透傳的客戶端IP地址
#apache 配置:
LogFormat "%{X-Forwarded-For}i %a %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{UserAgent}i\"" combined
#tomcat 配置:
pattern='%{X-Forwarded-For}i %l %T %t "%r" %s %b "%{UserAgent}i"'/>
#nginx 日誌格式:
http {
log_format main '"$http_x_forwarded_For" - $remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" ';
haproxy功能實現
初步調整好haproxy的配置文件之後,啓動haproxy服務,就已經可以對後端服務器進行代理來實現負載均衡了,不過很多情況下我們需要對後端服務器進行動態操作,例如修改某些主機的負載權重,對某些主機上線或下線等等,而這時,再不影響業務正常訪問的情況下,對haproxy動態操作方式一般有兩種:在圖形界面status狀態頁下操作,以及使用socat命令行工具通過socket通信。
圖形界面
想實現在status界面擁有修改權限,需在配置文件中加入選項stats admin if TRUE
。注意,TRUE要大寫,否則服務起不來會報錯parsing [/etc/haproxy/haproxy.cfg:52] : error detected while parsing a 'stats admin' rule : no such ACL : 'true'.
最終如下面所示
listen stats
mode http
bind 0.0.0.0:9999
stats enable
log global
stats uri /proxy_status
stats auth haadmin:hapasswd
stats admin if TRUE
這是再刷新status界面,就可以看到界面已經發生了變化
就可以對選擇的主機進行操作了。
命令行方式
這是通過直接與haproxy的socekt通信,socket路徑就是配置文件中指定的socket路徑了,只支持本地通信。而且這需要借主socat的工具,需要先進行安裝socat工具。
yum install socat
用echo信息的方式通過管道傳遞給socat工具指定haproxy的socket,就可以發送與接收haproxy的信息了。
查看haproxy工作的詳細信息
echo "show info" | socat stdio /var/lib/haproxy/haproxy.sock1
查看haproxy控制命令
echo "help" | socat stdio /var/lib/haproxy/haproxy.sock1
help : this message
prompt : toggle interactive mode with prompt
quit : disconnect
show tls-keys [id|*]: show tls keys references or dump tls ticket keys when id specified
set ssl tls-key [id|keyfile] <tlskey>: set the next TLS key for the <id> or <keyfile> listener to <tlskey>
show sess [id] : report the list of current sessions or dump this session
shutdown session : kill a specific session
shutdown sessions server : kill sessions on a server
clear counters : clear max statistics counters (add 'all' for all counters)
show info : report information about the running process [json|typed]
show stat : report counters for each proxy and server [json|typed]
show schema json : report schema used for stats
disable agent : disable agent checks (use 'set server' instead)
disable health : disable health checks (use 'set server' instead)
disable server : disable a server for maintenance (use 'set server' instead)
enable agent : enable agent checks (use 'set server' instead)
enable health : enable health checks (use 'set server' instead)
enable server : enable a disabled server (use 'set server' instead)
set maxconn server : change a server's maxconn setting
set server : change a server's state, weight or address
get weight : report a server's current weight
set weight : change a server's weight (deprecated)
show resolvers [id]: dumps counters from all resolvers section and associated name servers
clear table : remove an entry from a table
set table [id] : update or create a table entry's data
show table [id]: report table usage stats or dump this table's contents
show peers [peers section]: dump some information about all the peers or this peers section
disable frontend : temporarily disable specific frontend
enable frontend : re-enable specific frontend
set maxconn frontend : change a frontend's maxconn setting
show servers state [id]: dump volatile server information (for backend <id>)
show backend : list backends in the current running config
shutdown frontend : stop a specific frontend
set dynamic-cookie-key backend : change a backend secret key for dynamic cookies
enable dynamic-cookie backend : enable dynamic cookies on a specific backend
disable dynamic-cookie backend : disable dynamic cookies on a specific backend
show errors : report last request and response errors for each proxy
set maxconn global : change the per-process maxconn setting
set rate-limit : change a rate limiting value
set severity-output [none|number|string] : set presence of severity level in feedback information
set timeout : change a timeout setting
show env [var] : dump environment variables known to the process
show cli sockets : dump list of cli sockets
show cli level : display the level of the current CLI session
show fd [num] : dump list of file descriptors in use
show activity : show per-thread activity stats (for support/developers)
operator : lower the level of the current CLI session to operator
user : lower the level of the current CLI session to user
show startup-logs : report logs emitted during HAProxy startup
show cache : show cache status
add acl : add acl entry
clear acl <id> : clear the content of this acl
del acl : delete acl entry
get acl : report the patterns matching a sample for an ACL
show acl [id] : report available acls or dump an acl's contents
add map : add map entry
clear map <id> : clear the content of this map
del map : delete map entry
get map : report the keys and values matching a sample for a map
set map : modify map entry
show map [id] : report available maps or dump a map's contents
show pools : report information about the memory pools usage
show profiling : show CPU profiling options
set profiling : enable/disable CPU profiling
show threads : show some threads debugging information
查看線程1工作下的web_host集羣中web1主機的權重
[root@CentOS8 ~]#echo "get weight web_host/web1" | socat stdio /var/lib/haproxy/haproxy.sock1
1 (initial 1)
[root@CentOS8 ~]#
設置線程2工作下的web_host集羣中web1主機的權重爲2。設置時,不迴應信息,說明設置成功。
[root@CentOS8 ~]#echo "set weight web_host/web1 2" | socat stdio /var/lib/haproxy/haproxy.sock2
[root@CentOS8 ~]#
需要注意的一點就是,多線程工作模式下,每個線程是獨立的,設置1線程的權重,在其他線程上並不生效。這就意味着,如果想將某個服務器下線的話,需要在每個線程上都分別下線,上線是,也需要在每個線程中enable server。可以用腳本寫一個循環來實現。