Linux Nginx LVS HAproxy 负载均衡功能对比

Nginx:

  1. 工作在网络7层,可以针对http应用做一些分流的策略,比如针对域名,目录结构
  2. Nginx对网络的依赖较小,理论上能ping通就能进行敷在功能
  3. Nginx安装配置比较简单,测试起来很方便
  4. 也可以承担较高的负载压力且稳定,Nginx是为了解决c10k问题而诞生的
  5. 对后端服务器的健康检查,只支持通过端口来检测,不支持通过url来检测
  6. Nginx对请求的异步处理可以帮助节点服务器减轻负载压力
  7. Nginx仅能支持http、https和Email协议,这样就在适用范围较小
  8. 不支持Session的直接保持,但能通过ip_hash来解决,对Bigrequestheader的支持不是很好
  9. Nginx还能做Web服务器即Cache功能。

LVS:

  1. 抗负载能力强,性能高,能达到F5的60%,对内存和cpu资源消耗比较低
  2. 工作在网络4层,通过VRRP协议(仅做代理使用),具体的流量是由liunx内核来处理,因此没有流量的产生。
  3. 稳定,可靠性强,自身有完美的热备方案(Keepalived+LVS)
  4. 不支持正则处理,不能做动静分离
  5. 支持多种负载均衡算法:rr(轮询),wrr(带权轮询)、lc(最小连接)、wlc(带权最小连接)
  6. 配置相对复杂,对网络依赖比较大,稳定性很高。

LVS工作模式有4种:

  • nat地址转换
  • dr直接路由
  • tun隧道
  • full-nat

HAproxy:

  1. 支持两种代理模式:TCP(四层)和HTTP(七层),支持虚拟主机
  2. 能够补充Nginx的一些缺点比如Session的保持,Cookie引导等工作
  3. 支持url检测后端的服务器出问题的检测会有很好的帮助。
  4. 更多负载均衡策略比如:动态加权轮循,加权源地址哈希,加权URL哈希加权等参数哈希已经实现。
  5. 单纯从效率上来讲HAproxy更会比Nginx有更出色的负载均衡
  6. HAproxy可以对MYsql进行负载均衡,对后端的DB节点进行检测和负载均衡
  7. 支持负载均衡算法:轮循、带权轮循、源地址保持、请求URL、根据Cookie
  8. 不能做Web服务器即Cache。

三大主流软件负载均衡器适用的生产场景:

  1. 网站建设初期,可以选用Nginx、HAproxy作为反向代理负载均衡(流量不大时可以选择不用负载均衡)因为其配置简单,性能也能满足一般业务场景。如果考虑到负载均衡器是有单点失败问题,可以采用Nginx+Keepalived避免负载均衡器自身单点问题。
  2. 网站并发达到一定程度后,为了提高稳定性和转发效率,可以使用LVS,毕竟LVS比Nginx/HAproxy要更稳定,转发效率也高。

RabbitMq 基于 keepalived+haproxy实现高可用

1、概述

rabbitmq作为消息队列,广泛用于生产环境,但是,如果单节点,将导致故障后,生产环境不可用,因此,需要部署高可用环境
本文将介绍基于keepalived+haproxy实现rabbitmq的高可用
rabbitmq的集群中,所有节点都可读写,因此,可用haproxy调度到后端的任意一台rabbitmq上。

环境准备
三个节点mq-01 mq-02 mq-03 ,这里服务器复用了redis的服务器节点,所以机器名忽略。

添加hosts文件
#这一步很关键,所有的节点都要配置一样,否则mq启动会超时,集群功能也不会成功

vim /etc/hosts
192.168.70.32 mq-01
192.168.70.33 mq-02
192.168.70.34 mq-03

另外两台主机用于安装keepalived+haproxy
ip:
192.168.70.35
192.168.70.36
vip:192.168.70.37

2、编译安装erlang

服务包:otp_src_20.2.tar.gz
编译步骤如下

yum -y install make cmake gcc gcc-c++ bison bison-devel ncurses ncurses-devel openssl-devel
tar xf otp_src_20.2.tar.gz  -C /app
cd /app/otp_src_20.2/
./configure --prefix=/app/erlang && make && make install

#测试erlang是否安装成功

cd /app/erlang/bin/
./erl

3、编译安装rabbitmq

服务包:rabbitmq-server-generic-unix-3.7.4.tar.xz

tar xf rabbitmq-server-generic-unix-3.7.4.tar.xz -C /app
mv /app/rabbitmq_server-3.7.4/ /app/rabbitmq
vim /etc/profile
export PATH=$PATH:/app/erlang/bin:/app/rabbitmq/sbin
source /etc/profile

前台启动,测试启动服务是否报错

./rabbitmq/sbin/rabbitmq-server #前台模式(默认)

后台启动,建议运行服务的方式

/app/rabbitmq/sbin/rabbitmq-server -detached #以后台模式启动(建议),尤其是使用web图形界面时
/app/rabbitmq/sbin/rabbitmq-plugins enable rabbitmq_management #建议安装web图形化管理工具,如不需要 可以不装,15672为rabbitmq服务的图形管理端口
#创建桌面端登陆账号

rabbitmqctl add_vhost vh
rabbitmqctl add_user root hns..2018
rabbitmqctl set_user_tags root management
rabbitmqctl set_permissions -p vh root ".*" ".*" ".*"

#访问
http://192.168.70.32:15672/
#如果启动不起来 可能是系统自带的erl版本问题 删除/usr/bin/erl 然后source PATH文件即可

4、配置高可用

把节点redis-01的.erlang.cookie权限设置为777,并且拷贝到其他两个节点,同时,权限也都要设置为777.erlang.cookie的路径可能不一样,用find命令查找出来

redis-01执行如下命令

chmod 777 /root/.erlang.cookie
删掉02和03的.erlang.cookie
/root/.erlang.cookie

在01上执行

scp /root/.erlang.cookie 192.168.70.33:/root
scp /root/.erlang.cookie 192.168.70.34:/root

拷贝完成后,01,02和03执行如下,恢复原来的权限

chmod 400 /root/.erlang.cookie

确认三台机器的.erlang.cookie值一样

cat /root/.erlang.cookie

启动三个mq节点

rabbitmq-server -detached

停止02和03两个节点app

rabbitmqctl stop_app

在02 和 03上分别执行如下命令

rabbitmqctl join_cluster rabbit@redis-01
rabbitmqctl start_app

此时,如果没有报错,三个节点的mq已经组成rabbit集群
用如下命令进行查看集群状态

rabbitmqctl cluster_status

随便停止某一台rabbitmq,数据都可以从其他两台读取
到这里,rabbitmq集群已经完成,还需配置haproxy+keepalived来实现高可用,只用一个vip来进行调度

5、haproxy+keepalived编译安装

5.1 haproxy编译安装

软件包:haproxy-1.7.9.tar.gz

tar -xf  haproxy-1.7.9.tar.gz -C  /usr/local
groupadd  -r  -g  159  haproxy
useradd -g haproxy -r -s /sbin/nologin -u 159 haproxy
cd /usr/local/haproxy-1.7.9/
make TARGET=linux26  ARCH=X86_64 PREFIX=/app/haproxy
make install PREFIX=/app/haproxy
mkdir /etc/haproxy/
vim /etc/haproxy/haproxy.cfg #放在附录文件
vim /etc/init.d/haproxy  #放着附录文件
chmod 777 /etc/init.d/haproxy
service haproxy start
chkconfig --add haproxy 
chkconfig --level 2345  haproxy on

5.2 keepalived编译安装

keepalived编译安装见博客:,链接如下,但是keepalived的配置文件有区别,见附录。其他步骤都一样
http://blog.51cto.com/ghbsunny/2154262

5.3 测试

haproxy和keepalived启动后,断开主keepalived,vip会排异到另一台服务器上

另外,通过访问vip 192.168.70.37 的监听5672端口,可以把请求调度到后端的三台mq上,且任何一台mq异常,请求将不会调度到这台异常的mq上,即服务正常。
测试成功

6、附录

6.1 haproxy配置文件

两台配置都一样

vim /etc/haproxy/haproxy.cfg 
global
    log 127.0.0.1 local0 info
    maxconn 8192
        user haproxy
    group haproxy
