HAproxy的安裝設定及範例

2020-08-09 12:19:42

簡介

  • HAProxy 是一款提供高可用性、負載均衡以及基於**TCP(第四層)HTTP(第七層)**應用的代理軟體,支援虛擬主機,它是免費、快速並且可靠的一種解決方案。 HAProxy特別適用於那些負載特大的web站點,這些站點通常又需要對談保持或七層處理。HAProxy執行在時下的硬體上,完全可以支援數以萬計的 併發連線。並且它的執行模式使得它可以很簡單安全的整合進您當前的架構中, 同時可以保護你的web伺服器不被暴露到網路上。
  • HAProxy 支援全透明代理(已具備硬體防火牆的典型特點): 可以用用戶端IP地址或者任何其他地址來連線後端伺服器. 這個特性僅在Linux 2.4/2.6內核打了cttproxy修補程式後纔可以使用. 這個特性也使得爲某特殊伺服器處理部分流量同時又不修改伺服器的地址成爲可能。

安裝設定HAProxy

  • 安裝haproxy(在server1haproxy排程器上)
[root@server1 ~]# yum install -y haproxy##安裝
[root@server1 ~]# rpm -qi haproxy##檢視詳情資訊
Name        : haproxy
Version     : 1.5.18##版本號
Release     : 8.el7
Architecture: x86_64
Install Date: Sun 09 Aug 2020 09:37:17 AM CST
Group       : System Environment/Daemons 
Size        : 2690238
License     : GPLv2+
Signature   : RSA/SHA256, Thu 26 Jul 2018 10:00:42 AM CST, Key ID 199e2f91fd431d51
Source RPM  : haproxy-1.5.18-8.el7.src.rpm
Build Date  : Wed 25 Jul 2018 11:16:41 PM CST
Build Host  : x86-040.build.eng.bos.redhat.com
Relocations : (not relocatable)
Packager    : Red Hat, Inc. <http://bugzilla.redhat.com/bugzilla>
Vendor      : Red Hat, Inc.
URL         : http://www.haproxy.org/
Summary     : TCP/HTTP proxy and load balancer for high availability environments
  • 組態檔
[root@server1 ~]# rpm -ql haproxy
/etc/haproxy
/etc/haproxy/haproxy.cfg ##組態檔
/etc/logrotate.d/haproxy
/etc/sysconfig/haproxy
/usr/bin/halog
/usr/bin/iprange
/usr/lib/systemd/system/haproxy.service
/usr/sbin/haproxy

組態檔

  • haproxy 的組態檔由兩部分組成:全域性設定和對代理的設定,共分爲五段:global,defaults,frontend,backend,listen。

組態檔格式

  • global:參數是進程級的,通常和操作系統(OS)相關。這些參數一般只設置一次,如果設定無誤,就不需要再次設定進行修改
  • defaults:設定預設參數的,這些參數可以被利用設定到frontend,backend,listen元件
  • frontend:接收請求的前端虛擬節點,Frontend可以根據規則直接指定具體使用後端的backend(可動態選擇)。
  • backend:後端服務叢集的設定,是真實的伺服器,一個Backend對應一個或者多個實體伺服器。
  • listen:Frontend和Backend的組合體。
  • 其中一些關於時間的格式:
us 微秒(microseconds),即1/1000000秒
ms 毫秒(milliseconds),即1/10000 秒
s: 秒(seconds)
m 分鐘(minutes)
h 小時(hours)
d 天(days)

詳解組態檔

  • haproxy 的組態檔由兩部分組成:全域性設定和對代理的設定,共分爲五段:global,defaults,frontend,backend,listen。
  • global
global
    log         127.0.0.1 local2 ##定義全域性的syslog伺服器,最多可以定義兩個;

    chroot      /var/lib/haproxy ##修改haproxy的工作目錄至指定的目錄並在放棄許可權之前執行chroot()操作,可以提升haproxy的安全級別,不過需要注意的是要確保指定的目錄爲空目錄且任何使用者均不能有寫許可權
    pidfile     /var/run/haproxy.pid ##當前進程id檔案
    maxconn     4000 #最大連線數
    user        haproxy#所屬使用者
    group       haproxy#所屬組
    daemon ##讓haproxy以守護行程的方式工作於後台,其等同於「-D」選項的功能,當然,也可以在命令列中以「-db」選項將其禁用;

    # turn on stats unix socket
    stats socket /var/lib/haproxy/stats#基於原生的檔案傳輸
