Haproxy+Keepalived負載均衡


Haproxy介紹

HAProxy是一個特別適用於高可用性環境的TCP/HTTP開源的反向代理和負載均衡軟件。在7層負載均衡方面的功能很強大(支持cookie track, header rewrite等等),支持雙機熱備,支持虛擬主機,支持健康檢查,同時還提供直觀的監控頁面,可以清晰實時的監控服務集群的運行狀況。同時支持Linux 2.6內核中System Epoll,通過簡化系統調用,大幅的提高了網絡I/O性能。

Haproxy包括以下一些特征:

  • 根據靜態分配的cookie 分配HTTP請求
  • 分配負載到各個服務器,同時保證服務器通過使用HTTP Cookie實現連接保持;
  • 當主服務器宕機時切換到備份服務器;允許特殊端口的服務監控;
  • 做維護時通過熱配置可以保證業務的連續性,更加人性化;
  • 添加/修改/刪除HTTP Request和Response 頭;
  • 通過特定表達式Block HTTP請求;
  • 根據應用的cookie做連接保持;
  • 帶有用戶驗證的詳細的HTML監控報告.

Haproxy支持的平台

HAProxy is known to reliably run on the following OS/Platforms :
Linux 2.4 on x86, x86_64, Alpha, Sparc, MIPS, PARISC 
Linux 2.6 / 3.x on x86, x86_64, ARM, Sparc, PPC64 
Solaris 8/9 on UltraSPARC 2 and 3 
Solaris 10 on Opteron and UltraSPARC 
FreeBSD 4.10 - 10 on x86 
OpenBSD 3.1 to -current on i386, amd64, macppc, alpha, sparc64 and VAX (check the ports) 
AIX 5.1 - 5.3 on Power™ architecture 

HAProxy負載均衡算法

HAProxy的負載均衡算法現在具體有如下8種:

  • roundrobin,表示簡單的輪詢,這個不多說,這個是負載均衡基本都具備的;
  • static-rr,表示根據權重,建議關注;
  • leastconn,表示最少連接者先處理,建議關注;
  • source,表示根據請求源IP,這個跟NginxIP_hash機制類似,我們用其作為解決session問題的一種方法,建議關注;
  • ri,表示根據請求的URI;
  • rl_param,表示根據請求的URl參數’balance url_param’ requires an URL parameter name;
  • hdr(name),表示根據HTTP請求頭來鎖定每一次HTTP請求;
  • rdp-cookie(name),表示根據據cookie(name)來鎖定並哈希每一次TCP請求。

Haproxy部署

Haproxy源碼編譯安裝

安裝依賴軟件包

[root@linux-node1 ~]# yum install -y net-tools vim lrzsz tree screen lsof tcpdump nc mtr nmap gcc glib gcc-c++ make
[root@linux-node1 ~]# cd /usr/local/src
[root@linux-node1 src]# wget http://www.haproxy.org/download/1.6/src/haproxy-1.6.3.tar.gz
[root@linux-node1 src]# tar zxf haproxy-1.6.3.tar.gz 

編譯安裝Haproxy

[root@linux-node1 src]# cd haproxy-1.6.3
[root@linux-node1 src]# make TARGET=linux2628 PREFIX=/usr/local/haproxy-1.6.3
[root@linux-node1 src]# make install
[root@linux-node1 ~]# cp /usr/local/sbin/haproxy /usr/sbin/
[root@linux-node1 ~]# haproxy -v
HA-Proxy version 1.6.3 2015/12/25
Copyright 2000-2015 Willy Tarreau <willy@haproxy.org>

Haproxy啟動腳本

[root@linux-node1 ~]# cd /usr/local/src/haproxy-1.6.3
[root@linux-node1 haproxy-1.6.3]# cp examples/haproxy.init /etc/init.d/haproxy
[root@linux-node1 haproxy-1.6.3]# chmod 755 /etc/init.d/haproxy 

Haproxy配置文件

[root@linux-node1 ~]# useradd -r haproxy
[root@linux-node1 ~]# mkdir /etc/haproxy
[root@linux-node1 ~]# mkdir /var/lib/haproxy
[root@linux-node1 ~]# mkdir /var/run/haproxy
[root@linux-node1 ~]# vim /etc/haproxy/haproxy.cfg
global
   log 127.0.0.1 local3 info
   chroot /var/lib/haproxy
   user haproxy
   group haproxy
   daemon

defaults
   log global
   mode http
   option httplog
   option dontlognull
   timeout connect 5000
   timeout client 50000
   timeout server 50000

frontend http_front
   bind *:80
   stats uri /haproxy?stats
   default_backend http_back