defaults
    timeout connect     3500
    timeout queue       11000
    timeout tarpit      12000
    timeout client      30000
    timeout http-request    40000
    timeout http-keep-alive 5000
    timeout server      40000
    timeout check       7000
    option  contstats
    option  log-health-checks
#################################
##监控查看本地状态#####
listen admin_stats
        bind 0.0.0.0:9188
    mode http
    log 127.0.0.1 local0 err
    stats refresh 30s
    stats uri /haproxy-hnsyun
    stats realm welcome login Haproxy
    stats auth admin:hns..2018
    stats hide-version
    stats admin if TRUE
####################################
###反代监控
frontend server
    bind *:5672
    log global
    mode tcp
    #option forwardfor
    default_backend rabbitmq
    maxconn 3
backend rabbitmq
    mode tcp
    log global
    balance roundrobin
    server   mq-01 192.168.70.32:5672  check inter 5s rise 2 fall 3   #check inter 2000 是检测心跳频率,rise 2是2次正确认为服务器可用,fall 3是3次失败认为服务器不可用
    server   mq-02 192.168.70.33:5672  check inter 5s rise 2 fall 3
    server   mq-03 192.168.70.34:5672  check inter 5s rise 2 fall 3

6.2 haproxy启动文件

#编译安装的执行文件的路径需要调整,其他地方可保持一致

vim /etc/init.d/haproxy
#!/bin/sh
#
# haproxy
#
# chkconfig:   - 85 15
# description:  HAProxy is a free, very fast and reliable solution 
#               offering high availability, load balancing, and 
#               proxying for TCP and  HTTP-based applications
# processname: haproxy
# config:      /etc/haproxy/haproxy.cfg
# pidfile:     /var/run/haproxy.pid
# Source function library.
. /etc/rc.d/init.d/functions
# Source networking configuration.
. /etc/sysconfig/network
# Check that networking is up.
[ "$NETWORKING" = "no" ] && exit 0
exec="/app/haproxy/sbin/haproxy"  #这里要注意,编译安装的执行文件的路径
prog=$(basename $exec)
[ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog
cfgfile=/etc/haproxy/haproxy.cfg
pidfile=/var/run/haproxy.pid
lockfile=/var/lock/subsys/haproxy
check() {
    $exec -c -V -f $cfgfile $OPTIONS
}
start() {
    $exec -c -q -f $cfgfile $OPTIONS
    if [ $? -ne 0 ]; then
        echo "Errors in configuration file, check with $prog check."
        return 1
    fi
    echo -n $"Starting $prog: "
    # start it up here, usually something like "daemon $exec"
    daemon $exec -D -f $cfgfile -p $pidfile $OPTIONS
    retval=$?
    echo
    [ $retval -eq 0 ] && touch $lockfile
    return $retval
}
stop() {
    echo -n $"Stopping $prog: "
    # stop it here, often "killproc $prog"
    killproc $prog 
    retval=$?
    echo
    [ $retval -eq 0 ] && rm -f $lockfile
    return $retval
}
restart() {
    $exec -c -q -f $cfgfile $OPTIONS
    if [ $? -ne 0 ]; then
        echo "Errors in configuration file, check with $prog check."
        return 1
    fi
    stop
    start
}
reload() {
    $exec -c -q -f $cfgfile $OPTIONS
    if [ $? -ne 0 ]; then
        echo "Errors in configuration file, check with $prog check."
        return 1
    fi
    echo -n $"Reloading $prog: "
    $exec -D -f $cfgfile -p $pidfile $OPTIONS -sf $(cat $pidfile)
    retval=$?
    echo
    return $retval
}
force_reload() {
    restart
}
fdr_status() {
    status $prog
}
case "$1" in
    start|stop|restart|reload)
        $1
        ;;
    force-reload)
        force_reload
        ;;
    check)
        check
        ;;
    status)
        fdr_status
        ;;
    condrestart|try-restart)
      [ ! -f $lockfile ] || restart
    ;;
    *)
        echo $"Usage: $0 {start|stop|status|restart|try-restart|reload|force-reload}"
        exit 2
esac

6.3 keepalived配置文件

主备的配置文件有三点不同
router_id不一样
优先级不一样
state主从不一样
其他都一样

vim /etc/keepalived/keepalived.conf
#Keepalived配置文件
global_defs {
        router_id NodeA                 #路由ID, 主备的ID不能相同
}
vrrp_instance VI_1 {
        state MASTER #Keepalived的角色。Master表示主服务器,从服务器设置为BACKUP
        interface eth0          #指定监测网卡
        virtual_router_id 35
        priority 100            #优先级,BACKUP机器上的优先级要小于这个值
        advert_int 1            #设置主备之间的检查时间,单位为s
        authentication {        #定义验证类型和密码
                auth_type PASS
                auth_pass Pass1234
        }
        virtual_ipaddress {     #VIP地址,可以设置多个:
                192.168.70.35
        }
}

centos 7 安装HAproxy四层TCP负载均衡配置及测试

未分类

haproxy负载均衡166.110.110.100
后端服务器1 166.110.110.1
后端服务器2 166.110.110.2

--------------------------------------------------centos 7 处理----------------------------------------------------
关闭SELinux
vi /etc/selinux/config
#SELINUX=enforcing #注释掉
#SELINUXTYPE=targeted #注释掉
SELINUX=disabled #增加
:wq!  #保存退出
setenforce 0 #使配置立即生效

关闭centos 7的防火墙(仅在测试的时候)
systemctl stop firewalld.service
systemctl disable firewalld.service
--------------------------------------------------haproxy安装----------------------------------------------------
yum install wget gcc -y && wget -c --no-check-certificate https://src.fedoraproject.org/repo/pkgs/haproxy/haproxy-1.8.12.tar.gz && tar -xvf haproxy-1.8.12.tar.gz && cd haproxy-1.8.12

groupadd haproxy #添加haproxy组
useradd -g haproxy haproxy -s /bin/false #创建nginx运行账户haproxy并加入到haproxy组,不允许haproxy
--------------------------------------------------haproxy配置----------------------------------------------------
vi /etc/haproxy/haproxy.cfg

修改为以下配置
#---------------------------------------------------------------------
# Example configuration for a possible web application.  See the
# full configuration options online.
#
#   http://haproxy.1wt.eu/download/1.4/doc/configuration.txt
#
#---------------------------------------------------------------------

#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
    # to have these messages end up in /var/log/haproxy.log you will
    # need to:
    #
    # 1) configure syslog to accept network log events.  This is done
    #    by adding the '-r' option to the SYSLOGD_OPTIONS in
    #    /etc/sysconfig/syslog
    #
    # 2) configure local2 events to go to the /var/log/haproxy.log
    #   file. A line like the following can be added to
    #   /etc/sysconfig/syslog
    #
    #    local2.*                       /var/log/haproxy.log
    #
    log         127.0.0.1 local2

    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    maxconn     4000
    user        haproxy
    group       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
    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
#---------------------------------------------------------------------
listen admin_stats  
        bind 127.0.0.1:1080               #监听端口  
        mode http                       #http的7层模式  
        option httplog                  #采用http日志格式  
        #log 127.0.0.1 local0 err  
        maxconn 10  
        stats refresh 30s               #统计页面自动刷新时间  
        stats uri /stats                #统计页面url  
        stats realm Proxy Haproxy  #统计页面密码框上提示文本  
        stats auth admin:admin          #统计页面用户名和密码设置  
        stats hide-version              #隐藏统计页面上HAProxy的版本信息  


listen test1  
        bind 0.0.0.0:80  
        mode tcp
        balance leastconn
        #maxconn 40000  
        #log 127.0.0.1 local0 debug  
        server s1 166.110.110.1:80  
        server s2 166.110.110.2:80
------------------------------------------------------------------------------------------------------
centos7下haproxy启动停止重启重载状态等控制命令
systemctl (start, stop, restart, try-restart, reload, force-reload, status) haproxy.service

haproxy web监控信息166.110.110.100为haproxy安装所在服务器IP
http://166.110.110.100:1080/status
-----------------------------后端安装lighttpd 作为测试用----------------------------------------------
systemctl stop firewalld.service
systemctl disable firewalld.service
关闭SELinux
vi /etc/selinux/config
将SELINUX=enforcing改为SELINUX=disabled

