企業級應用:負載均衡層——haproxy(一)

本文首發於我的個人網站: 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 &quot;%r&quot; %s %b &quot;%{UserAgent}i&quot;'/>
#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。可以用腳本寫一個循環來實現。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章