backend http_back
   balance roundrobin
   server linux-node1 192.168.56.11:8080 check
   server linux-node2 192.168.56.12:8080 check

#設置可以監聽非本地IP

net.ipv4.ip_nonlocal_bind:
  sysctl.present: 
- value: 1

haproxy日志設置

[root@saltstack-node1 ~]# vim /etc/rsyslog.conf
#rsyslog 默認情況下,需要在514端口監聽UDP,所以可以把/etc/rsyslog.conf如下的注釋去掉
# Provides UDP syslog reception 
$ModLoad imudp 
$UDPServerRun 514
local3.*         /var/log/haproxy.log
[root@saltstack-node1 ~]# vim /etc/sysconfig/rsyslog
[root@linux-node1 ~]# systemctl restart rsyslog

Haproxy配置

配置案例

global
maxconn 100000
chroot /usr/local/haproxy
uid 99  
gid 99 
daemon
nbproc 1 
pidfile /usr/local/haproxy/logs/haproxy.pid 
log 127.0.0.1 local3 info

defaults
option http-keep-alive
maxconn 100000
mode http
timeout connect 5000ms
timeout client  50000ms
timeout server 50000ms

listen stats
mode http
bind 0.0.0.0:8888
stats enable
stats uri     /haproxy-status 
stats auth    haproxy:saltstack

frontend frontend_www_example_com
bind 192.168.56.21:80
mode http
option httplog
log global
default_backend backend_www_example_com

backend backend_www_example_com
option forwardfor header X-REAL-IP
option httpchk HEAD / HTTP/1.0
balance source
server web-node1  192.168.56.21:8080 check inter 2000 rise 30 fall 15
server web-node2 192.168.56.22:8080 check inter 2000 rise 30 fall 15

HAProxy的配置過程分為3個主要部分:

  • 命令行參數,這是最優先的
  • global(全局)段,設置進程級參數
  • 代理配置段,通常位於"default", "listen", "fronted", "backend"這樣的形式內。

配置文件的語法是由關鍵字后跟可選的一個或者多個參數(參數之間有空格)組成。如果字符串中包含空格,必須使用''進行轉義。\本身需要使用\進行轉義。
一些參數值為時間,比如說timeout。時間值通常單位為毫秒(ms),但是也可以通過加后綴來使用其他的單位,支持的單位為:

  - us : microseconds. 1 microsecond = 1/1000000 second
  - ms : milliseconds. 1 millisecond = 1/1000 second. This is the default.
  - s  : seconds. 1s = 1000ms
  - m  : minutes. 1m = 60s = 60000ms
  - h  : hours.   1h = 60m = 3600s = 3600000ms
  - d  : days.    1d = 24h = 1440m = 86400s = 86400000ms

HAProxy配置中分五大部分:

  • global:
    全局配置參數,進程級的,用來控制Haproxy啟動前的一些進程及系統設置。
  • defaults:
    配置一些默認的參數,可以被frontend,backend,listen段繼承使用。
  • frontend:
    用來匹配接收客戶所請求的域名,uri等,並針對不同的匹配,做不同的請求處理
  • backend:
    定義后端服務器集群,以及對后端服務器的一些權重、隊列、連接數等選項的設置,我將其理解為Nginx中的upstream塊。
  • listen:
    理解為frontend和backend的組合體。

HAProxy配置文件的配置方法主要用兩種:一種是由前端(frontend)和后端(backend)配置塊組成,前端和后端都可以有多個。第二種方法是只有一個listen配置快塊來同時實現前端和后端。我們這里主要介紹最常用的frontend和backend工作模式,這個也是推薦的配置方法。
同時前端(frontend)區域可以根據HTTP請求的header信息來定義一些規則,然后將符合某規則的請求轉發到相應后端(backend)進行處理,這個我們后面會詳細講解。

Global配置
global   # 全局參數的設置
log 127.0.0.1 local0 info
     # log語法:log [max_level_1]
     # 全局的日志配置,使用log關鍵字,指定使用127.0.0.1上的syslog服務中的local0日志設備,記錄日志等級為info的日志
maxconn 4096
     # 定義每個haproxy進程的最大連接數,由於每個連接包括一個客戶端和一個服務器端,所以單個進程的TCP會話最大數目將是該值的兩倍。
user haproxy
group haproxy
     # 設置運行haproxy的用戶和組,也可使用uid,gid關鍵字替代之
daemon
     # 以守護進程的方式運行
nbproc 16
     # 設置haproxy啟動時的進程數,根據官方文檔的解釋,我將其理解為:該值的設置應該和服務器的CPU核心數一致,即常見的2顆8核心CPU的服務器,即共有16核心,則可以將其值設置為:<=16 ,創建多個進程數,可以減少每個進程的任務隊列,但是過多的進程數也可能會導致進程的崩潰。這里我設置為16