安装
yum install -y epel-release gcc gcc-c++ autoconf automake  zlib zlib-devel pcre-devel zip unzip libtool bzip2-* && yum install -y lighttpd && systemctl enable lighttpd

编辑配置文件关闭ipv6
vi /etc/lighttpd/lighttpd.conf
注释掉ipv6

启动服务器
systemctl restart lighttpd.service

默认目录及首页
/var/www/lighttpd/index.html

对两个index.html进行修改进行区别
后端第一个服务器
echo "<h1>this is upstream server 1" >> /var/www/lighttpd/index.html

后端第二个服务器
echo "<h1>this is upstream server 2" >> /var/www/lighttpd/index.html

访问haproxy所在服务器IP或者解析的域名刷新试试

-----------------------------Haproxy 负载均衡的8种算法----------------------------------------
balance roundrobin # 轮询,软负载均衡基本都具备这种算法

balance static-rr # 根据权重,建议使用

balance leastconn # 最少连接者先处理,建议使用

balance source # 根据请求源IP,建议使用

balance uri # 根据请求的URI

balance url_param,# 根据请求的URl参数'balance url_param' requires an URL parameter name

balance hdr(name) # 根据HTTP请求头来锁定每一次HTTP请求

balance rdp-cookie(name) # 根据据cookie(name)来锁定并哈希每一次TCP请求

服务器端口转发-Haproxy安装及端口转发配置

简介

haproxy是一款功能强大、灵活好用反代软件,提供了高可用、负载均衡、后端服务器代理的功能,它在7层负载均衡方面的功能很强大(支持cookie track, header rewrite等等),支持双机热备,支持虚拟主机,拥有非常不错的服务器健康检查功能,当其代理的后端服务器出现故障, HAProxy会自动将该服务器摘除,故障恢复后再自动将该服务器加入;同时还提供直观的监控页面,可以清晰实时的监控服务集群的运行状况。

方法

1、安装haproxy

yum -y install haproxy

2、然后清空haproxy.cfg文件内容

cd /etc/haproxy/
> haproxy.cfg

3、把下面的内容写入到haproxy.cfg文件中

global
ulimit-n  51200
defaults
log global
mode    tcp
option  dontlognull
timeout connect 1000ms
timeout client 150000ms
timeout server 150000ms
listen status
bind 0.0.0.0:1080
mode http
log global
stats refresh 30s
stats uri /admin?stats
stats realm Private lands
stats auth admin:password
stats hide-version
frontend ssin
bind *:1000-2000
default_backend ssout
backend ssout
server server1 11.22.33.44 maxconn 204800

说明:bind *:1000-2000这里指的是1000-2000端口,11.22.33.44为需要转发的服务器的IP。

4、启动haproxy服务

service haproxy start

最后别忘了在你的服务器里开放转发的端口。

基于 Keepalived + HAproxy 的 RabbitMQ 高可用配置实践

本文使用的高可用架构是 Keepalived + HAproxy,用 HAproxy 来做 RabbitMQ 负载均衡和高可用,用 Keepalived 来保证 HAproxy 的高可用。

RabbitMQ 集群的安装过程这里不再赘述,可以参考 https://blog.csdn.net/WoogeYu/article/details/51119101。

这里使用的三节点集群的安装方式,规划如下:

组件 IP 端口

RabbitMQ 主 192.168.151.7 5672
RabbitMQ 从 192.168.151.18 5672
RabbitMQ 从 192.168.151.19 5672
HAproxy 主 192.168.151.18
HAproxy 从 192.168.151.19
Keepalived 主 192.168.151.18
Keepalived 从 192.168.151.19
VIP 192.168.151.108

RabbitMQ 集群安装

在 192.168.151.7、192.168.151.18、192.168.151.19 三个节点上分别安装配置。

安装

yum -y install rabbitmq-server
service rabbitmq-server start

配置

rabbitmqctl add_user admin admin
rabbitmqctl set_user_tags admin administrator
set_permissions -p / admin ‘.*’ ‘.*’ ‘.*’
rabbitmqctl set_permissions -p / admin ‘.*’ ‘.*’ ‘.*’

rabbitmq-plugins enable rabbitmq_management

局域网配置
分别在三个节点的 /etc/hosts 下设置相同的配置信息

192.168.151.7 HRB-PCRP1-M-BCCLM-CTL7
192.168.151.18 HRB-PCRP1-M-BCCLM-CTL18
192.168.151.19 HRB-PCRP1-M-BCCLM-CTL19

设置不同节点间同一认证的 Erlang Cookie
采用从主节点 copy 的方式保持 Cookie 的一致性。

# scp /var/lib/rabbitmq/.erlang.cookie 192.168.151.18:/var/lib/rabbitmq
# scp /var/lib/rabbitmq/.erlang.cookie 192.168.151.19:/var/lib/rabbitmq12

使用 -detached 运行各节点

rabbitmqctl stop
rabbitmq-server -detached

查看各节点的状态

rabbitmqctl cluster_status

创建并部署集群,以 192.168.151.7 节点为例:

# rabbitmqctl stop_app
# rabbitmqctl reset
# rabbitmqctl join_cluster rabbit@HRB-PCRP1-M-BCCLM-CTL7
# rabbitmqctl start_app

查看集群状态

# rabbitmqctl cluster_status
Cluster status of node ‘rabbit@HRB-PCRP1-M-BCCLM-CTL7’ …
[{nodes,[{disc,[‘rabbit@HRB-PCRP1-M-BCCLM-CTL18’,
‘rabbit@HRB-PCRP1-M-BCCLM-CTL19’,
‘rabbit@HRB-PCRP1-M-BCCLM-CTL7’]}]},
{running_nodes,[‘rabbit@HRB-PCRP1-M-BCCLM-CTL18’,
‘rabbit@HRB-PCRP1-M-BCCLM-CTL19’,
‘rabbit@HRB-PCRP1-M-BCCLM-CTL7’]},
{cluster_name,<<“rabbit@HRB-PCRP1-M-BCCLM-CTL7”>>},
{partitions,[]},
{alarms,[{‘rabbit@HRB-PCRP1-M-BCCLM-CTL18’,[]},
{‘rabbit@HRB-PCRP1-M-BCCLM-CTL19’,[]},
{‘rabbit@HRB-PCRP1-M-BCCLM-CTL7’,[]}]}]

RabbitMQ 集群至此安装完成。可以通过访问各节点的 http://192.168.151.7:15672/ 管理页面查看 RabbitMQ 状态。用户名密码使用之前配置的 admin/admin。

Keepalived 监控 192.168.151.18、192.168.151.19 上的 HAproxy,利用 Keepalived 的 VIP 漂移技术,若两台服务器上的 HAprox 都工作正常,则 VIP 与优先级别高的服务器(主服务器)绑定,当主服务器当掉时,则与从服务器绑定,而 VIP 则是暴露给外部访问的 IP;HAproxy 利用 Keepalived 生产的 VIP 对多台 RabbitMQ 进行读负载均衡。

下面对上面的 RabbitMQ 集群进行高可用配置,HAproxy 和 Keepalived 的安装方法这里不再赘述。

高可用架构 Keepalived + HAproxy

未分类

其中 Keepalived 来控制 HAproxy 的高可用,HAproxy 的作用是控制下层应用的负载均衡,同时可以用来保证下层应用的高可用。

HAproxy

HAproxy 是一个七层的负载均衡高度器,和 nginx 是属于一个层次上的,而 lvs 是一个四层的负载均衡高度器,它最多只能工作在 TCP/IP 协议栈上,所以对于代理转发,HAproxy 做的可以比 lvs 更细腻。

HAProxy 提供高可用性、负载均衡以及基于 TCP 和 HTTP 应用的代理,支持虚拟主机,它是免费、快速并且可靠的一种解决方案。HAProxy 特别适用于那些负载特大的 web 站点,这些站点通常又需要会话保持或七层处理。HAProxy 运行在当前的硬件上,完全可以支持数以万计的并发连接。并且它的运行模式使得它可以很简单安全的整合进您当前的架构中,同时可以保护你的 web 服务器不被暴露到网络上。

HAproxy 配置

这里仅列出了主要内容。

HAProxy配置中分成五部分内容,当然这些组件不是必选的,可以根据需要选择部分作为配置。

#global :参数是进程级的,通常和操作系统(OS)相关。这些参数一般只设置一次,如果配置无误,就不需要再次配置进行修改
#defaults:配置默认参数的,这些参数可以被利用配置到frontend,backend,listen组件
#frontend:接收请求的前端虚拟节点,Frontend可以根据规则直接指定具体使用后端的 backend(可动态选择)。
#backend :后端服务集群的配置,是真实的服务器,一个Backend对应一个或者多个实体服务器。
#listen :Frontend和Backend的组合体。

listen rabbitmq
bind 192.168.151.108:5673
balance roundrobin
mode tcp
option tcplog
option tcpka
bind-process 7
timeout client 15s
timeout connect 3s
timeout server 15s
server HRB-PCRP1-M-BCCLM-CTL7 192.168.151.7:5672 check inter 5000 rise 2 fall 3
server HRB-PCRP1-M-BCCLM-CTL18 192.168.151.18:5672 check inter 5000 rise 2 fall 3
server HRB-PCRP1-M-BCCLM-CTL19 192.168.151.19:5672 check inter 5000 rise 2 fall 3
# weight – 调节服务器的负重
# check – 允许对该服务器进行健康检查
# inter – 设置连续的两次健康检查之间的时间,单位为毫秒(ms),默认值 2000(ms)
# rise – 指定多少次连续成功的健康检查后,可认定该服务器处于可操作状态,默认值 2
# fall – 指定多少次不成功的健康检查后,认为服务器为当掉状态,默认值 3
# maxconn – 指定可被发送到该服务器的最大并发连接数

# 配置haproxy web监控,查看统计信息
listen private_monitoring :8100
mode http
option httplog
stats enable
#设置haproxy监控地址为http://localhost:8100/stats
stats uri /stats
stats refresh 5s

这里使用了一个 listen 块来同时实现前端和后端,也可以由前端(frontend)和后端(backend)配置。

最后我们打开 http://192.168.151.18:8100/stats,看一下监控页面,如果显示出正常就表明已经将 HAProxy 负载均衡配置好了!

未分类

注意点

启动 HAproxy 时可能会出现 cannot bind socket 的异常,这是因为 HAproxy 配置中使用了 VIP,但此时还没有启动 Keepalived,那么就还没有 VIP 绑定。

这时需要在 /etc/sysctl.conf 文件中配置如下内容:

net.ipv4.ip_nonlocal_bind = 1 # 意思是启动haproxy的时候,允许忽视VIP的存在
net.ipv4.ip_forward = 1 # 打开内核的转发功能

然后运行 sysctl –p 使其生效。

Keepalived

Keepalived 的作用是检测服务器的健康状态,在所有可能出现单点故障的地方为其提供高可用。如果有一台服务器死机,或工作出现故障,Keepalived 将检测到,并将有故障的服务器从系统中剔除,当服务器工作正常后 Keepalived 自动将服务器加入到服务器群中,这些工作全部自动完成,不需要人工干涉,需要人工做的只是修复故障的服务器。

这里使用的实现方式是单活方式,即主节点的 HAproxy 正常运行,备节点的会被停止。当主节点的出现故障时,备节点的 HAproxy 会自动启动。当主节点的恢复后,备节点的会自动停止。

当然 Keepalived 的高可用控制不止这一种,也可以有其他配置方式。

Keepalived 主节点配置

vrrp_script chk_haproxy {
script “service haproxy status” # 服务探测,返回0说明服务是正常的
interval 1 # 每隔1秒探测一次
weight -2 # 不正常时,权重-1,即haproxy上线,权重加2;下线,权重减2
}

vrrp_instance haproxy {
state MASTER # 主机为MASTER,备机为BACKUP
interface bond0 # 监测网络端口,用ipconfig查看
virtual_router_id 108 # 主备机必须相同
priority 100 # 主备机取不同的优先级,主机要大。
advert_int 1 # VRRP Multicast广播周期秒数
authentication {
auth_type PASS # VRRP认证方式
auth_pass 1234 # VRRP口令 主备机密码必须相同
}

track_script { # 调用haproxy进程检测脚本,备节点不配置
chk_haproxy
}
track_interface {
bond0
}
virtual_ipaddress { # VIP 漂移地址 即集群IP地址
192.168.151.108/25 dev bond0
}
}

Keepalived 备节点

vrrp_instance haproxy {
state BACKUP
interface bond0
virtual_router_id 108
priority 99
advert_int 1
authentication {
auth_type PASS
auth_pass 1234
}
track_interface {
bond0
}
virtual_ipaddress {
192.168.151.108
}
notify_master “/etc/keepalived/notify.sh master” # 当前节点成为master时,通知脚本执行任务,一般用于启动某服务
notify_backup “/etc/keepalived/notify.sh backup” # 当前节点成为backup时,通知脚本执行任务,一般用于关闭某服务

}

notify.sh 脚本
放在 /etc/keepalived/ 目录下,并赋予可执行权限。

#!/bin/bash

case “$1” in
master)
notify master
service haproxy start
exit 0
;;
backup)
notify backup
service haproxy stop
exit 0
;;
fault)
notify fault
service haproxy stop
exit 0
;;
*)
echo ‘Usage: `basename $0` {master|backup|fault}’
exit 1
;;
esac

Keepalived 执行过程
MASTER – 初始 priority 为 100,BACKUP – 初始 priority 为 99

模拟 MASTER 产生故障:

当检测到 chk_haproxy 执行结果为 down 时,priority 每次减少 2,变为 98;低于 BACKUP 的 priority;
此时 MASTER 变成 BACKUP;
同时 BACKUP 变成 MASTER,同时执行 notify_master 的脚本文件(启动haproxy);
模拟 MASTER 故障恢复:

当 MASTER 节点的 HAproxy 恢复后,原 MASTER 的优先级又变为 100,高于原 BACKUP 的 priority;
此时原 MASTER 由 BACKUP 又抢占成了 MASTER;
同时原 BACKUP 由 MASTER 又变了 BACKUP,同时执行 notify_backup 的脚本文件(关闭haproxy);

keepalived + haproxy + mysql 构建高可用数据库

keepalived + haproxy + mysql 构建高可用

  • keepalived 的高可用是主备,有一台作为备用
  • keepalived + haproxy 搭建的高可用是可以两台都会调度的高可用

拓扑图:

未分类

keepalived:负责抢占虚拟ip,使用vrrp协议
haproxy:负责做访问调度,减轻单点压力,单独监听一个端口,这里用23306

1、安装mysql

分别在两台机器上面搭建mysql,并做主从配置,这里不做介绍

2、搭建haproxy

  1. download 源码包,下载地址:http://www.haproxy.org/#down
  2. 在81.128和81.129解压缩安装
tar xf haproxy-1.8.4.tar.gz
cd haproxy-1.8.4
yum install -y gcc
make TARGET=linux310 ARCH=x86_64 # uname -a查看主机信息填写
make install SBINDIR=/usr/sbin/ MANDIR=/usr/share/man/ DOCDIR=/usr/share/doc/

3、提供启动脚本

#!/bin/sh
#
# haproxy
#
# chkconfig:   - 85 15
# description:  HAProxy is a free, very fast and reliable solution 
#               offering high availability, load balancing, and 
#               proxying for TCP and  HTTP-based applications
# processname: haproxy
# config:      /etc/haproxy/haproxy.cfg
# pidfile:     /var/run/haproxy.pid

# Source function library.
. /etc/rc.d/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

# Check that networking is up.
[ "$NETWORKING" = "no" ] && exit 0

exec="/usr/sbin/haproxy"
prog=$(basename $exec)

[ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog

cfgfile=/etc/haproxy/haproxy.cfg
pidfile=/var/run/haproxy.pid
lockfile=/var/lock/subsys/haproxy

check() {
    $exec -c -V -f $cfgfile $OPTIONS
}

start() {
    $exec -c -q -f $cfgfile $OPTIONS
    if [ $? -ne 0 ]; then
        echo "Errors in configuration file, check with $prog check."
        return 1
    fi

    echo -n $"Starting $prog: "
    # start it up here, usually something like "daemon $exec"
    daemon $exec -D -f $cfgfile -p $pidfile $OPTIONS
    retval=$?
    echo
    [ $retval -eq 0 ] && touch $lockfile
    return $retval
}

stop() {
    echo -n $"Stopping $prog: "
    # stop it here, often "killproc $prog"
    killproc $prog
    retval=$?
    echo
    [ $retval -eq 0 ] && rm -f $lockfile
    return $retval
}

restart() {
    $exec -c -q -f $cfgfile $OPTIONS
    if [ $? -ne 0 ]; then
        echo "Errors in configuration file, check with $prog check."
        return 1
    fi
    stop
    start
}

reload() {
    $exec -c -q -f $cfgfile $OPTIONS
    if [ $? -ne 0 ]; then
        echo "Errors in configuration file, check with $prog check."
        return 1
    fi
    echo -n $"Reloading $prog: "
    $exec -D -f $cfgfile -p $pidfile $OPTIONS -sf $(cat $pidfile)
    retval=$?
    echo
    return $retval
}

force_reload() {
    restart
}

fdr_status() {
    status $prog
}

case "$1" in
    start|stop|restart|reload)
        $1
        ;;
    force-reload)
        force_reload
        ;;
    check)
        check
        ;;
    status)
        fdr_status
        ;;
    condrestart|try-restart)
        [ ! -f $lockfile ] || restart
        ;;
    *)
        echo $"Usage: $0 {start|stop|status|restart|try-restart|reload|force-reload}"
        exit 2
esac

4、提供配置文件

mkdir /etc/haproxy
mkdir /var/lib/haproxy
useradd -r haproxy
vim /etc/haproxy/haproxy.cfg
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                    tcp
    log                     global
    option                  dontlognull
    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                 600

listen stats
    mode http
    bind :6677 
    stats enable
    stats hide-version              
    stats uri     /haproxyadmin?stats
    stats realm   Haproxy Statistics
    stats auth    admin:admin
    stats admin if TRUE 

frontend  main 
    bind  *:23306
    default_backend             mysql

backend mysql
    balance     leastconn
    server m1 192.168.81.128:3306 check port 3306 maxconn 300
    server m2 192.168.81.129:3306 check port 3306 maxconn 300

5、修改日志系统

###Provides UDP syslog reception //去掉下面两行注释,开启UDP监听

$ModLoad imudp
$UDPServerRun 514

local2.* /var/log/haproxy.log //添加此行
service rsyslog restart

6、启动测试haproxy

service haproxy start 
chkconfig --add haproxy
chkconfig haproxy on
netstat -tnlp
mysql -P23306 -uroot -p123456 -h192.168.81.129 # 查看

server_id,判断是否成功

7、搭建keepalived

1、download 源码包,下载地址:http://www.keepalived.org/download.html

2、在81.128和81.129解压缩安装

tar xf keepalived-1.2.7.tar.gz 
cd keepalived-1.2.7
./configure --prefix=/usr/local/keepalived --sbindir=/usr/sbin/ --sysconfdir=/etc/ --mandir=/usr/local/share/man/
make && make install
chkconfig --add keepalived
chkconfig keepalived on

3、提供配置文件

vim /etc/keepalived/keepalived.conf # 两个机器配置文件不同

! Configuration File for keepalived

global_defs {           
notification_email {          # 忽略
     [email protected]
     [email protected]
     [email protected]
   }
   notification_email_from [email protected]
   smtp_server 192.168.200.1
   smtp_connect_timeout 30
   router_id LVS_DEVEL
}

vrrp_script chk_haproxy {
    script "/etc/keepalived/chk.sh"     # 检查haproxy的脚本
    interval 2                          # 每两秒检查一次
}

vrrp_instance VI_1 {
    state BACKUP                        # 定义为BACKUP节点
    nopreempt                           # 开启不抢占,另一个不写
    interface ens33
    virtual_router_id 51
    priority 100                        # 开启了不抢占,所以此处优先级必须高于另一台,另一个写99
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass abcd
    }
    virtual_ipaddress {
        192.168.81.150                  # 配置VIP
    }
    track_script {
        chk_haproxy                     # 调用检查脚本
    }

    notify_backup "/etc/init.d/haproxy restart"
    notify_fault "/etc/init.d/haproxy stop"
} 

4、创建check文件

vim /etc/keepalived/chk.sh
#!/bin/bash

if [ $(ps -C haproxy --no-header | wc -l) -eq 0 ]; then
       /etc/init.d/keepalived stop
fi
chmod +x /etc/keepalived/chk.sh 
service keepalived start

5、测试

ip addr # 查看是否绑定了虚ip
tcpdump -nn -i ens33 vrrp # 抓包查看
http://192.168.81.128:6677/haproxyadmin?stats # 通过haproxy查看状态

lvs,nginx,haproxy的优缺点,适合场景

Nginx/LVS/HAProxy的基于Linux的开源免费的负载均衡软件。

LVS:使用集群技术和Linux操作系统实现一个高性能、高可用的服务器,它具有很好的可伸缩性、可靠性和可管理性,是一款强大实用的开源软件。

LVS的优点:

1:抗负载能力强、是工作在网络4层之上仅作分发之用,没有流量的产生,这个特点也决定了它在负载均衡软件里的性能最强的,也保证了均衡器I/O的性能不会受到大流量的影响。;
2:lvs是专门的负载均衡软件,对任何应用都可以做负载均衡;
3:工作稳定,因为其本身抗负载能力很强,自身有完整的双机热备方案,目前用的比较多的是lvs+keepalived,比较大型的用的多的是lvs+heartbeat。

nginx的优点:

1:Nginx的高并发,同时能承载上万个并发连接;
2:nginx有充足的第三方功能模块的支持,主要通过upstream模块进行负载均衡;
3:nginx对网络的依赖较小,理论上只要Ping得通,网页访问正常,nginx就能连得通;
4:工作在网络的7层之上,可以针对http应用做一些分流的策略,它的正则规则比haproxy更为强大和灵活,这也是它目前广泛流行的主要原因之一,nginx单凭这点可利用的场合就远多于lvs了。

nginx的缺点:

1:将Nginx当做反向代理时,负载均衡功能不是很好,对后端服务器的健康检查功能较弱;
2:nginx仅能支持http、https和email协议,这样就在适用范围上面小些,这个是它的缺点;
3:nginx只支持通过端口来检测,不支持通过url来检测。

haproxy的优点:

1:HAProxy的优点能够补充Nginx的一些缺点,比如支持Session的保持,Cookie的引导;同时支持通过获取指定的url来检测后端服务器的状态;
2:haproxy也是专门的负载均衡软件,Haproxy可以负载http,还可以负载均衡mysql;
3:HAProxy是支持虚拟主机的。

总结这么多,我觉得根据不同的需求,不同的功能,可以选择不同的软件类的负载均衡软件,当然也是可以选择硬件类的负载均衡器。
像对于大型的,需要进行高并发的网站或者对网络不太严格的时候,可以使用nginx;
对于大型的Web服务器的时候可以使用haproxy;
对性能有严格要求的时候可以使用lvs,就单纯从负载均衡的角度来说,lvs也许会成为主流,更适合现在大型的互联网公司。

Haproxy和pacemaker结合corosync实现负载均衡高可用,以及crm命令的使用

实验之前需要将之间做的负载均衡和高可用软件全部关掉!!!!!
server1和server9上安装Haproxy:
server1:

安装见上篇博文:
scp haproxy-1.6.11-1.x86_64.rpm 172.25.92.9:/root
scp /etc/haproxy/haproxy.cfg 172.25.92.9:/etc/haproxy
scp /etc/security/limits.conf 172.25.92.9:/etc/security
vim /etc/haproxy/haproxy.cfg 
     37         bind            172.25.92.100:80 name clear     #设置只有访问172.25.92.100才能访问集群资源
/etc/init.d/haproxy start

server9:

 rpm -ivh haproxy-1.6.11-1.x86_64.rpm 
  groupadd -g 200 haproxy
  useragdd -u 200 -g 200 haproxy
 useradd -u 200 -g 200 haproxy
  id haproxy
vim /etc/haproxy/haproxy.cfg
    37         bind            172.25.92.100:80 name clear
/etc/init.d/haproxy start

测试:打开后端服务器server2和server3:
server1和server9:curl 172.25.92.100
可以看到server3的hph页面。(之前搭建的)

server1和server9安装pacemaker和corosync:
其中corosync再之前做RHCS套件时已经安装,因为RHCS套件的高可用也时利用corosync实现心跳检测。
server1:

yum install -y pacemaker corosync
/etc/init.d/corosync start
[root@server1 ~]# cd /etc/corosync/
[root@server1 corosync]# cp corosync.conf.example corosync.conf
[root@server1 corosync]# vim corosync.conf
10                 bindnetaddr: 172.25.92.0
 11                 mcastaddr: 226.94.1.92
 12                 mcastport: 5405

 34 service{
 35         name:pacemaker
 36         ver:0
 37 }

[root@server1 corosync]# scp corosync.conf 172.25.92.9:/etc/corosync/

[root@server1 corosync]# /etc/init.d/corosync start
Starting Corosync Cluster Engine (corosync):               [  OK  ]
[root@server1 corosync]# tail -f /var/log/messages
#如果日志中有很多error,可能是因为多播地址或者端口冲突

#健康检测:
[root@server1 ~]# crm_verify -LV  发现没有fence设备报错

#安装crm管理工具:
[root@server1 ~]# yum install crmsh-1.2.6-0.rc2.2.1.x86_64.rpm pssh-2.3.1-2.1.x86_64.rpm


#配置禁掉fence功能
在主机上:/etc/fence_virtd stop
[root@server1 ~]# crm
crm(live)# configure 
crm(live)configure# property stonith-enabled=false
[root@server1 ~]# crm_verify -LV    #不报错

#关闭集群对节点数量的检查,集群默认最少量台主机,如果只是一台主机不能接管资源
crm(live)configure# property no-quorum-policy=ignore
crm(live)configure# commit

#添加资源,vip
crm(live)configure# primitive vip ocf:heartbeat:IPaddr2 params ip=172.25.92.100 cidr_netmask=24 op monitor interval=20s        #添加vip,并设置20s对资源监察一次,监控端可以发现vip资源添加上
crm(live)configure# commit

测试:在主机上访问:curl 172.25.92.100可以看见server3上的html页面。关掉其中一台corosnsc,vip会上到另一台主机上。

#添加资源haproxy:
crm(live)configure# primitive haproxy lsb:haproxy op monitor interval=30s
crm(live)configure# commit 

#添加haproxy后可以看出来vip和haproxy不再一台主机上,资源飘移:
#解决办法:建立资源组就可以解决
crm(live)configure# group westos vip haproxy
crm(live)configure# commit 

#添加资源fence:
添加fence之前首先开启主机上:systemctl start fence_virtd
yum install -y fence-virt.x86_64 fence-agents.x86_64 #两台主机上都做(server1和server9) ``!!!!! ``
crm(live)configure# property stonith-enabled=true  #开启fence功能
crm(live)configure# commit

[root@server1 ~]# stonith_admin -I   #查看主机支持fence的代理类型。本次使用fence_xvm
[root@server1 ~]# stonith_admin -M -a fence_xvm

crm(live)configure# primitive vmfence stonith:fence_xvm params  pcmk_host_map="server1:server1;server9:server9" op monitor interval=1min    #添加fence资源,并做好集群节点名和真实server的名字映射

#测试fence功能:
首先设置:corsync在两台主机上可其自启动:chkconfig corosync on
reboot(重启动)其中一台主机,等主机开启后会自动加到集群中!

#对集群 资源 的管理:
crm(live)resource# show        #显示资源种类,此处时只添加了一个资源vip,所以显示一个 
 vip    (ocf::heartbeat:IPaddr2):   Started #开启vip资源
crm(live)resource# stop vip
crm(live)resource# show
 vip    (ocf::heartbeat:IPaddr2):   Stopped  #停掉vip资源

#对集群 节点 的管理:
[root@server1 ~]# crm
crm(live)# node 
crm(live)node# standby     #停掉server1节点
crm(live)node# online      #开启sesrver1节点

server9:和server1是同步的,但此处作为监控

yum install -y pacemaker corosync
/etc/init.d/corosync start
#安装管理工具:
[root@server9 ~]# yum install pssh-2.3.1-2.1.x86_64.rpm crmsh-1.2.6-0.rc2.2.1.x86_64.rpm 
#监控集群:
[root@server9 ~]# crm_mon

haproxy TCP源端口耗尽问题

此文基本是翻译aloha的一篇文档,本人实际使用情况遇到的问题类似,但不是MySQL。

[2017.01.12 增补] 1.7版的haproxy开启了IP_BIND_ADDRESS_NO_PORT支持 ,即可以复用source port,这样可以从更基础的内核层面解决这个问题,唯一不足是需要将内核升级到4.2以上版本才可以。
参考:
http://www.haproxy.org/download/1.7/src/CHANGELOG
https://kernelnewbies.org/Linux_4.2#head-8ccffc90738ffcb0c20caa96bae6799694b8ba3a

环境描述

小公司,一个比较繁忙的PHP/MySQL构建的站点。
前端使用haproxy做负载均衡,后端web server连接MySQL数据库。
MySQL做了主从复制,前端PHP代码做了读写分离。
MySQL Master负责写入请求和一小部分读请求,MySQL Slave负责响应读请求。
另一个haproxy作为MySQL的反向代理。

拓扑图

未分类

问题描述

在请求很少的时候,工作得非常好。但当MySQL上的请求压力增大(2~3K次/秒)的时候,haproxy的本地端口耗尽。日志中报大量health check SOCKERR错误。

原因分析

haproxy作为反向代理,会使用自己的IP地址作为源地址连接后端的MySQL服务器。
根据TCP协议,无论任何类型操作系统都只能拥有64K个左右的源TCP端口,用于向外发起TCP连接。
一旦”srcIP:port => dstIP:port”建立,这个源端口将不能被重用于其它连接。
当前的MySQL Client Lib关闭连接时的操作序列如下:

Mysql Client ==> "QUIT" sequence ==> Mysql Server 
Mysql Client ==> FIN ==> MySQL Server 
Mysql Client <== FIN ACK <== MySQL Server 
Mysql Client ==> ACK ==> MySQL Server

这时候MySQL Client会进入2MSL状态,时间2分钟。
那么什么是2MSL状态呢?请看下图,这是关于TCP关闭连接时的握手序列:

未分类

上边TCP状态图中有一个TIME_WAIT状态,就是所谓的2MSL状态。
MSL就是maximum segment lifetime(最大分节生命期),这是一个IP数据包能在互联网上生存的最长时间,超过这个时间将在网络中消失。
MSL在RFC 1122上建议是2分钟,而源自berkeley的TCP实现传统上使用30秒。
因而,TIME_WAIT状态一般维持在1-4分钟。
该状态是为了可靠地实现TCP全双工连接的终止,保证在tcp客户端发给tcp服务端的最后一个ACK能顺利到达。
若没有TIME_WAIT状态,tcp客户端将直接进入CLOSED状态。
如果tcp客户端直接进入CLOSED状态,那么由于IP协议的不可靠性或者是其它网络原因,导致tcp服务端没有收到tcp客户端最后回复的ACK。那么tcp服务端就会在超时之后继续发送FIN,此时由于tcp客户端已经CLOSED了,就找不到与重发的FIN对应的连接,最后tcp服务端就会收到 RST而不是ACK,tcp服务端就会以为是连接错误把问题报告给高层协议。
这样的情况虽然不会造成数据丢失,但是却导致TCP协议不符合可靠连接的要求。
所以,tcp客户端不是直接进入CLOSED状态,而是要保持TIME_WAIT,当再次收到FIN的时候,能够保证对方收到ACK,最后正确的关闭连接。

这里有2点需要强调一下:

1、对于tcp请求来说,tcp的客户端服务端概念和http的不同,请求双方,哪边关闭请求,哪边就是tcp客户端,另一边就为服务端。请不要与MySQL Client和MySQL Server混淆起来。
2、tcp的一个链接由4个值确定,源ip、源端口、目标ip、目标地址。

参考:http://omnitraining.net/networking-101/98-networking-101-understanding-tcp-part-2
“There is no way for the person who sent the first FIN to get an ACK back for that last ACK. You might want to reread that now. The person that initially closed the connection enters the TIME_WAIT state; in case the other person didn’t really get the ACK and thinks the connection is still open. Typically, this lasts one to two minutes.”

根据上述的论述,如果一个源端口在2分钟内不能再次使用,则超过534个/秒的MySQL Client请求将会耗尽其本地TCP源端口。
64000 (可用端口) / 120 (2分钟,即120秒) = 533.333.

因为haproxy作为反向代理,会将所有MySQL请求转发给MySQL Server,因此haproxy会比MySQL Client更快的耗尽本地TCP源端口!!

但是如果MySQL Client和MySQL Server在同一台主机上,使用looback接口通信,则MySQL关闭序列是一个相对”干净”的序列:

Mysql Client ==> "QUIT" sequence ==> Mysql Server
Mysql Client <== FIN <== MySQL Server 
Mysql Client ==> FIN ACK ==> MySQL Server 
Mysql Client <== ACK <== MySQL Server

但在非loopback接口上则不是!因此如果要解决这个问题,需要MySQL的开发者修改他们的代码……
那么是不是完全没有办法呢?也不是,请向下看。

解决方案

1、增加本地端口范围
对于单一的dstIP:port,可用的源端口默认是28K左右,可以用如下命令查看当前值:

[haproxy ~]# sysctl net.ipv4.ip_local_port_range
net.ipv4.ip_local_port_range = 32768 61000

增加到64K个源端口

[haproxy ~]# vi /etc/sysctl.conf
net.ipv4.ip_local_port_range = 1025 65000

2、允许处于TIME_WAIT状态的源端口重用

[haproxy ~]# vi /etc/sysctl.conf
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1

3、使用多个IP连接单一dstIP:port,并让haproxy来管理源端口
配置示例:

....
server mysql1     10.0.0.1:3306 check source 10.0.0.100:1025-65000
server mysql1_bis 10.0.0.1:3306 check source 10.0.0.101:1025-65000
....

经过测试,如果不让haproxy管理源端口,则4个源IP地址最多管理不超过80K个TIME_WAIT连接。
但是haproxy管理源端口可以达到170K+个TIME_WAIT连接!!!

4、使用memcached和MySQL persistant connections

参考文档:
http://blog.exceliance.fr/2012/12/12/haproxy-high-mysql-request-rate-and-tcp-source-port-exhaustion/
http://go12345.iteye.com/blog/1798119
http://ganquan.org/blog/2009/09/tcp协议的time_wait状态详解/
http://kerry.blog.51cto.com/172631/105233/

HAProxy概念、配置、生产实例

HAProxy实验环境准备

node1:扮演调度器(安装HAProxy),node2:扮演后台web服务器节点1(安装nginx),node3:扮演后台web服务器节点2(安装nginx)。有关虚拟机安装后常见操作请看上一篇文章。

先来一波,让HAProxy运行起来

先把需要的软件安装好:

node1 ]# yum install -y haproxy
node2 ]# yum install -y nginx
node3 ]# yum install -y nginx

把node2、node3的nginx服务启动起来,添加网页文件(后面可能会写一篇关于nginx的文章)。
对于node1,修改HAP的配置文件(生产环境中,修改配置文件前要先做好备份):

node1 ]# vim /etc/haproxy/haproxy.cfg
保留global段、defaults段,其他配置信息都删掉。添加以下配置:
listen NginxServers
        bind *:80
        balance static-rr
        server N1 node2:80
        server N2 node3:80
启动HAP服务:node1 ]# systemctl start haproxy.service

打开浏览器,访问node1节点80端口,刷新网页,可以看到HAP已经能够正常工作!并把HTTP请求按照轮询的方式调度给node2和node3节点的nginx服务。

未分类

未分类

HAProxy介绍

HAProxy,High Available Proxy,即高可用的代理服务器。要注意的是,这里的高可用不是指HAP服务自身实现了高可用,而是指HAP原生自带对后端服务器的健康状态检查机制,若发现某个BackEnd Server不可用,服务请求就不会再发往此后端节点。
HAP是一种软件实现的负载均衡器,因此它工作为用户空间的一个进程,基于套接字与客户端,后端主机进行通信。基于此,HAP能够很好地支持对HTTP请求的七层调度,对HTTP请求实现诸如“动静分离”,“HTTP方法分离”等。另外,HAP支持通过模拟方式实现四层调度,四层调度性能应该稍差。
总的来说,HAP是目前最主流的七层调度器实现方案之一,具有较好的性能以及配置多样性。

HAP配置详解

HAP将配置文件分为两大段。

  • Global段:用来定义进程安全相关配置,性能参数调整,Debug等服务相关的配置。

  • Proxy段:用来定义与调度的具体实现方式,Proxy段具体包括

    • listen段:listen可以直接确定一种调度工作方式
    • frontend段:定义与客户端通信的工作方式
    • backend段:定义与后端主机通信的工作方式
    • defaults段:定义listen,frontend,backend中某些变量的默认值

global:全局配置段常用变量

进程及安全配置相关参数:
       chroot  /var/lib/haproxy:禁锢根,haproxy进程以此目录作为根目录,防止haproxy进程被劫持而设定的安全性配置
       user  haproxy: 运行haproxy进程的用户和组
       group haproxy:
       daemon:表示haproxy运行于后台守护进程,而非前台(调试模式)
       nbproc <number>:指明要启动的haproxy进程数量; haproxy默认工作于基于事件驱动的单进程模型(也可以指明为启动多进程,官方并不建议)
       ulimit-n <number>:每个haproxy进程能够打开的最大文件数:此参数非常重要,因为每一个连接都需要打开一个socket file,因此该值至少大于进程数 * 每个进程接受的最大连接数。haproxy能够根据运行情况自行调整该值,一般不需要定义
       log:定义全局的syslog服务器,用于将haproxy产生的日志发往并存储
             log <address> <facility> [level]

好像现在HAP默认关闭了日志记录,要启用还挺麻烦,大家可以参考这篇文章作者的启用方式,测试有效!HAProxy启用日志

     性能调整相关参数
       maxconn 4000:单个haproxy进程所能接受的最大并发连接数
       maxpipes:使用pipe机制实现内核级tcp报文重组;每进程能够使用的最大pipe数量;haproxy能够自动调整
       spread-checks <0..50>:百分比数字,用于打散健康状态监测的时间点。例如每隔60秒对后端100台主机进行健康状态检查,此值设定为20表示,某台主机进行完一次检查后,下一次的检查时间可能是(48s,72s)内的任何一个时间,这样就打散了每台主机的检查时间,从而减轻了由于health-check带来的性能消耗
      Debug相关参数
        debug:详细输出日志信息(调试模式时)
        quiet:简化日志的输出信息

下面介绍Proxy段中的常用变量:这些变量可用于listen,frontend,backend中的一个或多个

1、bind:可用在listen,frontend;用于指明haproxy服务监听的套接字地址
   # bind <address>:<port_range>,....[param*]

e.g.    bind *:80 ssl, 192.168.1.7/24:8080 

表示haproxy监听于任意ipv4地址的80端口(外部访问),以及192.168.1.7:8080这一地址(内部访问),同时,并且受理外部请求时必须是https连接。      


2、balance:可用在listen,backend,default;用于指明对后端server使用的调度算法
     # balance <algo> [params]
              <algo>: 表示调度算法,常用的调度算法如下:
                roundrobin  [加权]轮询
                 动态算法,支持权重的运行时调整以及慢启动机制;最多4095个后端主机
                 慢启动:若共6000个连接,3台后端服务器,权重均相同,则每台处理2000个连接。此时新增一台服务器,那么应该每台处理1500个连接,所以大量的新连接都会给新增的那台,极易造成压力过大,慢启动则避免了这点
                static-rr    [加权]轮询
                 静态算法:不支持权重的运行时调整以及慢启动机制;后端主机无数量限制

                leastconn   最少连接
                推荐使用在较长时间会话场景中,如LDAP,MYSQL协议

                first    依次处理请求
                  每台后端主机可定义自己的maxconn。first算法根据maxconn的从大到小为后端主机排序,然后每次都将连接请求发给maxconn最大的那台主机,直到达到它的maxconn,才调度给下一台sever。
                  first算法的好处是能够节约虚拟机资源(backendserver一般是虚拟机实例),按需决定启动多少台虚拟机,坏处是配置麻烦,单台虚拟机处理太多连接压力过大。

               source  源地址hash ---> 会话绑定
               uri     目标地址hash ---> 提高缓存命中率

                    采用哈希调度算法时,NEW连接首次被调度至哪里可用hash-type命令由两种方式指定:
                    #  hash-type <method>
                              map-based  取模法
                              consistent    一致性哈希

                hdr(<name>)  
                      对于每个http请求,此处name指定的http报文首部会被取出做hash计算。然后再有相同的请求时,调度给同一台主机。source和uri是它最常用的hash调度子类
            e.g.   对于某个站点,可能由多个域名,如jd.com,www.jd.com,对于请求报文中不同Host,都始终调度给同一台backend_server       
                              balance  hdr(Host)
                              hash-type  map-based


3、log:用在default,frontend,backend,listen;定义日志的记录位置,做多定义两个位置。
        # log global || #  log <address> <facility> [level] || #  no log
        分别表示使用全局配置中的log记录位置或使用自定义的日志记录位置或不记录日志


4、capture request header;用在listen,frontend;用于添加指定请求报文首部信息记录于日志中
    # capture request header <name> len <length>
    e.g.  capture request header User-Agent len 10


5、capture response header ;用在listen,frontend;用于添加指定响应报文首部信息记录于日志中
    # capture response header <name> len <length>
e.g.  capture response header Cache-Control len 5


6、compression;用在listen,frontend,backend;用于压缩报文中的body部分
    # compression algo <algorithm>
    # compression type <mime type>
        支持的压缩algo:gzip,deflate
        mime type:通常只压缩文本类信息
e.g.   compression algo gzip 
         compression type  text/html
注意:compression用在frontend中表示压缩与客户端通信报文中的body,用在backend中则表示压缩与后端主机通信过程中报文的body


7、server:用于listen,backend;用来定义一个后端主机
    #  server <name> <addr:port> [params*]
        <name>:HAProxy中服务器的唯一标识,必给
        <addr:port>:后端主机监听的ip地址及端口
        [params*]:定义一个主机时同时可指定的可选参数
                backup:设定为备用服务器,仅在LB中其他服务器均不可用时才接受请求。类似于nginx-upstream定义主机时的down,用于维护时下线主机
                check:对后端主机作基于tcp端口的四层健康状态检测;check后可跟辅助参数,也可仅适用默认值
                            inter<delay>:每隔多久做一次检测
                            fall<count>:连续多少次失败从LB中移除该主机
                            rise<count>:连续多少次成功从LB中添加该主机
                maxconn:指定该服务器支持的最大连接数
                maxqueue:指定该服务器支持的最大等待队列长度
                cookie <name>:本台server的cookie信息,可任意指定
                redir <prefix>:将发往此服务器的所有GET,HEAD请求重定向至指定地址
                weight <weight>:指定权重


8、httpchk:用于listen,backend;基于7层http协议对后端主机进行状态检测
   # option httpchk  <uri>
e.g.   option httpchk  /login.html    


9、cookie:用于listen,backend;设定基于cookie的会话绑定       
    # cookie <name> [ insert | prefix | rewrite ] [params*]
            <name>:cookie标签的名字
            insert:插入某主机的cookie信息
            prefix:在cookie前添加信息
            rewrite:重写cookie
e.g.   cookie  WEBNODES insert  indirect nocache
         server node1 172.16.100.67:8100 check cookie node1
         server node1 172.16.100.67:8100 check cookie node1  
            随后,在HTTP请求报文中可以看到添加的cookie信息,并且一段时间内来自同一cip的请求被调度至了同一台server


10、mode:用在default,frontend,backend,listen;指明haproxy的工作模式
    # mode {tcp | http}
       http:后端LB集群为web server时,应设定mode为http模式,此时支持各种高级分析功能
       tcp:当后端LB集群为mysq等非基于http协议通信的服务时,应使haproxy工作于tcp模式,此时可调度mysql,ldap,ssh,ssl等协议的通信报文


11、forwardfor:在后端web server的日志文件中记录下CIP而非DIP()
 e.g.  option forwardfor  except  127.0.0.1/8
        同时修改后端httpd配置文件中的Logformat中 %h为  %{X-Forwarded-For}i


12、option http-keep-alive
        option http-server-close
前者表示启用与client端通信时的长连接功能,启用此功能时,一般需要同时启用后者,表示允许HAProxy关闭非活动状态的长连接。


13、rspadd <search>    haproxy在给client的响应报文中添加某自定义header;用于listen,backend中
        # rspdel <search>     haproxy在给client的响应报文中查找某hearder并删除
        # rspidel <search>    haproxy在给client的响应报文中基于正则表达式查找某hearder并删除
 e.g.   在响应报文中,一般我们不想让客户端知道后端real server的信息,可用以下指令完成
      rspidel  ^Server:.*     

若要实现复杂的调度能够,如“动静分离”,则需要定于ACL相关变量:

 1、 acl:用在frontend中,定义一条acl匹配规则 
# acl <aclname> <criterion> [flags] [operator] <value> ...
           criterion:acl匹配检查规则
                四层
                    dst IP  
                    dst_port PORT
                    src  IP
                    src_port  PORT
                七层
                    method <http_method>:指明http报文中的请求方法

                    path:URI精确匹配
                    path_beg:URI开头匹配
                    path_end:URI结尾匹配
                    path_reg:URI正则表达式匹配

                    url:URL精确匹配
                    url_beg:URL开头匹配
                    url_end:URL结尾匹配
                    url_end:URL正则表达式匹配

                    hdr <name><value>:请求报文中某个header值的精确匹配
                    hdr_beg <name><value>:请求报文中某个header值的开头匹配
                    hdr_end <name><value>:请求报文中某个header值的结尾匹配

          flags:   -i   表示匹配检查时忽略字符大小写

          value:匹配检查的对象


2、use_backend:用于frontend中,表示当满足某个acl时,调用指定的backend <name>
# use_backend <backend> [if | unless <acl_name>]



3、default_backend:用于frontend中,指明默认将请求调度给哪个backend <name>
# deault_backend <backend>



4、block:用于frontend中,符合acl规则时,阻止访问请求
# block if | unless <acl_name>

HAP生产配置环境案例

1、启用HAProxy内置管理页面

  listen stats  *:9001         定义访问管理页面的IP:PORT
      stats  enable                         启用此功能
      stats  uri  /haproxyadmin          定义访问的URI
      stats  realm  "ADMIN AREA"             页面提示信息,要求用户登录后访问
      stats  auth  admin:123456abc         设定登录用户的账号密码
      stats  admin  if TRUE             如果登录成功,在此页面开启管理接口权限(默认只能查看运行状态统计信息)

2、HAProxy实现模拟实现四层调度

  listen MySQLsrvs
      bind *:20002
      balance leastconn          使用最少连接调度算法
      mode tcp                   定义为四层调度
      server sqlnode1 172.16.100.67:3306 check
      server sqlnode2 172.16.100.68:3306 check

3、配置一个能够实现动静分离的调度服务器:

frontend dirctor
    bind *:80,*:8080
    acl picreq path_end -i .jpg .jepg .bmp
    acl phpreq path_end -i .php
    acl putreq method put
    acl stop src 222.222.222.0/24

    use_backend picsrvs if picreq
    use_backend phpsrvs if phpreq
    use_backend putnode if putreq
    default_backend stasrvs
    block if stop

backend picsrvs
    balance roundrobin
    server picnode1 172.16.100.67:8100 check weight 1 maxconn 2000
    server picnode2 172.16.100.77:8100 check weight 2 maxconn 2000

backend phpsrvs
    balance roundrobin
    cookie PHP insert indirect nocache
    server phpnode1 172.16.100.68:8100 check maxconn 300 cookie phpnode1
    server phpnode2 172.16.100.78:8100 check maxconn 300 cookie phpnode2

backend putnode
    balance static-rr
    server node 172.16.100.69:8100 check

backend stasrvs
    balance roundrobin
    server httpnode1 172.16.100.70:8100 check maxconn 2000 weight 1
    server httpnode2 172.16.100.80:8100 check maxconn 2000 weight 2