haproxy使用詳解

HAProxy簡介javascript

HAProxy是免費、極速且可靠的用於爲TCP和基於HTTP應用程序提供高可用、負載均衡和代理服務的解決方案,尤爲適用於高負載且須要持久鏈接或7層處理機制的web站點。HAProxy還能夠將後端的服務器與網絡隔離,起到保護後端服務器的做用。HAProxy的負載均衡能力雖不如LVS,但也是至關不錯,並且因爲其工做在7層,能夠對http請求報文作深刻分析,按照本身的須要將報文轉發至後端不一樣的服務器(例如動靜分離),這一點工做在4層的LVS沒法完成。php


安裝配置HAproxycss

HAProxy已經集成在base源中,可直接經過yum下載。
html

[root@node1 ~]# yum install haproxy

固然也能夠去官網直接下載源碼編譯安裝。前端


/etc/haproxy/haproxy.cfg爲haproxy的主配置文件,裏面包括全局配置段(global settings)和代理配置段(proxies)。
java

global settings:主要用於定義haproxy進程管理安全及性能相關的參數node

proxies:代理相關的配置能夠有以下幾個配置端組成。nginx

 - defaults <name>:爲其它配置段提供默認參數,默認配置參數可由下一個「defaults」從新設定。git

 - frontend <name>:定義一系列監聽的套接字,這些套接字可接受客戶端請求並與之創建鏈接。github

 - backend  <name>:定義「後端」服務器,前端代理服務器將會把客戶端的請求調度至這些服務器。

 - listen   <name>:定義監聽的套接字和後端的服務器。相似於將frontend和backend段放在一塊兒 


HAproxy的工做模式:

HAProxy的工做模式通常有兩種:tcp模式和http模式。

tcp模式:實例運行於TCP模式,在客戶端和服務器端之間將創建一個全雙工的鏈接,且不會對7層報文作任何類型的檢查,只能以簡單模式工做。此爲默認模式,一般用於SSL、SSH、SMTP等應用。

http模式:實例運行於HTTP模式,客戶端請求在轉發至後端服務器以前將被深度分析,全部不與RFC格式兼容的請求都會被拒絕。

當實現內容交換時,前端和後端必須工做於同一種模式(通常都是HTTP模式),不然將沒法啓動實例。工做模式可經過mode參數在default,frontend,listen,backend中實現定義。

mode {tcp|http}

下面介紹一些HAproxy的常見用法。


應用實例

基於HAProxy實現負載均衡

在backend段或listen段中經過server定義後端節點。

格式:server <name> <address>[:port] [param*]

<name>:爲此服務器指定的內部名稱

[param*]:爲此服務器設定的一系參數。其可用的參數不少,如下爲經常使用參數。

服務器參數:

backup:設定爲備用服務器,僅在負載均衡場景中的其它server均不可用於啓用此server;

maxconn <maxconn>:指定此服務器接受的最大併發鏈接數;若是發往此服務器的鏈接數目高於此處指定的值,其將被放置於請求隊列,以等待其它鏈接被釋放;

maxqueue <maxqueue>:設定請求隊列的最大長度;

observe <mode>:經過觀察服務器的通訊情況來斷定其健康狀態,默認爲禁用,其支持的類型有「layer4」和「layer7」,「layer7」僅能用於http代理場景;

redir <prefix>:啓用重定向功能,將發往此服務器的GET和HEAD請求均以302狀態碼響應;

weight <weight>:服務器權重,默認爲1,最大值爲256,0表示不參與負載均衡;


定義負載均衡的算法,算法的定義除了listen段和backend段中也能夠放在defaults段中,定義格式以下:

balance <algorithm> [ <arguments> ]

balance url_param <param> [check_post [<max_wait>]]

常見的調度算法有:

roundrobin:基於權重進行輪詢,此算法是動態的其權重能夠在運行時進行調整。

static-rr:基於權重進行輪詢,與roundrobin相似,可是爲靜態方法,在運行時調整其服務器權重不會生效。

leastconn:新的鏈接請求被派發至具備最少鏈接數目的後端服務器,動態算法,適用於較長時間會話的場景。

source:將請求的源地址進行hash運算,並與後端服務器的總權重做取模運算後調度至某臺服務器;同一IP地址的請求將始終被調度至某特定的服務器,靜態算法,可使用hash-type修改此特性;