defaults
    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會把用戶端的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 ##在用戶端建立連線但不請求數據時,關閉用戶端連線
    timeout queue           1m##等待最大時長
    timeout connect         10s##定義haproxy將用戶端請求轉發至後端伺服器所等待的超時時長
    timeout client          1m ##用戶端非活動狀態的超時時長
    timeout server          1m##用戶端與伺服器端建立連線後,等待伺服器端的超長時長
    timeout http-keep-alive 10s ##定義保持連線的超長時長
    timeout check           10s##健康狀態監測的超時時間,過短會誤判,過長資源消耗
    maxconn                 3000 ##設定每個haproxy進程所接受的最大併發連線數,其等同於命令列選項「-n」;「ulimit -n」自動計算的結果正是參照此參數設定的;
  • fronted
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             app##預設存取的是app
  • backend static
backend static
#使用了靜態動態分離(如果url_path匹配 .jpg .gif .png .css .js靜態檔案則存取此後端)
    balance     roundrobin
    server      static 127.0.0.1:4331 check
    ##靜態檔案部署在本機(也可以部署在其他機器)
  • backend app
backend app
#定義一個名爲app後端部分。PS:此處app只是一個自定義名字而已,但是需要與frontend裏面設定項default_backend 值相一致


    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
  • balance關鍵字:
  • 定義負載均衡演算法,可用於「defaults」、「listen」和「backend」。用於在負載均衡場景中挑選一個server,其僅應用於持久資訊不可用的條件下或需要將一個連線重新派發至另一個伺服器時。支援的演算法有:
  1. roundrobin:基於權重進行輪叫,在伺服器的處理時間保持均勻分佈時,這是最平衡、最公平的演算法。此演算法是動態的,這表示其權重可以在執行時進行調整,不過,在設計上,每個後端伺服器僅能最多接受4128個連線;並支援慢啓動。

  2. static-rr:基於權重進行輪叫,與roundrobin類似,但是爲靜態方法,在執行時調整其伺服器權重不會生效;不過,其在後端伺服器連線數上沒有限制;不支援慢啓動,在高負荷的情況下,伺服器重新上線時會立即被分配大量連線。

  3. leastconn(WLC):適用於長連線的對談,新的連線請求被派發至具有最少連線數目的後端伺服器;在有着較長時間對談的場景中推薦使用此演算法,如LDAP、SQL等,其並不太適用於較短對談的應用層協定,如HTTP;此演算法是動態的,可以在執行時調整其權重;

  4. source:將請求的源地址進行hash運算,並由後端伺服器的權重總數相除後派發至某匹配的伺服器;這可以使得同一個用戶端IP的請求始終被派發至某特定的伺服器;不過,當伺服器權重總數發生變化時,如某伺服器宕機或新增了新的伺服器,許多用戶端的請求可能會被派發至與此前請求不同的伺服器;常用於負載均衡無cookie功能的基於TCP的協定;其預設爲靜態,不過也可以使用hash-type修改此特性;

1)對原地址hash,第一次排程時使用WLC source:IP層,位於同一個NAT伺服器背後的多個請求都會定向至同一個upstream
server,不利於負載均衡,一般只有不支援使用cookie插入又需要保持對談時使用 cookie:應用層,有更好的負載均衡效果;

2)hash/weight%ip :除以權重取模

  1. uri:對URI的左半部分(「問題」標記之前的部分)或整個URI進行hash運算,並由伺服器的總權重相除後派發至某匹配的伺服器;這可以使得對同一個URI的請求總是被派發至某特定的伺服器,除非伺服器的權重總數發生了變化;此演算法常用於代理快取或反病毒代理以提高快取的命中率;需要注意的是,此演算法僅應用於HTTP後端伺服器場景;其預設爲靜態演算法,不過也可以使用hash-type修改此特性;

  2. url_param:通過爲URL指定的參數在每個HTTP GET請求中將會被檢索;如果找到了指定的參數且其通過等於號「=」被賦予了一個值,那麼此值將被執行hash運算並被伺服器的總權重相除後派發至某匹配的伺服器;此演算法可以通過追蹤請求中的使用者標識進而確保同一個使用者ID的請求將被送往同一個特定的伺服器,除非伺服器的總權重發生了變化;如果某請求中沒有出現指定的參數或其沒有有效值,則使用輪叫演算法對相應請求進行排程;此演算法預設爲靜態的,不過其也可以使用hash-type修改此特性;

  3. hdr():對於每個HTTP請求,通過指定的HTTP首部將會被檢索;如果相應的首部沒有出現或其沒有有效值,則使用輪叫演算法對相應請求進行排程;其有一個可選選項「use_domain_only」,可在指定檢索類似Host類的首部時僅計算域名部分(比如通過www.feiyu.com來說,僅計算feiyu字串的hash值)以降低hash演算法的運算量;此演算法預設爲靜態的,不過其也可以使用hash-type修改此特性;

  4. rdp-cookie(name) 表示根據據cookie(name)來鎖定並雜湊每一次TCP請求。