maxconn 4096
     # 定義每個haproxy進程的最大連接數,由於每個連接包括一個客戶端和一個服務器端,所以單個進程的TCP會話最大數目將是該值的兩倍。
     #ulimit -n 65536
     # 設置最大打開的文件描述符數,在1.4的官方文檔中提示,該值會自動計算,所以不建議進行設置
     pidfile /var/run/haproxy.pid# 定義haproxy的pid
代理(Proxies)相關配置

使用Haproxy進行反向代理負載均衡,最常修改的部分就是代理相關的配置了,代理相關配置位於下列配置段中:

-	defaults <name>
-	frontend<name>
-	backend  <name>
-	listen   <name>
  • "defaults"段為其后的所有其他配置段設置默認參數。 "defaults"段可以有多個,后設置的總是會覆蓋之前的配置。查看下面的列表可以知道"defaults"段可以使用哪些配置參數。"defaults"關鍵字是可選的,但是為了更好的可讀性,建議加上。

  • "frontend"段描述了一組監聽的套接字,它們接受客戶端連接。

  • "backend"段描述了一組服務器,代理(Haproxy)會連接這些服務器並轉發客戶端請求到這些服
    務器上。

  • "listen"段定義了一個完整的代理,它的前段(frontend)和后端(frontend)都在這個配置
    段里。這種配置通常用於僅TCP的流量.代理名必須由大(小)寫字母、數字、'-'、'_'、'.'、':'組成。ACL名字是大小寫敏感的,
    也即www和WWW分別指不同的代理。由於歷史原因,所有的代理名字是可以重疊的,這種僅僅會導致日志有些問題。后來內容交換
    (Content Switching)的加入使得兩個有重復功能的代理(frontend/backend)必須使用不
    同的名字。然而,仍然允許frontend和backend使用同一個名字,因為這種配置會經常遇到。

當前,HAProxy支持兩種主要的代理模式: "tcp"也即4層,和"http",即7層。在4層模式下,
HAproxy僅在客戶端和服務器之間轉發雙向流量。7層模式下,HAProxy會分析協議,並且能通過
允許、拒絕、交換、增加、修改或者刪除請求(request)或者回應(response)里指定內容來控制
協議,這種操作要基於特定規則。

Defaults配置
defaults	# 默認部分的定義
mode http
     # mode語法:mode {http|tcp|health} 。http是七層模式,tcp是四層模式,health是健康檢測,返回OK
log 127.0.0.1 local3 err
     # 使用127.0.0.1上的syslog服務的local3設備記錄錯誤信息
retries 3
     # 定義連接后端服務器的失敗重連次數,連接失敗次數超過此值后將會將對應后端服務器標記為不可用
option httplog
     # 啟用日志記錄HTTP請求,默認haproxy日志記錄是不記錄HTTP請求的,只記錄“時間[Jan 5 13:23:46] 日志服務器[127.0.0.1] 實例名已經pid[haproxy[25218]] 信息[Proxy http_80_in stopped.]”,日志格式很簡單。
option redispatch
     # 當使用了cookie時,haproxy將會將其請求的后端服務器的serverID插入到cookie中,以保證會話的SESSION持久性;而此時,如果后端的服務器宕掉了,但是客戶端的cookie是不會刷新的,如果設置此參數,將會將客戶的請求強制定向到另外一個后端server上,以保證服務的正常。
option abortonclose
     # 當服務器負載很高的時候,自動結束掉當前隊列處理比較久的鏈接
option dontlognull
     # 啟用該項,日志中將不會記錄空連接。所謂空連接就是在上游的負載均衡器或者監控系統為了探測該服務是否存活可用時,需要定期的連接或者獲取某一固定的組件或頁面,或者探測掃描端口是否在監聽或開放等動作被稱為空連接;官方文檔中標注,如果該服務上游沒有其他的負載均衡器的話,建議不要使用該參數,因為互聯網上的惡意掃描或其他動作就不會被記錄下來
option httpclose
     # 這個參數我是這樣理解的:使用該參數,每處理完一個request時,haproxy都會去檢查http頭中的Connection的值,如果該值不是close,haproxy將會將其刪除,如果該值為空將會添加為:Connection: close。使每個客戶端和服務器端在完成一次傳輸后都會主動關閉TCP連接。與該參數類似的另外一個參數是“option forceclose”,該參數的作用是強制關閉對外的服務通道,因為有的服務器端收到Connection: close時,也不會自動關閉TCP連接,如果客戶端也不關閉,連接就會一直處於打開,直到超時。