uri:對URI的左半部分(「?」以前的部分)或整個URI進行hash運算,並與後端服務器的總權重做取模運算後調度至某臺服務器;同一URI的請求將始終被調度至某特定的服務器,靜態算法,可使用hash-type修改此特性;

hdr(<name>):根據用戶請求報文中指定的http首部的值進行調度,經常使用於實現將對同一個虛擬主機的請求始終發往同個backend server。


前端代理服務器上配置示例(其他爲默認配置):

#---------------------------------------------------------------------
# main frontend which proxys to the backends
#---------------------------------------------------------------------
frontend  service *:80
default_backend             app
#---------------------------------------------------------------------
# static backend for serving up p_w_picpaths, stylesheets and such
#---------------------------------------------------------------------
backend app
    balance     roundrobin
    server      app1 192.168.2.7:80 maxconn 3000 weight 2
    server      app2 192.168.2.18:80 maxconn 3000 weight 1
    server      app3 127.0.0.1:8080 backup

在app1(192.168.2.7)上配置測試頁面:

[root@node1 ~]# vim /web/index.html
<h2>server node1</h2>

在app1(192.168.2.18)上:

[root@node2 ~]# vim /web/index.html
<h2>server node2</h2>

在代理服務器上有兩個接口:192.168.1.116(面向客戶端),192.168.2.11。配置完成後啓動haproxy服務。後端節點上啓動nginx服務。

wKioL1XgbxHgCpfGAACQfDMkB_g198.jpg

wKiom1XgbWeB64WxAACNjWrjslE151.jpg

已實現輪詢訪問。

在上述的算法中涉及到hash運算,hash-type參數可定義hash的運算方式。格式以下:

格式:hash-type <map-based|consistent>

map-based:靜態方法,在線調整服務器權重不能當即生效。hash表是一個包含了全部在線服務器的靜態數組。簡而言之,經過這種運算方式將請求調度至後端的某臺服務器,當後端的服務器放生變更時(如某臺服務器宕機或新添加了一臺服務器),大部分的鏈接將會被從新調度至一個與以前不一樣的服務器上。

consistent:動態發放,支持在線調整服務器權重。hash表是一個由各服務器填充而成的樹狀結構,使用此算法調度,當後端的服務器發生變更時,大分佈的鏈接將依舊被調度至本來的服務器上。


默認方式爲map-based,可應用於大部分場景。可是若後端的服務器爲緩存服務器,使用默認方式,當後端的服務器調整時,將致使緩存沒法命中,從而影響系統的性能。推薦的配置方式:

backend <name>
    balance    uri
    hash-type consistent
    server      ....
    server      ...


對後端服務器健康情況的檢測

check爲server的參數,可啓動對此server執行健康狀態的檢測。check藉助其額外的參數可實現更精細的監測機制。

inter <delay>:健康狀態檢測的時間間隔,單位爲毫秒,默認爲2000,可使用fastinter和downinter來根據服務器端狀態優化此時間延遲;

rise <count>:健康狀態檢測中,某離線的server從離線狀態轉換至正常狀態須要成功檢查的次數;

fall <count>:確認server從正常狀態轉換爲不可用狀態須要檢查的次數;

配置示例:

backend app
    balance     roundrobin
    server      app1 192.168.2.7:80 maxconn 3000 weight 2 check inter 1 rise 1 fall 2
    server      app2 192.168.2.18:80 maxconn 3000 weight 1 check inter 1 rise 1 fall 2
    server      app3 127.0.0.1:8080 backup


state頁面

啓用統計報告,經過state頁面可查看到各服務器的狀態及其相關信息。關於state的配置建議單獨定義一個listen。

listen stats
    mode http                                   
    bind 192.168.1.116:1080              #監聽端口  
    stats enable                         #啓用state功能
    stats scope app                      #統計報告的報告區段,不啓動這項則報告全部區段
    stats hide-version                   #隱藏HAProxy版本號
    stats uri /haproxyadmin?stats        #state頁面的訪問路徑
    stats realm Haproxy\ Statistics      #認證時提示信息
    stats auth baby:baby                 #認證的帳號密碼
    stats admin if TRUE                  #啓用管理功能

配置完成後重啓haproxy服務。而後訪問定義的路徑:http://192.168.1.116:1080/haproxyadmin?stats。首先完成認證。

wKioL1XgfiOA3edNAAEFiOoWJ6k464.jpg

wKioL1XgfuOj20y7AAVPQvYm1II564.jpg


基於前面配置完成的健康狀態檢測,如今中止其中一臺後端服務器的nginx服務。