設定案例

  • 實驗環境:
  • 利用四臺虛擬機器實現簡單的前端輪詢排程。一臺用戶端,一臺haproxy排程器,兩臺RS
    server1 192.168.43.10(haproxy排程器)
    server2 192.168.43.2(用戶端)
    server3 192.168.43.3(RS)
    server4 192.168.43.4(RS)

統計頁面的輸出機制 機製

  • 刪去了原組態檔多餘的部分。(global部分沒有改動,default加了幾行,刪去了backend static部分,將app1和app2改成自己後端伺服器的ip)
global
    log         127.0.0.1 local2
    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    maxconn     4000
    user        haproxy
    group       haproxy
    daemon
    stats socket /var/lib/haproxy/stats
defaults
    mode                    http
    log                     global
    option                  httplog
    option                  dontlognull
    option http-server-close
    option forwardfor       except 127.0.0.0/8
    option                  redispatch
    retries                 3
    timeout http-request    10s
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 3000
    stats uri /status	## 自定義統計頁面的url
    stats auth admin:123456##統計頁面使用者名稱和密碼的設定
    stats hide-version##隱藏統計頁面上的HAproxy的版本資訊
    stats refresh 5s## 統計頁面自動重新整理時間
frontend  main *:80
    default_backend             app
backend app
    balance     roundrobin
    server  app1 192.168.43.3:80 check
    server  app2 192.168.43.4:80 check
  • 實驗結果:在瀏覽器存取192.168.43.10/status
    在这里插入图片描述
    在这里插入图片描述

定義獨立日誌檔案

  • vim /etc/rsyslog.conf
    在这里插入图片描述
    在这里插入图片描述
  • systemctl restart rsyslog重新啓動日誌服務
  • 實驗結果:日誌檔案獨立出來了,並且顯示正常內容
    在这里插入图片描述

動靜分離範例

  • vim /etc/haproxy.haproxy.cfg
  • 前面global和default與上面保持一致
rontend  main *: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             app

backend static
   balance     roundrobin
  server      static 192.168.43.3:80 check

backend app
    balance     roundrobin
    server  app2 192.168.43.4:80 check
    server backup 192.168.43.2:80 backup
  • 實驗結果測試
  • 在server3中/var/www/html/放一張照片,用於測試靜態頁面的存取
  • 在server4中,安裝php,在/var/www/html,建立index.php檔案
[root@server4 html]# cat index.php
<?php
phpinfo()
?>
  • 測試頁面:測試192.168.43.10/images就會出現一張圖片
    在这里插入图片描述

讀寫分離案例

  • vim /etc/haproxy.haproxy.cfg
  • 前面global和default與上面保持一致
frontend  main *:80
    acl read_request method GET ##請求方法
    acl read_request method POST
    acl write_request method PUT
    acl write_request method POST

    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 read_request##如果是讀請求用 static
    use_backend app          if write_request ##如果是寫請求用 app
    default_backend             app

backend static
   balance     roundrobin
  server      static 192.168.43.3:80 check

backend app
    balance     roundrobin
    server  app2 192.168.43.4:80 check
    server backup 192.168.43.2:80 backup
  • 實驗結果測試
  • 在server3和server4的/var/www/html/下寫入兩個檔案用於測試
- [root@server3 html]# cat index.php
<html>
<body>

<form action="upload_file.php" method="post"
enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file" /> 
<br />
<input type="submit" name="submit" value="Submit" />
</form>

</body>
</html>
[root@server3 html]# cat upload_file.php
<?php
if ((($_FILES["file"]["type"] == "image/gif")
|| ($_FILES["file"]["type"] == "image/jpeg")
|| ($_FILES["file"]["type"] == "image/pjpeg"))
&& ($_FILES["file"]["size"] < 20000))
  {
  if ($_FILES["file"]["error"] > 0)
    {
    echo "Return Code: " . $_FILES["file"]["error"] . "<br />";
    }
  else
    {
    echo "Upload: " . $_FILES["file"]["name"] . "<br />";
    echo "Type: " . $_FILES["file"]["type"] . "<br />";
    echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
    echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br />";

    if (file_exists("upload/" . $_FILES["file"]["name"]))
      {
      echo $_FILES["file"]["name"] . " already exists. ";
      }
    else
      {
      move_uploaded_file($_FILES["file"]["tmp_name"],
      "upload/" . $_FILES["file"]["name"]);
      echo "Stored in: " . "upload/" . $_FILES["file"]["name"];
      }
    }
  }
else
  {
  echo "Invalid file";
  }
?>
  • 在server4中/var/www/html建立一個upload目錄並開滿許可權,用於圖片的寫入

  • chmod 777 /var/ww/html/upload

  • 實驗結果測試
    在这里插入图片描述

  • server4中upload下成功寫入上傳圖片