contimeout 5000
     # 設置成功連接到一台服務器的最長等待時間,默認單位是毫秒,新版本的haproxy使用timeout connect替代,該參數向后兼容
clitimeout 3000
     # 設置連接客戶端發送數據時的成功連接最長等待時間,默認單位是毫秒,新版本haproxy使用timeout client替代。該參數向后兼容
srvtimeout 3000
     # 設置服務器端回應客戶度數據發送的最長等待時間,默認單位是毫秒,新版本haproxy使用timeout server替代。該參數向后兼容
Listen配置
listen status	# 定義一個名為status的部分
bind 0.0.0.0:1080
     # 定義監聽的套接字
mode http
     # 定義為HTTP模式
log global
     # 繼承global中log的定義
stats refresh 30s
     # stats是haproxy的一個統計頁面的套接字,該參數設置統計頁面的刷新間隔為30s
stats uri /admin?stats
     # 設置統計頁面的uri為/admin?stats
stats realm Private lands
     # 設置統計頁面認證時的提示內容
stats auth admin:password
     # 設置統計頁面認證的用戶和密碼,如果要設置多個,另起一行寫入即可
stats hide-version
     # 隱藏統計頁面上的haproxy版本信息
Frontend配置
frontend http_80_in	# 定義一個名為http_80_in的前端部分
bind 0.0.0.0:80
     # http_80_in定義前端部分監聽的套接字
mode http
     # 定義為HTTP模式
log global
     # 繼承global中log的定義
option forwardfor
     # 啟用X-Forwarded-For,在requests頭部插入客戶端IP發送給后端的server,使后端server獲取到客戶端的真實IP
acl static_down nbsrv(static_server) lt 1
     # 定義一個名叫static_down的acl,當backend static_sever中存活機器數小於1時會被匹配到
     use_backend php_server if static_down
     # 如果滿足策略static_down時,就將請求交予backend php_server
Backend配置
backend php_server	#定義一個名為php_server的后端部分
mode http
     # 設置為http模式
balance source
     # 設置haproxy的調度算法為源地址hash
cookie SERVERID
     # 允許向cookie插入SERVERID,每台服務器的SERVERID可在下面使用cookie關鍵字定義
option httpchk GET /test/index.php
     # 開啟對后端服務器的健康檢測,通過GET /test/index.php來判斷后端服務器的健康情況
server php_server_1 10.12.25.68:80 cookie 1 check inter 2000 rise 3 fall 3 weight 2
server php_server_2 10.12.25.72:80 cookie 2 check inter 2000 rise 3 fall 3 weight 1
server php_server_bak 10.12.25.79:80 cookie 3 check inter 1500 rise 3 fall 3 backup
     # server語法:server [:port] [param*]
     # 使用server關鍵字來設置后端服務器;為后端服務器所設置的內部名稱[php_server_1],該名稱將會呈現在日志或警報中、后端服務器的IP地址,支持端口映射[10.12.25.68:80]、指定該服務器的SERVERID為1[cookie 1]、接受健康監測[check]、監測的間隔時長,單位毫秒[inter 2000]、監測正常多少次后被認為后端服務器是可用的[rise 3]、監測失敗多少次后被認為后端服務器是不可用的[fall 3]、分發的權重[weight 2]、最為備份用的后端服務器,當正常的服務器全部都宕機后,才會啟用備份服務器[backup]

backend static_server
mode http
option httpchk GET /test/index.html
server static_server_1 10.12.25.83:80 cookie 3 check inter 2000 rise 3 fall 3

調試相關配置

  • debug
    啟動debug模式,此模式會dump所有的交互信息到stdout,並運行於前台(譯注:不進入deamon
    模式)。等效於命令行參數-d. 此參數絕不要用於生產環境,因為它會在系統啟動時被掛起.
  • quiet
    在啟動時不顯示任何信息。等於命令行參數-v

Haproxy健康檢查

HAProxy作為Loadbalance,支持對backend的健康檢查,以保證在后端backend不能服務時,把從frotend進來的request分配至可以其它可服務的backend,從而保證整體服務的可用性。

通過監聽端口進行健康檢測

這種檢測方式,haproxy只會去檢查后端server的端口,並不能保證服務的真正可用。

listen http_proxy 0.0.0.0:80 
        mode http 
        cookie SERVERID 
        balance roundrobin 
        option httpchk 
        server web1 192.168.1.1:80 cookie server01 check 
        server web2 192.168.1.2:80 cookie server02 check inter 500 rise 1 fall 2 

通過URI獲取進行健康檢測