[root@node1 web]# service nginx stop
Stopping nginx:                                            [  OK  ]

wKioL1Xgf6XiZg_MAAF5d2e3Ybc563.jpg

紅色表示服務不在線,若中止全部後端服務器的服務,則會訪問定義爲backup的server(127.0.0.1上的sorry頁面)。

wKiom1XgfjPBj1uVAAEwdYLsgx0446.jpg


wKioL1XggJfhvMeGAACNQwUmeTY001.jpg


基於cookie的session綁定

在響應報文中添加cookie信息,下一次的客戶請求會帶上這個cookie信息,服務器端根據cookie將請求始終定向至後端的某一臺服務器。可用於保持session會話。

cookie配置格式:

cookie <name> [ rewrite | insert | prefix ] [ indirect ] [ nocache ][ postonly ] [ preserve ] [ httponly ] [ secure ][ domain <domain> ]* [ maxidle <idle> ] [ maxlife <life> ]

配置示例:

backend app
    balance     roundrobin
    cookie      babyserver insert nocache indirect
    server      app1 192.168.2.17:80 check port 80 cookie app1
    server      app2 192.168.2.16:80 check port 80 cookie app2

重啓服務,客戶端進行訪問。

客戶端查看響應報文:

wKiom1XggEWAuVnjAACLV3tvbMA193.jpg

Set-Cookie首部已經添加信息,接下來該客戶端的訪問(只要cookie信息還在)將始終被定向至app2。


option forwardfor

客戶端的請求經前端的代理服務器轉發至後端的web服務器,代理服務器在轉發時將目標地址改成後端的某臺web服務器地址,將源地址由client ip(客戶端地址)改成本身面向後端服務器的地址。後端的web服務器若使用默認格式記錄日誌,則記錄的客戶端IP地址都爲前端的代理服務器地址。這時須要在發日後端的請求報文中添加內容爲客戶端IP地址的首部,以便後端的web服務器可以正確獲取客戶端地址。

使用option forwardfor 在發往服務器的請求首部中插入「X-Forwarded-For」首部。

格式:option forwardfor [ except <network> ] [ header <name> ] [ if-none ]

<network>:源地址被該參數匹配到時,禁用此功能;

<name>:可自定義首部名稱代替「X-Forwarded-For」;

if-none:僅在此首部不存在時才容許添加至請求報文中。

backend app
.......
    option forwardfor header X-Client

在後端的web服務器上修改日誌格式。

wKiom1Xg8QyRmQGcAADDZi7p6cU956.jpg

這裏後端的web服務器爲nginx,若爲httpd,%{headname}i獲取指定首部信息。從新加載配置文件後,便可獲取客戶端IP。須要注意的是,HAProxy工做於隧道模式,其僅檢查每個鏈接的第一個請求,所以,僅第一個請求報文被附加此首部。若是想爲每個請求都附加此首部,須要確保同時使用了「option httpclose」、「option forceclose」和「option http-server-close」幾個option。


ACL簡介

haproxy的ACL可以經過檢測請求報文的首部、響應報文的內容或其餘的環境狀態信息做出轉發決策,加強了其配置彈性。配置分兩步驟:首先定義ACL,即定義一個測試條件,再定義動做,即知足測試條件的狀況下執行的某特定動做。

定義格式:acl <aclname> <criterion> [flags] [operator] <value> ...

<aclname>:ACL名稱。

<criterion>:測試標準,即對什麼信息發起測試。

[flags]:目前haproxy的acl支持的標誌位有3個:

    -i:不區分<value>中模式字符的大小寫;

    -f:從指定的文件中加載模式;

    --:標誌符的強制結束標記;

<value>:acl測試的值。

常見的測試標準(criterion)有be_sess_rate,fe_sess_rate,hdr <string>,method <string>,path_beg <string>,path_end <string>,hdr_beg <string>,hdr_end <string>.....具體的用法能夠查閱相關文檔。



基於ACL實現動靜分離

實驗環境:

wKioL1Xg_EzBoyTXAADCON9Uao8884.jpg

haproxy2做爲高可用集羣的備用節點。

前端代理服務器收到的請求經過分析其uri,將靜態內容調度至static server1和2,將動態內容調度至dynamic server1和2。

1)首先haproxy1和haproxy2實現時間同步

2)在haproxy1和haproxy2安裝keepalived和haproxy。

3)編輯配置文件

