35.第29章 HAProxy负载均衡

一.HAProxy调度算法

1.静态算法

静态算法:按照事先定义好的规则轮询公平调度,不关⼼后端服务器的当前负载、链接数和响应速度等,且⽆法实时修改权重,只能靠重启HAProxy⽣效。

1.1 static-rr

static-rr:基于权重的轮询调度,不⽀持权重的运⾏时调整及后端服务器慢启动,其后端主机数量没有限制

1.2 first

first:根据服务器在列表中的位置,⾃上⽽下进⾏调度,但是其只会当第⼀台服务器的连接数达到上限,新请求才会分配给下⼀台服务,因此会忽略服务器的权重设置。

2.动态算法

动态算法:基于后端服务器 状态进⾏调度适当调整,⽐如优先调度⾄当前负载较低的服务器,且权重可以在haproxy运⾏时动态调整⽆需重启。

2.1 roundrobin

roundrobin:基于权重的轮询动态调度算法,⽀持权重的运⾏时调整,不完全等于lvs中的rr轮训模式,HAProxy中的roundrobin⽀持慢启动(新加的服务器会逐渐增加转发数),其每个后端backend中最多⽀持4095个real server,roundrobin为默认调度算法,且⽀持对real server权重动态调整。

2.2 leastconn

leastconn加权的最少连接的动态,⽀持权重的运⾏时调整和慢启动,即当前后端服务器连接最少的优先调度(新客户端连接),⽐较适合⻓连接的场景使⽤,⽐如MySQL等场景。

3.其他算法

其他部分算法即可作为静态算法,⼜可以通过选项成为动态算法

3.1 source

源地址hash,基于⽤户源地址hash并将请求转发到后端服务器,默认为静态即取模⽅式,但是可以通过hash-type⽀持的选项更改,后续同⼀个源地址请求将被转发⾄同⼀个后端web服务器,⽐较适⽤于session保持/缓存业务等场景。
源地址有两种转发客户端请求到后端服务器的服务器选取计算⽅式,分别是取模法和⼀致性hash

3.1.1 map-base取模法

map-based:取模法,基于服务器总权重的hash数组取模,该hash是静态的即不⽀持在线调整权重,不⽀持慢启动,其对后端服务器调度均衡,缺点是当服务器的总权重发⽣变化时,即有服务器上线或下线,都会因权重发⽣变化⽽导致调度结果整体改变。
所谓取模运算,就是计算两个数相除之后的余数,10%7=3,7%4=3,基于权重取模:(2^32-1)%(1+1+2),公式为,hash(o)mod n,即a mod b=c,表明a除以b余数为c。

3.1.2 ⼀致性hash

⼀致性哈希,该hash是动态的,⽀持在线调整权重,⽀持慢启动,优点在于当服务器的总权重发⽣变化时,对调度结果影响是局部的,不会引起⼤的变动。

3.2 uri

基于对⽤户请求的uri做hash并将请求转发到后端指定服务器,也可以通过map-based和consistent定义使⽤取模法还是⼀致性hash。

3.3 url_param

url_param对⽤户请求的url中的 params 部分中的参数name作hash计算,并由服务器总权重相除以后派发⾄某挑出的服务器;通常⽤于追踪⽤户,以确保来⾃同⼀个⽤户的请求始终发往同⼀个real server

3.4 hdr

针对⽤户每个http头部(header)请求中的指定信息做hash,此处由name 指定的http⾸部将会被取出并做hash计算,然后由服务器总权重相除以后派发⾄某挑出的服务器,假如⽆有效的值,则会使⽤默认的轮询调度。

3.5 rdp-cookie

rdp-cookie使⽤客户端cookie保持会话,可以实现对windows远程桌⾯的负载等

3.6 random

在1.9版本开始增加⼀个叫做random的负载平衡算法,其基于⼀个随机数作为⼀致性hash的key,随机负载平衡对于⼤型服务器场或经常添加或删除服务器⾮常有⽤。

算法总结:

static-rr--------->tcp/http 静态
first------------->tcp/http 静态
roundrobin-------->tcp/http 动态
leastconn--------->tcp/http 动态
random------------>tcp/http 动态
source------------>tcp/http
Uri--------------->http
url_param--------->http 取决于hash_type是否
consistent
hdr--------------->http
rdp-cookie-------->tcp

各算法使⽤场景:

first #使⽤较少

static-rr #做了session共享的web集群
roundrobin
random

leastconn #数据库
source #基于客户端公⽹IP的会话保持

Uri--------------->http #缓存服务器,CDN服务商,蓝汛、百度、阿⾥云、腾讯
url_param--------->http

hdr #基于客户端请求报⽂头部做下⼀步处理

rdp-cookie #很少使⽤

二.HAProxy一键编译安装

[root@centos7 ~]# cat install_haproxy.sh
#!/bin/bash
#
#******************************************************************************
#Author:        zhanghui
#QQ:            19661891
#Date:          2021-09-03
#FileName:      install_haproxy.sh
#URL:           www.cnblogs.com/neteagles
#Description:   install_haproxy for centos 7/8 & ubuntu 18.04/20.04
#Copyright (C): 2021 All rights reserved
#******************************************************************************
SRC_DIR=/usr/local/src
COLOR="echo -e \\033[01;31m"
END='\033[0m'
CPUS=`lscpu |awk '/^CPU\(s\)/{print $2}'`