這種檢測方式,是用過去GET后端server的的web頁面,基本上可以代表后端服務的可用性。

listen http_proxy 0.0.0.0:80 
        mode http 
        cookie SERVERID 
        balance roundrobin 
        option httpchk GET /index.html 
        server web1 192.168.1.1:80 cookie server01 check 
        server web2 192.168.1.2:80 cookie server02 check inter 500 rise 1 fall 2 
 相關配置
option httpchk <method><uri><version>

啟用七層健康檢測

http-check disable-on-404 
如果backend返回404,則除了長連接之外的后續請求將不被分配至該backend 
http-check send-state 
增加一個header,同步HAProxy中看到的backend狀態。該header為server可見。 X-Haproxy-Server-State: UP 2/3; name=bck/srv2; node=lb1; weight=1/2; scur=13/22; qcur=0 
server option 
check:啟用健康檢測
inter:健康檢測間隔
rise:檢測服務可用的連續次數
fall:檢測服務不可用的連續次數
error-limit:往server寫數據連續失敗的次數上限,執行on-error的設定
observe <mode>:把正常服務過程作為健康檢測請求,即實時檢測
on-error <mode>:滿足error-limit后執行的操作(fastinter、fail-check、sudden-death、mark-down)。其中fastinter表示立即按照fastinter的檢測延時進行。fail-check表示改次error作為一次檢測;sudden-death表示模仿一次fatal,如果緊接着一次fail則置server為down;mark-down表示直接把server置為down狀態。
其它
retries:連接失敗重試的次數,如果重試該次數后還不能正常服務,則斷開連接。

通過request獲取的頭部信息進行匹配進行健康檢測

這種檢測方式,則是基於高級,精細的一些監測需求。通過對后端服務訪問的頭部信息進行匹配檢測。

listen http_proxy 0.0.0.0:80 
        mode http 
        cookie SERVERID 
        balance roundrobin 
        option httpchk HEAD /index.jsp HTTP/1.1\r\nHost:\ www.xxx.com 
        server web1 192.168.1.1:80 cookie server01 check 
        server web2 192.168.1.2:80 cookie server02 check inter 500 rise 1 fall 2 

Haproxy負載均衡算法

HAProxy的算法有如下8種:

roundrobin,表示簡單的輪詢,
static-rr,表示根據權重,建議關注;
leastconn,表示最少連接者先處理,建議關注;
source,表示根據請求源IP,建議關注;
uri,表示根據請求的URI;
url_param,表示根據請求的URl參數'balance url_param' requires an URL parameter name
hdr(name),表示根據HTTP請求頭來鎖定每一次HTTP請求;
rdp-cookie(name),表示根據據cookie(name)來鎖定並哈希每一次TCP請求。
調度算法source

haroxy 將用戶IP經過hash計算后 指定到固定的真實服務器上(類似於nginx 的IP hash 指令)
配置指令 balance source

haproxy 將WEB服務端發送給客戶端的cookie中插入(或添加加前綴)haproxy定義的后端的服務器COOKIE ID。
配置指令例舉 cookie SESSION_COOKIE insert indirect nocache

session 識別

haproxy 將后端服務器產生的session和后端服務器標識存在haproxy中的一張表里。客戶端請求時先查詢這張表。然后根據session分配后端server。
配置指令:appsession<cookie> len <length> timeout <holdtime>