配置haproxy,配置完成後將配置文件同步至haproxy2節點(關於每一個參數的解釋,可參考http://cbonte.github.io/haproxy-dconv/):

[root@node1 haproxy]# vim haproxy.cfg 
#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
    log         127.0.0.1 local2
    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    maxconn     4000                              #最大併發鏈接數
    user        haproxy                           #運行haproxy的用戶
    group       haproxy                           #運行haproxy的組
    daemon                                        #後臺運行
    # turn on stats unix socket
    stats socket /var/lib/haproxy/stats
#---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block
#---------------------------------------------------------------------
defaults
    mode                    http                   #工做模式
    log                     global                 #使用全局日誌
    option                  httplog
    option                  dontlognull
    option http-server-close                       #容許客戶端關閉鏈接
    option forwardfor       except 127.0.0.0/8
    option                  redispatch             #某上游服務器故障,從新將發往該服務器的請求發往其餘的server。
    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                      
?#---------------------------------------------------------------------
# main frontend which proxys to the backends
#---------------------------------------------------------------------
frontend  service 192.168.1.200:80
    option httpclose                               #容許服務器端被動關閉鏈接
    option logasap
    capture request  header Host len 20
    capture request  header Referer len 60
	
	#定義ACL,如下兩個ACL是獲取靜態請求
    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      #將靜態請求定向至static
    default_backend             app                #非靜態請求定向至app
    option forwardfor header X-Client              #添加內容爲客戶端IP的首部

#---------------------------------------------------------------------
# static backend for serving up p_w_picpaths, stylesheets and such
#---------------------------------------------------------------------
backend static
    balance     roundrobin
    server      first 192.168.2.7:80 check port 80 maxconn 3000
    server      second 192.168.2.18:80 check port 80 maxconn 3000
#---------------------------------------------------------------------
# round robin balancing between the various backends
#---------------------------------------------------------------------
backend app
    balance     roundrobin
    option forwardfor header X-Client
    server      app1 192.168.2.17:80 check port 80 maxconn 3000
    server      app2 192.168.2.16:80 check port 80 maxconn 3000
    server      app3 127.0.0.1:8080 backup


配置keepalived:

haproxy1上:

[root@node1 ~]# vim /etc/keepalived/keepalived.conf
vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1234
    }
    virtual_ipaddress {
        192.168.1.200
    }
    notify_master "/etc/init.d/haproxy start"       #提高爲主節點時,啓動haproxy服務
    notify_backup "/etc/init.d/haproxy stop"        #降級爲備節點時,關閉haproxy服務
    notify_fault "/etc/init.d/haproxy stop"         #運行出錯時,關閉haproxy服務
}

haproxy2上(省略部分與haproxy1上一致):

vrrp_instance VI_1 {
    state BACKUP              #備用節點             
......
    priority 99               #服務器優先級
.......
}

配置完成後在啓動各節點上的服務:

[root@www ~]# ansible haproxy -m shell -a 'service haproxy start'
[root@www ~]# ansible haproxy -m shell -a 'service keepalived start'
[root@www ~]# ansible webstatic -m shell -a 'service nginx start'
[root@www ~]# ansible webdynamic -m shell -a 'service httpd start'

wKioL1XhCSehcjksAAGW_mlc8ms089.jpg

能夠看到主節點上的虛擬IP已啓用。在各個web節點上準備測試頁面。

dynamic server1和server2上:

####server1#####
[root@node1 ~]# vim /var/www/html/index.php 
<h1>dynamic server1</h1>
<?php
 phpinfo();
?>

####server2#####
[root@node2 ~]# vim /var/www/html/index.php 
<h1>dynamic server2</h1>
<?php
 phpinfo();
?>

static server1和server2上:

####server1#####
[root@node1 web]# vim p_w_picpaths/abc.html 
<h1>static node1</h1>

####server2#####
[root@node2 web]# vim p_w_picpaths/abc.html 
<h1>static node2</h1>


進行訪問測試:

訪問靜態內容:

wKioL1XhCjaw0SccAACq0MKz8L8090.jpg


wKiom1XhCEPx27KiAACm03_PZrk777.jpg

訪問動態內容:

wKioL1XhCxrTmIyoAAC5WzGR4TM848.jpg


wKiom1XhCP_wm_o1AAC7CKeJaCo579.jpg

這裏已經對單節點haproxy作了高可用,當主節點故障時,服務可以自動切換至備節點而不中斷訪問。完成部署!.................^_^

相關文章
相關標籤/搜索