LUA_FILE=lua-5.4.3.tar.gz
HAPROXY_FILE=haproxy-2.4.3.tar.gz
HAPROXY_INSTALL_DIR=/apps/haproxy

STATS_AUTH_USER=admin
STATS_AUTH_PASSWORD=123456

NET_NAME=`ip a |awk -F"[: ]" '/^2/{print $3}'`
IP=`ip addr show ${NET_NAME}| awk -F" +|/" '/global/{print $3}'`

os(){
    if grep -Eqi "CentOS" /etc/issue || grep -Eq "CentOS" /etc/*-release;then
        rpm -q redhat-lsb-core &> /dev/null || { ${COLOR}"安装lsb_release工具"${END};yum -y install  redhat-lsb-core &> /dev/null; }
    fi
    OS_ID=`lsb_release -is`
}

check_file (){
    cd ${SRC_DIR}
    ${COLOR}'检查HAPROXY相关源码包'${END}
    if [ ! -e ${LUA_FILE} ];then
        ${COLOR}"缺少${LUA_FILE}文件"${END}
        exit
    elif [ ! -e ${HAPROXY_FILE} ];then
        ${COLOR}"缺少${HAPROXY_FILE}文件"${END}
        exit
    else
        ${COLOR}"相关文件已准备好"${END}
    fi
}

install_haproxy(){
    [ -d ${HAPROXY_INSTALL_DIR} ] && { ${COLOR}"haproxy已存在,安装失败"${END};exit; }
    ${COLOR}"开始安装HAPROXY"${END}
    ${COLOR}"开始安装HAPROXY依赖包"${END}
    if [ ${OS_ID} == "CentOS" ] &> /dev/null;then
        yum -y install gcc make gcc-c++ glibc glibc-devel pcre pcre-devel openssl openssl-devel systemd-devel libtermcap-devel ncurses-devel libevent-devel readline-devel &> /dev/null
    else
        apt update &> /dev/null;apt -y install gcc make openssl libssl-dev libpcre3 libpcre3-dev zlib1g-dev  libreadline-dev libsystemd-dev &> /dev/null
    fi
    tar xf ${LUA_FILE}
    LUA_DIR=`echo ${LUA_FILE} | sed -nr 's/^(.*[0-9]).*/\1/p'`
    cd ${LUA_DIR}
    make all test
    cd ${SRC_DIR}
    tar xf ${HAPROXY_FILE}
    HAPROXY_DIR=`echo ${HAPROXY_FILE} | sed -nr 's/^(.*[0-9]).*/\1/p'`
    cd ${HAPROXY_DIR}
    make -j ${CPUS} ARCH=x86_64 TARGET=linux-glibc USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 USE_SYSTEMD=1 USE_CPU_AFFINITY=1 USE_LUA=1 LUA_INC=/usr/local/src/${LUA_DIR}/src/ LUA_LIB=/usr/local/src/${LUA_DIR}/src/ PREFIX=${HAPROXY_INSTALL_DIR}
    make install PREFIX=${HAPROXY_INSTALL_DIR}
    [ $? -eq 0 ] && $COLOR"HAPROXY编译安装成功"$END ||  { $COLOR"HAPROXY编译安装失败,退出!"$END;exit; }
    cat > /lib/systemd/system/haproxy.service <<-EOF
[Unit]
Description=HAProxy Load Balancer
After=syslog.target network.target

[Service]
ExecStartPre=/usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -c -q
ExecStart=/usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /var/lib/haproxy/haproxy.pid
ExecReload=/bin/kill -USR2 $MAINPID

[Install]
WantedBy=multi-user.target
EOF
    [ -L /usr/sbin/haproxy ] || ln -s ../../apps/haproxy/sbin/haproxy /usr/sbin/ &> /dev/null
    [ -d /etc/haproxy ] || mkdir /etc/haproxy &> /dev/null  
    [ -d /var/lib/haproxy/ ] || mkdir -p /var/lib/haproxy/ &> /dev/null
    cat > /etc/haproxy/haproxy.cfg <<-EOF
global
maxconn 100000
chroot /apps/haproxy
stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin
uid 99
gid 99
daemon
#nbproc 4
#cpu-map 1 0
#cpu-map 2 1
#cpu-map 3 2
#cpu-map 4 3
pidfile /var/lib/haproxy/haproxy.pid
log 127.0.0.1 local3 info

defaults
option http-keep-alive
option forwardfor
maxconn 100000
mode http
timeout connect 300000ms
timeout client 300000ms
timeout server 300000ms

listen stats
    mode http
    bind 0.0.0.0:9999
    stats enable
    log global
    stats uri /haproxy-status
    stats auth ${STATS_AUTH_USER}:${STATS_AUTH_PASSWORD}
EOF
    echo "PATH=${HAPROXY_INSTALL_DIR}/sbin:${PATH}" > /etc/profile.d/haproxy.sh
    systemctl daemon-reload
    systemctl enable --now haproxy &> /dev/null
    systemctl is-active haproxy &> /dev/null ||  { ${COLOR}"HAPROXY 启动失败,退出!"${END} ; exit; }
    ${COLOR}"HAPROXY安装完成"${END} && ${COLOR}"HAPROXY状态页地址: http://${IP}:9999/haproxy-status,用户名:admin,密码:123456"${END}
}

main(){
    os
    check_file
    install_haproxy
}

main
posted @ 2021-04-07 15:43  网络之鹰  阅读(800)  评论(0编辑  收藏  举报