Haproxy 七層負載均衡
reqirep ^Host:\\ www.abc.com Host:\\ abc.com
acl host_abc_com hdr(host)      -i abc.com
acl host_cn      hdr_end(host)  -i .cn
acl host_xyz     hdr_beg(host)  -i xzy.
acl url_xxx      url_reg        -i ^/xxx
use_backend host-abc-com if host_abc_com 
use_backend host-cn      if host_cn
use_backend host-xyz-url-xxx if host_xyz url_xxx
default_backend default-servers
根據URL后綴進行負載均衡
acl php_web url_reg /*.php$
#acl php_web path_end .php # 定義一個名叫php_web的acl,當請求的url末尾是以.php結尾的,將會被匹配到,上面兩種寫法任選其一

acl static_web url_reg /*.(css|jpg|png|jpeg|js|gif)$
#acl static_web path_end .gif .png .jpg .css .js .jpeg

# 定義一個名叫static_web的acl,當請求的url末尾是以.css、.jpg、.png、.jpeg、.js、.gif結尾的,將會被匹配到,上面兩種寫法任選其一

use_backend php_server if php_web
# 如果滿足策略php_web時,就將請求交予backend php_server
use_backend static_server if static_web
# 如果滿足策略static_web時,就將請求交予backend static_server
根據url進行負載均衡
acl invitec url_reg /invitec_pk.do
use_backend b_yxpopo_com_pk if invitec
根據User-Agent實現域名跳轉

需求如下:

Haproxy主要配置如下:

acl static_d path_beg /static /small /big  #匹配XX開始的
acl index_page path_reg ^/$  #匹配首頁
acl ua hdr_reg(User-Agent) -i iphone android #匹配User-Agent類型
acl club hdr_reg(host) -i   club.jesse.com #匹配訪問的域名
redirect prefix http://3g.club.jesse.com if ua static_d club #匹配相關的ACL策略就進行跳轉
redirect prefix http://3g.club.jesse.com if index_page ua club
use_backend club_pool if club

Haproxy TCP端口耗盡解決方案

在實際使用過程中,有兩個問題比較容易發生:

  1. TCP端口耗盡
  2. 網卡帶寬跑滿
    本文重點講講如何優化問題1,問題2暫不討論。

優化一:使用盡可能多的端口

Linux系統默認提供了65K個端口,每當Haproxy建立了一個到MySQL的連接,就會消耗一個端口;當Haproxy斷開和MySQL的連接時,該端口並不會立即釋放,而是會處於TIME_WAIT狀態(2*MSL),超時后才會釋放此端口供新的連接使用。
我的環境中,tcp_fin_timeout為15秒,也就是說如果我環境中的haproxy可以承載的最大並發連接數為64K/(15*2)=2.1K,可實際上達不到這個上限,原因如下:
net.ipv4.ip_local_port_range = 15000 65000
linux會保留一段端口,實際能參與分配的端口數只有50K,為了獲得盡可能多的可分配端口,做如下調整:

# sysctl net.ipv4.ip_local_port_range="1025 65000"
# sysctl net.ipv4.ip_local_port_range="1025 65000"

#記得修改/etc/sysctl.conf中對應的內容

優化二:復用處於TIME_WAIT的端口

調整兩個參數:

net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1 

第一個參數很安全,可以不用過多關注。需要注意的是第二個參數,某些情況下會導致數據包被丟棄。
例如:client通過NAT連接haproxy,並且haproxy端打開了tcp_tw_recycle,同時saw_tstamp也沒有關閉,當第一個連接建立並關閉后,此端口(句柄)處於TIME_WAIT狀態,在2*MSL時間內又一個client(相同IP,如果打開了xfrm還要相同PORT)發一個syn包,此時linux內核就會認為這個數據包異常,從而丟掉這個包,並發送rst包.
不過通常情況下,client都是通過內網直接連接haproxy,所以可以認為tcp_tw_recycle是安全的,只是需要記住此坑。

優化三:縮短TIME_WAIT時間

Linux系統默認MSL為60秒,也就是正常情況下,120秒后處於TIME_WAIT的端口(句柄)才會釋放,可以將MSL的時間縮小,縮短端口的釋放周期。

# cat /proc/sys/net/ipv4/tcp_fin_timeout
60
# echo 15 > /proc/sys/net/ipv4/tcp_fin_timeout
#這是一個折中的數值,太小也會導致其它問題

優化四:使用多IP

如優化一中所說,我們已經盡可能多的使用了系統提供的端口范圍。但最多依然不超過65K。
Haproxy提供了內建的端口管理方法,可以充分利用以擴大我們的端口范圍。

server mysql0     10.0.3.1:3306 check source 10.0.3.100:1025-65000
server mysql1     10.0.3.1:3306 check source 10.0.3.101:1025-65000

如果使用兩個ip,我們可用的端口數就接近130K。擴展多個IP,就可以不斷增加端口數。

優化五:使用長連接

服務最好使用長連接,一是避免頻繁的申請連接,導致端口耗盡;二是避免創建連接帶來的時間消耗。

Haproxy 在線維護

Haproxy Sock

開啟Haproxy Unix Socket
在global添加:

	stats socket /usr/local/haproxy/haproxy.sock mode 600 level admin
	stats timeout 2m

Socat 工具

socat是一個多功能的網絡工具,名字來由是“Socket CAT”,可以看作是netcat的N倍加強版,socat的官方網站:http://www.dest-unreach.org/socat/
socat是一個兩個獨立數據通道之間的雙向數據傳輸的繼電器。這些數據通道包含文件、管道、設備(終端或調制解調器等)、插座(Unix,IP4,IP6 - raw,UDP,TCP)、SSL、SOCKS4客戶端或代理CONNECT。
socat支持廣播和多播、抽象Unix sockets、Linux tun/tap、GNU readline和PTY。它提供了分叉、記錄和進程間通信的不同模式。多個選項可用於調整socat和其渠道,Socat可以作為TCP中繼(一次性或守護進程),作為一個守護進程基於socksifier,作為一個shell Unix套接字接口,作為IP6的繼電器,或面向TCP的程序重定向到一個串行線。

socat的主要特點就是在兩個數據流之間建立通道;且支持眾多協議和鏈接方式:ip, tcp, udp, ipv6, pipe,exec,system,open,proxy,openssl,socket等。

使用socat可以查看和設置HAProxy狀態,首先得讓HAProxy產生出一個sock出來(hatop ,socat都是基於這個的,沒這個什么都做不了)。

[root@lb-node3 ~]#yum install –y readline-devel openssl-devel tcp_wrappers
[root@lb-node3 ~]# cd /usr/local/src
[root@lb-node3 src]# wgethttp://www.dest-unreach.org/socat/download/socat-1.7.2.4.tar.gz
[root@lb-node3 src]# tar zxf socat-1.7.2.4.tar.gz 
[root@lb-node3 src]# cd socat-1.7.2.4
[root@lb-node3 socat-1.7.2.4]# ./configure&& make && make install

常用功能

獲取幫助:


echo "help"| socat stdio /usr/local/haproxy/haproxy.sock
Unknown command. Please enter one of the following commands only :
clear counters : clear max statistics counters (add 'all' for all counters)
clear table    : remove an entry from a table
help           : this message
prompt         : toggle interactive mode with prompt
quit           : disconnect
show info      : report information about the running process
show pools     : report information about the memory pools usage
show stat      : report counters for each proxy and server
show errors    : report last request and response errors for each proxy
show sess [id] : report the list of current sessions or dump this session
show table [id]: report table usage stats or dump this table's contents
get weight     : report a server's current weight
set weight     : change a server's weight
set server     : change a server's state or weight
set table [id] : update or create a table entry's data
set timeout    : change a timeout setting
set maxconn    : change a maxconn setting
set rate-limit : change a rate limiting value
disable        : put a server or frontend in maintenance mode
enable         : re-enable a server or frontend which is in maintenance mode
shutdown       : kill a session or a frontend (eg:to release listening ports)
show acl [id]  : report avalaible acls or dump an acl's contents
get acl        : reports the patterns matching a sample for an ACL
add acl        : add acl entry
del acl        : delete acl entry
clear acl <id> : clear the content of this acl
show map [id]  : report avalaible maps or dump a map's contents
get map        : reports the keys and values matching a sample for a map
set map        : modify map entry
add map        : add map entry
del map        : delete map entry
clear map <id> : clear the content of this map
set ssl <stmt> : set statement for ssl
#查看狀態:
echo "show info;show stat" | socat /usr/local/haproxy/haproxy.sock stdio
#關閉節點:
echo "disable server b_yxpopo_com/hongbao-node11" | socat /usr/local/haproxy/haproxy.sock stdio
#啟用節點:
echo "enable server b_yxpopo_com/hongbao-node11" | socat /usr/local/haproxy/haproxy.sock stdio

Haproxy+keepalived架構實踐

VRRP介紹

  • VRRP中的角色
  • VRRP路由器
    VRRP路由器就是一台路由器,只不過上面運行了VRRP協議的程序,比如我們等下要安裝的Keepalived就是運行了VRRPD這樣的程序來實現VRRP協議,我們可以理解為一台物理路由器,需要注意的是一台VRRP路由器可以位於多個虛擬路由器。
    VRRP虛擬路由器
    VRRP虛擬路由器通常有多台物理的VRRP路由器組成,這多台物理路由器組成一個Pool,虛擬路由器在生產環境中可以有多個,通過VRID進行標示。
    MASTER和BACKUP
    在一個VRRP虛擬路由器中,有多台物理的VRRP路由器,但是這多台路由器並不同時工作,而是由一台稱之為MASTER的負責路由工作,其它的都是BACKUP。MASTER並不是一成不變的,VRRP協議讓每個VRRP路由器參與競選,競選成功的就可以成為MASTER。MASTER擁有虛擬路由器的IP地址,我們把這個IP地址稱之為VIP,MASTER負責轉發發送給網關地址的數據包和響應ARP請求。
    VRRP是如何工作的?
    VRRP通過競選協議來實現虛擬路由器的功能,協議報文通過IP多播(多播地址:224.0.0.18)方式進行發送。虛擬路由器有VRID(范圍0-255)和一組IP地址組成,對外表現為一個MAC地址:00-00-5E-00-01-{VRID}。所以,在一個虛擬路由器中,不管誰是Master,對外都是相同的MAC地址和IP地址。如果其中一台虛擬路由器Down機,角色發送切換,那么客戶端並不需要因為Master的變化修改自己的路由設置,可以做到透明的切換。這樣就實現了如果一台機器宕機,那么備用的機器會擁有MASTER上的IP地址,實現高可用功能。
    VRRP是如何通信的?
    在一個虛擬路由器中,只有作為MASTER的VRRP路由器會一直發送VRRP廣播包,BACKUP的路由器會被動接收數據庫,不會搶占MASTER。當MASTER不可用時,這個時候BACKUP就收不到廣播包,多台BACKUP中優先級最高的這台會搶占成為MASTER。這個搶占的速度非常快小於1s,幾乎不會影響生產應用。為了安全考慮VRRP的數據包使用了加密協議進行加密。

Keepalived部署

[root@linux-node1 ~]# cd /usr/local/src
[root@linux-node1 src]# wget http://www.keepalived.org/software/keepalived-1.2.19.tar.gz
[root@linux-node1 src]# tar zxf keepalived-1.2.19.tar.gz 
[root@linux-node1 src]# cd keepalived-1.2.19
[root@linux-node1 keepalived-1.2.19]# ./configure --prefix=/usr/local/keepalived-1.2.19
[root@linux-node1 keepalived-1.2.19]# make && make install
[root@linux-node1 keepalived-1.2.19]# cp keepalived/etc/init.d/keepalived.init /etc/init.d/keepalived
[root@linux-node1 keepalived-1.2.19]# chmod +x /etc/init.d/keepalived
[root@linux-node1 keepalived-1.2.19]# cp keepalived/etc/init.d/keepalived.sysconfig /etc/sysconfig/keepalived
[root@linux-node1 keepalived-1.2.19]# cp keepalived/etc/keepalived/keepalived.conf /etc

Keepalived配置詳解

Keepalived的所有配置都在一個配置文件里面,主要分為三大類:

  1. 全局配置
  2. VRRPD配置
  3. LVS配置
    配置文件是以配置塊的形式存在,每個配置塊都在一個閉合的{}范圍內,所有編輯的時候注意大括號的閉合問題。#和!開頭的都是注釋。
    2.3.1 全局配置
    全局配置是對整個Keepalived生效的配置,一個典型的配置如下:
global_defs {
#設置keepalived再發生事件(比如切換)的時候,需要發送到的email地址,可以設置多個,每行一個。
   notification_email {
     shundong.zhao@dianjoy.com
   }
#設置通知郵件發送來自於哪里
   notification_email_from keepalived@dianjoy.com
#指定發送郵件的smtp服務器  
 smtp_server 127.0.0.1
#設置smtp連接超時事件,單位是秒
   smtp_connect_timeout 30
#設置route_id,是運行keepalived的一個標示,多個集群設置為不同的。
   router_id nginx_ha
}

VRRPD配置

VRRPD的配置是Keepalived比較重要的配置,主要分為兩個部分VRR同步組合VRRP實例,我們先說VRRP實例,也就是要想使用VRRP進行高可用選舉,那么就一定需要配置一個VRRP實例,在實例中來定義VIP、服務器角色等。

vrrp_instance NGINX_HA {
    #指定實例初始狀態,實際的MASTER和BACKUP是選舉決定的
    state MASTER
#指定實例綁定的網卡
    interface eth0
#設置VRID標記,多個集群不同重復(0..255)
    virtual_router_id 51
#設置優先級,優先級高的會被競選為Master,Master要高於BACKUP至少50
    priority 150
#檢查的時間間隔,默認是1s。
    advert_int 1
#設置驗證的類型和密碼。
    authentication {
        auth_type PASS
        auth_pass nginx
    }
#設置VIP,可以設置多個,用於切換時的地址綁定。
    virtual_ipaddress {
        192.168.99.176
        192.168.99.170
    }
}

可選的選項:

設置路由,可以設置多條,用於切換時執行。

virtual_routes{
#src <IPADDR> to <IPADDR>/<MASK> via | gw <IPADDR> dev <STRING> scope <SCOPE>
}
#track_interface 設置額外的監控網卡,如果任何一個出現故障,就會進入FAULT狀態
#mcast_src_ip 設置發送多播的地址,默認是綁定的網卡的primary IP

配置案例

! Configuration File for keepalived

global_defs {

notification_email {

saltstack@example.com

}

notification_email_from keepalived@example.com

smtp_server 127.0.0.1

smtp_connect_timeout 30

router_id  150

}



vrrp_instance haproxy_ha {

state Master

interface eth0

virtual_router_id 36

priority 100

advert_int 1

authentication {

auth_type PASS

auth_pass 1111

}

virtual_ipaddress {

192.168.56.20

}

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM