【高性能群集部署技术】HAProxy

HAProxy

HAProxy概述

定义
HAProxy是一种提供高可用性、负载均衡以及基于TCP和HTTP应用的代理解决方案。它是免费、快速且可靠的,尤其适用于并发量大的web站点,这些站点通常还需要会话保持或七层处理。
运行模式
HAProxy的运行模式使其能够简单且安全地整合到当前的架构中,同时保护web服务器不被直接暴露在网络上。

HAProxy的主要特性

  1. 可靠性和稳定性:与硬件级的F5负载均衡设备相媲美。
  2. 并发处理能力:最高可同时维护40000-50000个并发连接,单位时间内处理的最大请求数为20000个,最大处理能力可达10Git/s。
  3. 负载均衡算法:支持多达8种负载均衡算法。
  4. 会话保持:支持Session会话保持和Cookie的引导。
  5. 健康检查:支持通过获取指定的URL来检测后端服务器的状态。
  6. 虚机主机功能:实现web负载均衡更加灵活。
  7. 独特功能:支持连接拒绝、全透明代理等。
  8. ACL支持:用于访问控制,功能强大。
  9. 协议支持:支持TCP和HTTP协议的负载均衡转发。
  10. 客户端keepalive功能:减少客户端与HAProxy的多次三次握手,让多个请求在一个TCP连接中完成。

HAProxy负载均衡策略

  1. roundrobin:简单的轮询。
  2. static-rr:根据权重进行分配。
  3. leastconn:最少连接者先处理。
  4. source:根据请求源IP进行分配。
  5. uri:根据请求的URI进行分配,常用于CDN。
  6. url_param:根据请求的URL参数进行分配。
  7. hdr(name):根据HTTP请求头来锁定每一次HTTP请求。
  8. rdp-cookie(name):根据cookie(name)来锁定并哈希每一次TCP请求。

LVS、Nginx、Haproxy的区别

负载均衡转发性能
  • 硬件负载均衡 F5 > LVS > Haproxy > Nginx
支持的代理类型
  • LVS
    • 基于Linux内核实现的软负载均衡。
    • 只支持四层代理转发。
    • 不支持正则表达式处理。
    • 不能做动静分离。
  • Nginx & Haproxy
    • 基于应用层实现的软负载均衡。
    • 支持四层和七层代理转发。
    • 支持正则表达式处理。
    • 能做动静分离。
配置维护
  • LVS

    • 实施配置复杂。
    • 维护成本相对较高。
  • Nginx & Haproxy

    • 配置简单。
    • 维护成本较低。
健康检查
  • LVS
    • 可以配合Keepalived实现高可用。
    • 支持TCP端口或HTTP URL方式的健康检查。
  • Nginx
    • 默认只支持被动方式的健康检查。
    • 主动健康检查需要安装第三方模块(nginx_upstream_check_module)。
  • Haproxy
    • 默认支持主动的TCP端口、HTTP URL等方式的健康检查。

Haproxy的8种调度算法

  1. roundrobin:轮询
  2. static-rr:加权轮询
  3. leastconn:最少连接
  4. source:根据源地址做哈希
  5. uri:根据请求的URI地址做哈希
  6. url_param:根据请求的URL路径里传递的参数做哈希
  7. hdr(NAME):根据请求头的字段做哈希
  8. rdp-cookie(NAME):根据cookie里的字段做哈希

Haproxy的3种会话保持方式

  1. 源地址hash
    balance source
    
  2. 设置cookie
    cookie HA_STICKY_dy insert indirect nocache
    server tomcatsrv1 192.168.80.11:8080 cookie tomcatsrv1
    
  3. 会话粘性表stick-table
    stick-table type ip size 5k expire 1m
    stick on src
    

Haproxy搭建Web群集

环境配置

  • Haproxy服务器:192.168.80.10
  • Nginx服务器1:192.168.80.100
  • Nginx服务器2:192.168.80.101
  • 客户端:192.168.80.200

Haproxy服务器部署

  1. 关闭防火墙并传输软件包

    systemctl stop firewalld
    setenforce 0
    wget http://www.haproxy.org/download/1.7/src/haproxy-1.7.2.tar.gz
    
  2. 安装Haproxy

    yum install -y pcre-devel bzip2-devel gcc gcc-c++ make
    tar zxvf haproxy-1.7.2.tar.gz
    cd haproxy-1.7.2/
    make TARGET=linux2628 ARCH=x86_64
    make install PREFIX=/usr/local/haproxy
    
  3. Haproxy服务器配置

    • 创建用户和目录
      useradd -M -s /sbin/nologin haproxy
      mkdir -p /etc/haproxy
      
    • 安装Haproxy
      yum install -y haproxy
      
    • 配置文件haproxy.cfg
    # 全局配置
    global
     # 将info级别的日志发送到127.0.0.1的local0接口
     log 127.0.0.1 local0 info
     # 将warning级别的日志发送到127.0.0.1的local1接口
     log 127.0.0.1 local1 warning
     # 设置最大连接数为30000
     maxconn 30000
     # 指定haproxy进程号的文件路径
     pidfile /var/run/haproxy.pid
     # 以haproxy用户身份运行haproxy进程
     user haproxy
     # 以haproxy组身份运行haproxy进程
     group haproxy
     # 以守护进程方式运行haproxy
     daemon
     # 在后端服务器数量较多的场景中,增加健康检查的时间间隔随机性,避免所有服务器同时进行健康检查带来的意外问题
     spread-checks 2
    
    # 默认配置
    defaults
     # 使用全局的日志配置
     log global
     # 设置工作模式为http
     mode http
     # 使用keepAlive连接,后端为静态建议使用http-keep-alive,后端为动态应用程序建议使用http-server-close
     option http-keep-alive
     # 记录客户端IP在X-Forwarded-For头域中,haproxy将在发往后端的请求中加上"X-Forwarded-For"首部字段
     option forwardfor
     # 开启httplog,在日志中记录http请求、session信息等
     option httplog
     # 不在日志中记录空连接
     option dontlognull
     # 当某后端down掉使得haproxy无法转发携带cookie的请求到该后端时,将其转发到别的后端上
     option redispatch
     # 当服务器负载很高的时候,自动结束掉当前队列处理比较久的链接
     option abortonclose
     # 设置最大连接数为20000
     maxconn 20000
     # 定义连接后端服务器的失败重连次数,连接失败次数超过此值后会将对应后端服务器标记为不可用
     retries 3
     # 设置http请求超时时间,此为等待客户端发送完整请求的最大时长,用于避免类DoS攻击
     timeout http-request 2s
     # 设置客户端请求在队列中的最大时长
     timeout queue 3s
     # 设置haproxy和服务端建立连接的最大时长,新版本中替代contimeout,该参数向后兼容
     timeout connect 1s
     # 设置和客户端保持空闲连接的超时时长,在高并发下可稍微短一点,可设置为10秒以尽快释放连接,新版本中替代clitimeout
     timeout client 10s
     # 设置和服务端保持空闲连接的超时时长,局域网内建立连接很快,所以尽量设置短一些,特别是高并发时,新版本中替代srvtimeout
     timeout server 2s
     # 设置和客户端保持长连接的最大时长。优先级高于timeout http-request 也高于timeout client
     timeout http-keep-alive 10s
     # 和后端服务器成功建立连接后到最终完成检查的最大时长(不包括建立连接的时间,只是读取到检查结果的时长)
     timeout check 2s
    
    # 定义前端服务实例
    frontend http-in
     # 绑定监听地址和端口,指定为*或0.0.0.0时,将监听当前系统的所有IPv4地址
     bind *:80
     # 定义此端口上的maxconn
     maxconn 18000
     # 定义ACL,当uri以/static /images开头时,ACL[url_static1]为true
     acl url_static1 path_beg -i /static /images
     # 定义ACL,当uri以.jpg .jpeg .gif .png .html .htm .txt结尾时,ACL[url_static2]为true
     acl url_static2 path_end -i .jpg .jpeg .gif .png .html .htm .txt
     # 当ACL[url_static1]为true时,定向到后端域ms1中
     use_backend ms1 if url_static1
     # 当ACL[url_static2]为true时,定向到后端域ms2中
     use_backend ms2 if url_static2
     # 其他情况时,定向到后端域dynamic_group中
     default_backend dynamic_group
    
    # 定义后端服务实例组ms1
    backend ms1
     # 使用轮询算法
     balance roundrobin
     # 基于http协议来做健康状况检查,只有返回状态码为2xx或3xx的才认为是健康的,其余所有状态码都认为不健康
     option httpchk GET /test.html
     # 定义后端服务器ms1.inst1,IP为192.168.80.100,端口为80,最大连接数为5000,启用健康检查
     server ms1.inst1 192.168.80.100:80 maxconn 5000 check inter 2000 rise 2 fall 3
     # 定义后端服务器ms1.inst2,IP为192.168.80.100,端口为81,最大连接数为5000,启用健康检查
     server ms1.inst2 192.168.80.100:81 maxconn 5000 check
    
    # 定义后端服务实例组ms2
    backend ms2
     # 使用轮询算法
     balance roundrobin
     # 基于http协议来做健康状况检查,只有返回状态码为2xx或3xx的才认为是健康的,其余所有状态码都认为不健康
     option httpchk GET /test.html
     # 定义后端服务器ms2.inst1,IP为192.168.80.101,端口为80,最大连接数为5000,启用健康检查
     server ms2.inst1 192.168.80.101:80 maxconn 5000 check
     # 定义后端服务器ms2.inst2,IP为192.168.80.101,端口为81,最大连接数为5000,启用健康检查
     server ms2.inst2 192.168.80.101:81 maxconn 5000 check
    
    # 定义后端服务实例组dynamic_group
    backend dynamic_group
     # 使用轮询算法
     balance roundrobin
     # 使用http-server-close选项,表示连接建立后,服务器端主动关闭连接
     option http-server-close
     # 在响应中插入名为HA_STICKY_dy的cookie,其值为对应的server定义中指定的值,并根据请求中此cookie的值决定转发至哪个server
     cookie HA_STICKY_dy insert indirect nocache
     # 定义后端服务器appsrv1,IP为192.168.80.100,端口为8080,最大连接数为5000,启用健康检查
     server appsrv1 192.168.80.100:8080 cookie appsrv1 maxconn 5000 check
     # 定义后端服务器appsrv2,IP为192.168.80.101,端口为8080,最大连接数为5000,启用健康检查
     server appsrv2 192.168.80.101:8080 cookie appsrv2 maxconn 5000 check
    
    # 定义监控页面
    listen stats
     # 绑定监听地址和端口
     bind *:1080
     # 启用统计报告监控
     stats enable
     # 设置每30秒更新监控数据
     stats refresh 30s
     # 设置访问监控页面的uri
     stats uri /stats
     # 设置监控页面的认证提示
     stats realm HAProxy\ Stats
     # 设置监控页面的用户名和密码
     stats auth admin:admin
    
  4. 添加Haproxy系统服务

    vim /etc/init.d/haproxy
    #!/bin/bash
    #chkconfig: 2345 90 30
    #description: Haproxy Service Control Script
    
    # 设置相关变量
    PROGDIR=/usr/local/haproxy
    PROGNAME=haproxy
    DAEMON=$PROGDIR/sbin/$PROGNAME
    CONFIG=/etc/haproxy/$PROGNAME.cfg
    PIDFILE=/var/run/$PROGNAME.pid
    DESC="HAProxy daemon"
    SCRIPTNAME=/etc/init.d/$PROGNAME
    # 如果haproxy二进制文件不存在,则优雅退出
    # Gracefully exit if the package has been removed.
    test -x $DAEMON || exit 0
    # 启动函数
    start()
    {
     echo -e "Starting $DESC: $PROGNAME\n"
     $DAEMON -f $CONFIG
     echo "......"
    }
    # 停止函数
    stop()
    {
     echo -e "Stopping $DESC: $PROGNAME\n"
     haproxy_pid="$(cat $PIDFILE)"
     kill $haproxy_pid
     echo "......"
    }
    # 重启函数
    restart()
    {
     echo -e "Restarting $DESC: $PROGNAME\n"
     $DAEMON -f $CONFIG -p $PIDFILE -sf $(cat $PIDFILE)
     echo "......"
    }
    # 根据传入的参数执行相应操作
    case "$1" in
    start)
      start
      ;;
    
    stop)
      stop
      ;;
    
    restart)
       restart
       ;;
     
    *)
       echo "Usage: $SCRIPTNAME {start|stop|restart}"
       exit 1
       ;;
    esac
    
    exit 0
    
    cd /etc/init.d/
    chmod +x haproxy          # 赋予脚本执行权限
    chkconfig --add /etc/init.d/haproxy  # 将脚本添加到系统服务
    ln -s /usr/local/haproxy/sbin/haproxy /usr/sbin/haproxy  # 创建haproxy命令的软链接
    
    haproxy -c -f haproxy.cfg  # 检查haproxy配置文件的语法
    service haproxy start   # 启动haproxy服务
    # 或者使用 /etc/init.d/haproxy start  # 另一种启动haproxy服务的方式
    
    

节点服务器部署

  1. 安装Nginx
    systemctl stop firewalld
    setenforce 0
    yum install -y pcre-devel zlib-devel gcc gcc-c++ make
    useradd -M -s /sbin/nologin nginx
    cd /opt
    tar zxvf nginx-1.12.0.tar.gz -C /opt/
    cd nginx-1.12.0/
    ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx && make && make install
    
  2. 配置Nginx
    • 服务器1
      echo "this is kgc web" > /usr/local/nginx/html/test.html
      
    • 服务器2
      echo "this is benet web" > /usr/local/nginx/html/test.html
      
  3. 启动Nginx
    ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/
    nginx
    

测试Web群集

  • 在客户端浏览器打开http://192.168.80.10/test.html,不断刷新测试负载均衡效果。
  • 访问监控页面http://192.168.80.10:1080/stats,输入用户名密码admin/admin进行验证。

HAProxy日志管理

在生产环境中,为了更好地管理HAProxy的日志,通常会单独定义日志输出,并将不同级别的日志记录到不同的文件中。

方法一

  1. 修改HAProxy配置文件
    编辑 /etc/haproxy/haproxy.cfg 文件,将info和notice级别的日志分别输出到不同的设备文件中。
    global
        log /dev/log local0 info
        log /dev/log local0 notice
        ......
    
  2. 修改rsyslog配置
    为了便于管理,将HAProxy相关的配置独立定义到 /etc/rsyslog.d/haproxy.conf 文件中。
    if ($programname == 'haproxy' and $syslogseverity-text == 'info')
    then -/var/log/haproxy/haproxy-info.log
    &~
    if ($programname == 'haproxy' and $syslogseverity-text == 'notice')
    then -/var/log/haproxy/haproxy-notice.log
    &~
    
    这段配置将HAProxy的info日志记录到 /var/log/haproxy/haproxy-info.log,将notice日志记录到 /var/log/haproxy/haproxy-notice.log&~ 表示当日志写入到日志文件后,rsyslog停止处理这个信息。
  3. 重启服务
    service rsyslog restart
    service haproxy restart
    
  4. 查看日志
    tail -f /var/log/haproxy/haproxy-info.log
    

方法二

  1. 修改HAProxy配置文件
    编辑 /etc/haproxy/haproxy.cfg 文件,将info及以上级别的日志发送到rsyslog的local0接口,将warning及以上级别的日志发送到rsyslog的local1接口。
    global
        ......
        log 127.0.0.1 local0 info
        log 127.0.0.1 local1 warning
        ......
    
    注:在生产环境中,建议将日志级别调整为notice,以减少磁盘空间的占用。
  2. 为rsyslog添加HAProxy日志的配置
    创建 /var/log/haproxy 目录,并编辑 /etc/rsyslog.d/haproxy.conf 文件。
    $ModLoad imudp
    $UDPServerRun 514
    $FileCreateMode 0644
    $FileOwner haproxy
    local0.*     /var/log/haproxy/haproxy.log
    local1.*     /var/log/haproxy/haproxy_warn.log
    
  3. 修改rsyslog的启动参数
    编辑 /etc/sysconfig/rsyslog 文件,添加以下选项。
    SYSLOGD_OPTIONS="-c 2 -r -m 0"
    
  4. 重启服务
    service rsyslog restart
    service haproxy restart
    
  5. 查看日志
    tail -f /var/log/haproxy/haproxy.log
    

使用 Keepalived 实现 HAProxy 高可用

安装 Keepalived

首先,确保在所有需要实现高可用的服务器上安装 Keepalived。

yum install -y keepalived

配置健康检查脚本

创建一个脚本来检查 HAProxy 实例是否正在运行。这个脚本将用于 Keepalived 的健康检查机制。

vim /etc/keepalived/check_haproxy.sh

脚本内容如下:

#!/bin/bash
# 使用 killall -0 检查 haproxy 实例是否存在,性能高于 ps 命令
if ! killall -0 haproxy; then
  systemctl stop keepalived
fi

赋予脚本执行权限:

chmod +x /etc/keepalived/check_haproxy.sh

配置 Keepalived

编辑 Keepalived 的主配置文件 /etc/keepalived/keepalived.conf

vim /etc/keepalived/keepalived.conf

配置文件内容如下:

! Configuration File for keepalived
global_defs {
    router_id LVS_HA1    # 虚拟路由名称
}

# HAProxy 健康检查配置
vrrp_script chk_haproxy {
    script "/etc/keepalived/check_haproxy.sh"    # 指定健康检查脚本
    interval 2                                   # 脚本运行周期(秒)
    weight 2                                     # 每次检查的加权权重值
}

# 虚拟路由配置
vrrp_instance VI_1 {
    state MASTER              # 本机实例状态,MASTER/BACKUP
    interface ens33           # 本机网卡名称
    virtual_router_id 51      # 虚拟路由编号,主备机保持一致
    priority 100              # 本机初始权重,备机设置小于主机的值
    advert_int 1              # 争抢虚地址的周期(秒)
    virtual_ipaddress {
        192.168.80.100        # 虚地址IP,主备机保持一致
    }
    track_script {
        chk_haproxy           # 对应的健康检查配置
    }
}
启动 Keepalived

启动 Keepalived 服务以应用配置。

systemctl start keepalived
验证虚拟 IP 地址

使用 ip addr 命令查看虚拟 IP 地址是否已正确绑定到网络接口。

ip addr
故障切换测试

为了验证高可用性配置是否有效,可以停止当前 MASTER 主机的 HAProxy 实例,观察虚拟 IP 地址是否自动切换到备份节点。

service haproxy stop

此时当主节点出现问题时,Keepalived 将自动将虚拟 IP 地址切换到备份节点,确保服务的连续性。

内核优化

编辑 /etc/sysctl.conf 文件以进行内核参数优化,这些参数有助于提高系统的网络性能和稳定性。

# 开启重用。允许将TIME-WAIT sockets重用于新的TCP连接,默认0,表示关闭;
net.ipv4.tcp_tw_reuse = 1

# 用于向外连接的端口范围。缺省情况下很小
net.ipv4.ip_local_port_range = 1024 65535

# SYN队列长度,记录尚未收到客户端确认信息的连接请求的最大值。默认为1024,加大队列长度可容纳更多等待连接的网络连接数。
net.ipv4.tcp_max_syn_backlog = 10240

# 表示系统同时保持TIME_WAIT最大数量,如果超过,TIME_WAIT将立刻被清除并打印警告信息。默认180000,此项参数可控制TIME_WAIT 最大数量
net.ipv4.tcp_max_tw_buckets = 5000

# 系统中最多有多少个TCP套接字不被关联到任何一个用户文件句柄上,如超过,连接将即刻被复位并打印警告信息,这个限制仅是为防止简单的DoS攻击,不能过分依靠它或人为减小这个值,更应该增加这个值(如果增加内存后)
net.ipv4.tcp_max_orphans = 3276800

# 为打开对端的连接,内核需发送个SYN并附带个回应前一个SYN的ACK。即三次握手中的第二次握手。该设置决定内核放弃连接前发SYN+ACK包的数量。
net.ipv4.tcp_synack_retries = 3

# 如web应用中listen函数的backlog默认会给我们内核参数的net.core.somaxconn限制到128,而 nginx 定义的 NGX_LISTEN_BACKLOG 默认511,所以有必要调整这个值。
net.core.somaxconn = 32768

应用更改并重新加载内核参数:

sysctl -p
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值