Haproxy
Haproxy

Haproxy

安装Haproxy

社区版网站:http://www.haproxy.org/
github:https://github.com/haproxy

#ubuntu 打开链接: https://haproxy.debian.net/ ,选择合适的版本  (apt安装版本较老不推荐)
#rhel 官网没有安装包,建议编译安装(yum安装版本较老不推荐)


#解决 lua 环境
Lua 官网:www.lua.org
curl -R -O http://www.lua.org/ftp/lua-5.4.4.tar.gz
tar zxf lua-5.4.4.tar.gz
cd lua-5.4.4
make all test


#编译安装
#!/bin/bash
#
#********************************************************************
#Author:            shuhong
#QQ:                985347841
#Date:              2022-10-21
#FileName:          install_haproxy.sh
#URL:               hhhhh
#Description:       The test script
#Copyright (C):     2022 All rights reserved
#********************************************************************

read -p "请输入haproxy版本(2.6.6):" HAPROXY_VERSION
#HAPROXY_VERSION=2.6.6
HAPROXY_FILE=haproxy-${HAPROXY_VERSION}.tar.gz
#HAPROXY_FILE=haproxy-2.2.12.tar.gz
LUA_VERSION=5.4.4
LUA_FILE=lua-${LUA_VERSION}.tar.gz
#LUA_FILE=lua-5.4.3.tar.gz
HAPROXY_INSTALL_DIR=/apps/haproxy

SRC_DIR=/usr/local/src
CWD=pwd
CPUS=lscpu |awk '/^CPU\(s\)/{print $2}'
LOCAL_IP=$(hostname -I|awk '{print $1}')

STATS_AUTH_USER=admin
STATS_AUTH_PASSWORD=123456

VIP=192.168.10.100
MASTER1=192.168.10.101
MASTER2=192.168.10.102
MASTER3=192.168.10.103

. /etc/os-release

color () {
    RES_COL=60
    MOVE_TO_COL="echo -en \\033[${RES_COL}G"
    SETCOLOR_SUCCESS="echo -en \\033[1;32m"
    SETCOLOR_FAILURE="echo -en \\033[1;31m"
    SETCOLOR_WARNING="echo -en \\033[1;33m"
    SETCOLOR_NORMAL="echo -en \E[0m"
    echo -n "$1" && $MOVE_TO_COL
    echo -n "["
    if [ $2 = "success" -o $2 = "0" ] ;then
        ${SETCOLOR_SUCCESS}
        echo -n $"  OK  "    
    elif [ $2 = "failure" -o $2 = "1"  ] ;then 
        ${SETCOLOR_FAILURE}
        echo -n $"FAILED"
    else
        ${SETCOLOR_WARNING}
        echo -n $"WARNING"
    fi
    ${SETCOLOR_NORMAL}
    echo -n "]"
    echo 
}


check_file (){
    if [ ! -e ${LUA_FILE} ];then
        color "缺少${LUA_FILE}文件!" 1
        exit
    elif [ ! -e ${HAPROXY_FILE} ];then
        color "缺少${HAPROXY_FILE}文件!" 1
        exit
    else
        color "相关文件已准备!" 0
    fi
}

install_packs () {
    if [ $ID = "centos" -o $ID = "rocky" ];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 
    elif [ $ID = "ubuntu" ];then
        apt update 
        apt -y install gcc make openssl libssl-dev libpcre3 libpcre3-dev zlib1g-dev  libreadline-dev libsystemd-dev 
    else
        color "不支持此操作系统!" 1
    fi
    [ $? -eq 0 ] ||  { color '安装软件包失败,退出!' 1; exit; }
}

install_lua () {
    tar xf ${LUA_FILE} -C ${SRC_DIR}
    LUA_DIR=${LUA_FILE%.tar*}
    cd ${SRC_DIR}/${LUA_DIR}
    make all test
}

install_haproxy(){
    cd ${CWD}
    tar xf ${HAPROXY_FILE} -C ${SRC_DIR}
    HAPROXY_DIR=${HAPROXY_FILE%.tar*}
    cd ${SRC_DIR}/${HAPROXY_DIR}
    make -j ${CPUS} ARCH=x86_64 TARGET=linux-glibc  USE_PROMEX=1 USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 USE_SYSTEMD=1 USE_CPU_AFFINITY=1 USE_LUA=1 LUA_INC=${SRC_DIR}/${LUA_DIR}/src/ LUA_LIB=${SRC_DIR}/${LUA_DIR}/src/ PREFIX=${HAPROXY_INSTALL_DIR}
    make install PREFIX=${HAPROXY_INSTALL_DIR}
    [ $? -eq 0 ] && color "HAPROXY编译安装成功" 0 ||  { color "HAPROXY编译安装失败,退出!" 1;exit; }
    [ -L /usr/sbin/haproxy ] || ln -s ${HAPROXY_INSTALL_DIR}/sbin/haproxy /usr/sbin/ 
    [ -d /etc/haproxy ] || mkdir /etc/haproxy 
    [ -d /var/lib/haproxy/ ] || mkdir -p /var/lib/haproxy/ 
    cat > /etc/haproxy/haproxy.cfg <<-EOF
global
maxconn 100000
stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin
uid 99
gid 99
daemon

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}

#listen kubernetes-6443
#    bind ${VIP}:6443
#    mode tcp
#    log global
#    server ${MASTER1} ${MASTER1}:6443 check inter 3000 fall 2 rise 5
#    server ${MASTER2} ${MASTER2}:6443 check inter 3000 fall 2 rise 5
#    server ${MASTER3} ${MASTER2}:6443 check inter 3000 fall 2 rise 5

EOF
    
    groupadd -g 99 haproxy
    useradd -u 99 -g haproxy -d /var/lib/haproxy -M -r -s /sbin/nologin haproxy
}

start_haproxy () {
    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
    systemctl daemon-reload
    systemctl enable --now haproxy 
    systemctl is-active haproxy &> /dev/null && color 'HAPROXY安装完成!' 0 ||  { color 'HAPROXY 启动失败,退出!' 1; exit; }
    echo "-------------------------------------------------------------------"
    echo -e "请访问链接: \E[32;1mhttp://${LOCAL_IP}:9999/haproxy-status\E[0m"
    echo -e "用户和密码: \E[32;1m${STATS_AUTH_USER}/${STATS_AUTH_PASSWORD}\E[0m" 
}

check_file
install_packs
install_lua
install_haproxy
start_haproxy

基础配置

Global 配置参数说明:

官方文档:http://cbonte.github.io/haproxy-dconv/2.6/configuration.html#3

chroot #锁定运行目录
deamon #以守护进程运行
stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin process 1
#socket文件,并可以通过此文件管理
user, group, uid, gid #运行haproxy的用户身份
#nbproc n #开启的haproxy worker 进程数,默认进程数是一个, nbproc从HAProxy2.5开始不再支持
nbthread 1 #和多进程 nbproc配置互斥(版本有关,CentOS8的haproxy1.8无此问题),指定每个haproxy进程开启的线程数,默认为每个进程一个线程
#如果同时启用nbproc和nbthread 会出现以下日志的错误,无法启动服务
Apr 7 14:46:23 haproxy haproxy: [ALERT] 097/144623 (1454) : config : cannot enable multiple processes if multiple threads are configured. Please use eithernbproc or nbthread but not both.

#cpu-map 1 0 #绑定haproxy worker 进程至指定CPU,将第1个worker进程绑定至0号CPU
#cpu-map 2 1 #绑定haproxy worker 进程至指定CPU,将第2个worker进程绑定至1号CPU

cpu-map auto:1/1-8 0-7 #haproxy2.4中启用nbthreads,在global配置中添加此选项,可以进行线程和CPU的绑定,nbproc选项2.5版本中将会删除,每个进程中1-8个线程分别绑定0-7号CPU

maxconn n #每个haproxy进程的最大并发连接数
maxsslconn n #每个haproxy进程ssl最大连接数,用于haproxy配置了证书的场景下
maxconnrate n #每个进程每秒创建的最大连接数量
spread-checks n #后端server状态check随机提前或延迟百分比时间,建议2-5(20%-50%)之间,默认值0

pidfile #指定pid文件路径
log 127.0.0.1 local2 info #定义全局的syslog服务器;日志服务器需要开启UDP协议,最多可以定义两个

HAProxy日志配置

#在global配置项定义:
log 127.0.0.1 local{1-7} info #基于syslog记录日志到指定设备,级别有(err、warning、
info、debug)
listen web_port
bind 127.0.0.1:80
mode http
log global #开启当前web_port的日志功能,默认不记录日志
server web1 127.0.0.1:8080 check inter 3000 fall 2 rise 5
# systemctl restart haproxy

Rsyslog配置

[root@haproxy ~]#vim /etc/rsyslog.conf 
module(load="imudp")
input(type="imudp" port="514")
[root@haproxy ~]#vim /etc/rsyslog.d/50-default.conf 
local3.* /var/log/haproxy.log

[root@haproxy ~]#systemctl restart rsyslog.service 

[root@haproxy ~]#tail -f /var/log/haproxy.log 
Oct 24 20:45:43 localhost haproxy[9993]: Connect from 172.20.0.3:57687 to 172.20.0.230:9999 (stats/HTTP)

Proxies 配置

官方文档:http://cbonte.github.io/haproxy-dconv/2.6/configuration.html#4

defaults [<name>] #默认配置项,针对以下的frontend、backend和listen生效,可以多个name也可以没有name
frontend <name> #前端servername,类似于Nginx的一个虚拟主机 server和LVS服务集群。
backend <name> #后端服务器组,等于nginx的upstream和LVS中的RS服务器
listen <name> #将frontend和backend合并在一起配置,相对于frontend和backend配置更简洁,生产常用

注意:name字段只能使用大小写字母,数字,‘-’(dash),'_‘(underscore),'.' (dot)和 ':'(colon),并且严格区分大小写

defaults配置参数:
option redispatch #当server Id对应的服务器挂掉后,强制定向到其他健康的服务器,重新派发
option abortonclose #当服务器负载很高时,自动结束掉当前队列处理比较久的连接,针对业务情况选择开启
option http-keep-alive #开启与客户端的会话保持
option forwardfor #透传客户端真实IP至后端web服务器
mode http|tcp #设置默认工作类型,使用TCP服务器性能更好,减少压力
timeout http-keep-alive 120s #session 会话保持超时时间,此时间段内会转发到相同的后端服务器
timeout connect 120s #客户端请求从haproxy到后端server最长连接等待时间(TCP连接之前),默认单位ms
timeout server 600s #客户端请求从haproxy到后端服务端的请求处理超时时长(TCP连接之后),默认单位ms,如果超时,会出现502错误,此值建议设置较大些,防止出现502错误
timeout client 600s #设置haproxy与客户端的最长非活动时间,默认单位ms,建议和timeoutserver相同
timeout check 5s #对后端服务器的默认检测超时时间
default-server inter 1000 weight 3 #指定后端服务器的默认设置

#listen配置参数:
#官网业务访问入口
listen WEB_PORT_80
bind 192.168.10.100:80
mode http
option forwardfor
server web1 10.0.0.17:8080 check inter 3000 fall 3 rise 5
server web2 10.0.0.27:8080 check inter 3000 fall 3 rise 5
#检查语法
[root@ubuntu2004 ~]#haproxy -c -f /etc/haproxy/haproxy.cfg
Configuration file is valid

#frontend配置参数:
bind: #指定HAProxy的监听地址,可以是IPV4或IPV6,可以同时监听多个IP或端口,可同时用于
listen字段中
#格式:
bind [<address>]:<port_range> [, ...] [param*]
#注意:如果需要绑定在非本机的IP,需要开启内核参数:net.ipv4.ip_nonlocal_bind=1
backlog <backlog> #针对所有server配置,当前端服务器的连接数达到上限后的后援队列长度,注意:不支持backend

#backend配置参数:
mode http|tcp #指定负载协议类型,和对应的frontend必须一致
option #配置选项
server #定义后端real server,必须指定IP和端口

server 配置:
#针对一个server配置
check #对指定real进行健康状态检查,如果不加此设置,默认不开启检查,只有check后面没有其它配置也可以启用检查功能
#默认对相应的后端服务器IP和端口,利用TCP连接进行周期性健康性检查,注意必须指定端口才能实现健康性检查
addr <IP> #可指定的健康状态监测IP,可以是专门的数据网段,减少业务网络的流量
port <num> #指定的健康状态监测端口
inter <num> #健康状态检查间隔时间,默认2000 ms
fall <num> #后端服务器从线上转为线下的检查的连续失效次数,默认为3
rise <num> #后端服务器从下线恢复上线的检查的连续有效次数,默认为2
weight <weight> #默认为1,最大值为256,0(状态为蓝色)表示不参与负载均衡,但仍接受持久连接
backup #将后端服务器标记为备份状态,只在所有非备份主机down机时提供服务,类似Sorry Server
disabled #将后端服务器标记为不可用状态,即维护状态,除了持久模式,将不再接受连接,状态为深黄色,优雅下线,不再接受新用户的请求
maxconn <maxconn> #当前后端server的最大并发连接数,放在,放在server 指令后面
redir http://www.baidu.com #将请求临时(302)重定向至其它URL,只适用于http模式,放在server 指令后面

redirect 配置:
#注意:此指令和redir功能相似,但不属于server指令后面,是独立存放在listen,frontend,backend语句块
redirect prefix http://www.baidu.com/ #将请求临时(302)重定向至其它URL,只适用于http模式

使用子配置文件保存配置

[root@haproxy ~]#mkdir /etc/haproxy/conf.d/

[root@haproxy ~]#vim /lib/systemd/system/haproxy.service 
[Unit]
Description=HAProxy Load Balancer
After=syslog.target network.target

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

[Install]
WantedBy=multi-user.target

[root@haproxy ~]#systemctl daemon-reload 
[root@haproxy ~]#systemctl restart haproxy.service 

调度算法

官方文档:http://cbonte.github.io/haproxy-dconv/2.6/configuration.html#4-balance

Socat 工具

[root@haproxy ~]#apt -y install socat
[root@centos ~]#yum -y install socat

[root@haproxy ~]#socat -h
[root@haproxy ~]#echo "help" | socat stdio /var/lib/haproxy/haproxy.sock
The following commands are valid at this level:
  abort ssl ca-file <cafile>              : abort a transaction for a CA file
  abort ssl cert <certfile>               : abort a transaction for a certificate file
  abort ssl crl-file <crlfile>            : abort a transaction for a CRL file
  add acl [@<ver>] <acl> <pattern>        : add an acl entry
  add map [@<ver>] <map> <key> <val>      : add a map entry (payload supported instead of key/val)
  add server <bk>/<srv>                   : create a new server
  add ssl crt-list <list> <cert> [opts]*  : add to crt-list file <list> a line <cert> or a payload
  clear acl [@<ver>] <acl>                : clear the contents of this acl
  clear counters [all]                    : clear max statistics counters (or all counters)
  clear map [@<ver>] <map>                : clear the contents of this map
  clear table <table> [<filter>]*         : remove an entry from a table (filter: data/key)
  commit acl @<ver> <acl>                 : commit the ACL at this version
  commit map @<ver> <map>                 : commit the map at this version
  commit ssl ca-file <cafile>             : commit a CA file
  commit ssl cert <certfile>              : commit a certificate file
  commit ssl crl-file <crlfile>           : commit a CRL file
  del acl <acl> [<key>|#<ref>]            : delete acl entries matching <key>
  del map <map> [<key>|#<ref>]            : delete map entries matching <key>
  del server <bk>/<srv>                   : remove a dynamically added server
  del ssl ca-file <cafile>                : delete an unused CA file
  del ssl cert <certfile>                 : delete an unused certificate file
  del ssl crl-file <crlfile>              : delete an unused CRL file
  del ssl crt-list <list> <cert[:line]>   : delete a line <cert> from crt-list file <list>
  disable agent                           : disable agent checks
  disable dynamic-cookie backend <bk>     : disable dynamic cookies on a specific backend
  disable frontend <frontend>             : temporarily disable specific frontend
  disable health                          : disable health checks
  disable server (DEPRECATED)             : disable a server for maintenance (use 'set server' instead)
  enable agent                            : enable agent checks
  enable dynamic-cookie backend <bk>      : enable dynamic cookies on a specific backend
  enable frontend <frontend>              : re-enable specific frontend
  enable health                           : enable health checks
  enable server  (DEPRECATED)             : enable a disabled server (use 'set server' instead)
  get acl <acl> <value>                   : report the patterns matching a sample for an ACL
  get map <acl> <value>                   : report the keys and values matching a sample for a map
  get var <name>                          : retrieve contents of a process-wide variable
  get weight <bk>/<srv>                   : report a server's current weight
  new ssl ca-file <cafile>                : create a new CA file to be used in a crt-list
  new ssl cert <certfile>                 : create a new certificate file to be used in a crt-list or a directory
  new ssl crlfile <crlfile>               : create a new CRL file to be used in a crt-list
  operator                                : lower the level of the current CLI session to operator
  prepare acl <acl>                       : prepare a new version for atomic ACL replacement
  prepare map <acl>                       : prepare a new version for atomic map replacement
  set dynamic-cookie-key backend <bk> <k> : change a backend secret key for dynamic cookies
  set map <map> [<key>|#<ref>] <value>    : modify a map entry
  set maxconn frontend <frontend> <value> : change a frontend's maxconn setting
  set maxconn global <value>              : change the per-process maxconn setting
  set maxconn server <bk>/<srv>           : change a server's maxconn setting
  set profiling <what> {auto|on|off}      : enable/disable resource profiling (tasks,memory)
  set rate-limit <setting> <value>        : change a rate limiting value
  set server <bk>/<srv> [opts]            : change a server's state, weight, address or ssl
  set severity-output [none|number|string]: set presence of severity level in feedback information
  set ssl ca-file <cafile> <payload>      : replace a CA file
  set ssl cert <certfile> <payload>       : replace a certificate file
  set ssl crl-file <crlfile> <payload>    : replace a CRL file
  set ssl ocsp-response <resp|payload>    : update a certificate's OCSP Response from a base64-encode DER
  set ssl tls-key [id|file] <key>         : set the next TLS key for the <id> or <file> listener to <key>
  set table <table> key <k> [data.* <v>]* : update or create a table entry's data
  set timeout [cli] <delay>               : change a timeout setting
  set weight <bk>/<srv>  (DEPRECATED)     : change a server's weight (use 'set server' instead)
  show acl [@<ver>] <acl>]                : report available acls or dump an acl's contents
  show activity                           : show per-thread activity stats (for support/developers)
  show backend                            : list backends in the current running config
  show cache                              : show cache status
  show cli level                          : display the level of the current CLI session
  show cli sockets                        : dump list of cli sockets
  show env [var]                          : dump environment variables known to the process
  show errors [<px>] [request|response]   : report last request and/or response errors for each proxy
  show events [<sink>] [-w] [-n]          : show event sink state
  show fd [num]                           : dump list of file descriptors in use or a specific one
  show info [desc|json|typed|float]*      : report information about the running process
  show libs                               : show loaded object files and libraries
  show map [@ver] [map]                   : report available maps or dump a map's contents
  show peers [dict|-] [section]           : dump some information about all the peers or this peers section
  show pools                              : report information about the memory pools usage
  show profiling [<what>|<#lines>|byaddr]*: show profiling state (all,status,tasks,memory)
  show resolvers [id]                     : dumps counters from all resolvers section and associated name servers
  show schema json                        : report schema used for stats
  show servers conn [<backend>]           : dump server connections status (all or for a single backend)
  show servers state [<backend>]          : dump volatile server information (all or for a single backend)
  show sess [id]                          : report the list of current sessions or dump this exact session
  show ssl ca-file [<cafile>[:<index>]]   : display the SSL CA files used in memory, or the details of a <cafile>, or a single certificate of index <index> of a CA file <cafile>
  show ssl cert [<certfile>]              : display the SSL certificates used in memory, or the details of a file
  show ssl crl-file [<crlfile[:<index>>]] : display the SSL CRL files used in memory, or the details of a <crlfile>, or a single CRL of index <index> of CRL file <crlfile>
  show ssl crt-list [-n] [<list>]         : show the list of crt-lists or the content of a crt-list file <list>
  show ssl ocsp-response [id]             : display the IDs of the OCSP responses used in memory, or the details of a single OCSP response
  show startup-logs                       : report logs emitted during HAProxy startup
  show stat [desc|json|no-maint|typed|up]*: report counters for each proxy and server
  show table <table> [<filter>]*          : report table usage stats or dump this table's contents (filter: data/key)
  show tasks                              : show running tasks
  show threads                            : show some threads debugging information
  show tls-keys [id|*]                    : show tls keys references or dump tls ticket keys when id specified
  show trace [<module>]                   : show live tracing state
  show version                            : show version of the current process
  shutdown frontend <frontend>            : stop a specific frontend
  shutdown session [id]                   : kill a specific session
  shutdown sessions server <bk>/<srv>     : kill sessions on a server
  trace [<module>|0] [cmd [args...]]      : manage live tracing (empty to list, 0 to stop all)
  user                                    : lower the level of the current CLI session to user
  help [<command>]                        : list matching or all commands
  prompt                                  : toggle interactive mode with prompt
  quit                                    : disconnect

[root@haproxy ~]#echo "show info" | socat stdio /var/lib/haproxy/haproxy.sock
Name: HAProxy
Version: 2.6.6-274d1a4
Release_date: 2022/09/22
Nbthread: 2
Nbproc: 1
Process_num: 1
Pid: 12453
Uptime: 0d 0h08m02s
Uptime_sec: 482
Memmax_MB: 0
PoolAlloc_MB: 0
PoolUsed_MB: 0
PoolFailed: 0
Ulimit-n: 200029
Maxsock: 200029
Maxconn: 100000
Hard_maxconn: 100000
CurrConns: 0
CumConns: 2
CumReq: 2
MaxSslConns: 0
CurrSslConns: 0
CumSslConns: 0
Maxpipes: 0
PipesUsed: 0
PipesFree: 0
ConnRate: 0
ConnRateLimit: 0
MaxConnRate: 0
SessRate: 0
SessRateLimit: 0
MaxSessRate: 0
SslRate: 0
SslRateLimit: 0
MaxSslRate: 0
SslFrontendKeyRate: 0
SslFrontendMaxKeyRate: 0
SslFrontendSessionReuse_pct: 0
SslBackendKeyRate: 0
SslBackendMaxKeyRate: 0
SslCacheLookups: 0
SslCacheMisses: 0
CompressBpsIn: 0
CompressBpsOut: 0
CompressBpsRateLim: 0
ZlibMemUsage: 0
MaxZlibMemUsage: 0
Tasks: 12
Run_queue: 0
Idle_pct: 100
node: haproxy
Stopping: 0
Jobs: 4
Unstoppable Jobs: 1
Listeners: 3
ActivePeers: 0
ConnectedPeers: 0
DroppedLogs: 0
BusyPolling: 0
FailedResolutions: 0
TotalBytesOut: 8911
TotalSplicdedBytesOut: 0
BytesOutRate: 0
DebugCommandsIssued: 0
CumRecvLogs: 0
Build info: 2.6.6-274d1a4
Memmax_bytes: 0
PoolAlloc_bytes: 105752
PoolUsed_bytes: 105752
Start_time_sec: 1666616072
Tainted: 0

静态算法

static-rr 算法

static-rr:基于权重的轮询调度,不支持运行时利用socat进行权重的动态调整(只支持0和1,不支持其它值)及后端服务器慢启动,其后端主机数量没有限制,相当于LVS中的 wrr

[root@haproxy conf.d]#vim web.cfg
listen web_site
  bind 172.20.0.230:80
  mode http
  log  global
  balance static-rr
  server web1 10.0.0.206:80 weight 1 check inter 3000 fall 2 rise 5
  server web2 10.0.0.207:80 weight 2 check inter 3000 fall 2 rise 5

[root@haproxy conf.d]#systemctl restart haproxy.service 

#测试
[root@ubuntu2004 ~]#curl 172.20.0.230
10.0.0.207
[root@ubuntu2004 ~]#curl 172.20.0.230
10.0.0.207
[root@ubuntu2004 ~]#curl 172.20.0.230
10.0.0.206
[root@ubuntu2004 ~]#curl 172.20.0.230
10.0.0.207                                   

first 算法

first:根据服务器在列表中的位置,自上而下进行调度,但是其只会当第一台服务器的连接数达到上限,新请求才会分配给下一台服务,因此会忽略服务器的权重设置,此方式使用较少;不支持用socat进行动态修改权重,可以设置0和1,可以设置其它值但无效

[root@haproxy conf.d]#vim web.cfg 
listen web_site
  bind 172.20.0.230:80
  mode http
  log  global
  balance first
  server web1 10.0.0.206:80 maxconn 2 weight 1 check inter 3000 fall 2 rise 5
  server web2 10.0.0.207:80 weight 2 check inter 3000 fall 2 rise 5

[root@haproxy conf.d]#systemctl restart haproxy.service 


#测试
[root@ubuntu2004 ~]#curl 172.20.0.230
10.0.0.206
[root@ubuntu2004 ~]#curl 172.20.0.230
10.0.0.206
[root@ubuntu2004 ~]#curl 172.20.0.230
10.0.0.206
[root@ubuntu2004 ~]#curl 172.20.0.230
10.0.0.206
[root@ubuntu2004 ~]#curl 172.20.0.230
10.0.0.206
[root@ubuntu2004 ~]#wget --limit-rate 1k  172.20.0.230/f1.img
--2022-10-24 21:19:17--  http://172.20.0.230/f1.img
正在连接 172.20.0.230:80... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度: 1073741824 (1.0G) [application/octet-stream]
正在保存至: “f1.img”

f1.img                                    0%[                                                                             ]   4.13K  1024 B/s    剩余 12d 3h
[root@ubuntu2004 ~]#wget --limit-rate 1k  172.20.0.230/f1.img
--2022-10-24 21:20:22--  http://172.20.0.230/f1.img
正在连接 172.20.0.230:80... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度: 1073741824 (1.0G) [application/octet-stream]
正在保存至: “f1.img.1”

f1.img.1                                  0%[                                                                             ]  18.76K  1024 B/s    剩余 12d 3h
[root@ubuntu2004 ~]#curl 172.20.0.230
10.0.0.207
[root@ubuntu2004 ~]#curl 172.20.0.230
10.0.0.207
[root@ubuntu2004 ~]#curl 172.20.0.230
10.0.0.207
[root@ubuntu2004 ~]#curl 172.20.0.230
10.0.0.207
[root@ubuntu2004 ~]#curl 172.20.0.230
10.0.0.207

动态算法

roundrobin 算法(默认算法)

roundrobin:基于权重的轮询动态调度算法,支持权重的运行时调整,不同于lvs中的rr轮训模式,HAProxy中的roundrobin支持慢启动(新加的服务器会逐渐增加转发数),其每个后端backend中最多支持4095个real server,支持对real server权重动态调整,roundrobin为默认调度算法,此算法使用广泛

[root@haproxy conf.d]#vim web.cfg 
listen web_site
  bind 172.20.0.230:80
  mode http
  log  global
  balance roundrobin
  server web1 10.0.0.206:80 weight 1 check inter 3000 fall 2 rise 5
  server web2 10.0.0.207:80 weight 2 check inter 3000 fall 2 rise 5

[root@haproxy conf.d]#systemctl restart haproxy.service 

[root@haproxy conf.d]#echo "get weight web_site/web1" | socat stdio /var/lib/haproxy/haproxy.sock
1 (initial 1)
[root@haproxy conf.d]#echo "set weight web_site/web1 6" | socat stdio /var/lib/haproxy/haproxy.sock

[root@haproxy conf.d]#echo "get weight web_site/web1" | socat stdio /var/lib/haproxy/haproxy.sock
6 (initial 1)

#测试
[root@ubuntu2004 ~]#curl 172.20.0.230
10.0.0.206
[root@ubuntu2004 ~]#curl 172.20.0.230
10.0.0.206
[root@ubuntu2004 ~]#curl 172.20.0.230
10.0.0.206
[root@ubuntu2004 ~]#curl 172.20.0.230
10.0.0.207
[root@ubuntu2004 ~]#curl 172.20.0.230
10.0.0.206

leastconn 算法(不建议使用,容易浪费资源)

leastconn 加权的最少连接的动态,支持权重的运行时调整和慢启动,即根据当前连接最少的后端服务器而非权重进行优先调度(新客户端连接),比较适合长连接的场景使用,比如:MySQL等场景。

[root@haproxy conf.d]#vim web.cfg 
listen web_site
  bind 172.20.0.230:80
  mode http
  log  global
  balance leastconn
  server web1 10.0.0.206:80 weight 1 check inter 3000 fall 2 rise 5
  server web2 10.0.0.207:80 weight 2 check inter 3000 fall 2 rise 5

[root@haproxy conf.d]#systemctl restart haproxy.service 

random 算法

在1.9版本开始增加 random的负载平衡算法,其基于随机数作为一致性hash的key,随机负载平衡对于大型服务器场或经常添加或删除服务器非常有用,支持weight的动态调整,weight较大的主机有更大概率获取新请求

[root@haproxy conf.d]#vim web.cfg 
listen web_site
  bind 172.20.0.230:80
  mode http
  log  global
  balance random
  server web1 10.0.0.206:80 weight 1 check inter 3000 fall 2 rise 5
  server web2 10.0.0.207:80 weight 2 check inter 3000 fall 2 rise 5

[root@haproxy conf.d]#systemctl restart haproxy.service 

其他算法

source 算法

源地址hash,基于用户源地址hash并将请求转发到后端服务器,后续同一个源地址请求将被转发至同一个后端web服务器。此方式当后端服务器数据量发生变化时,会导致很多用户的请求转发至新的后端服务器,默认为静态方式,但是可以通过hash-type选项进行更改

这个算法一般是在不插入Cookie的TCP模式下使用,也可给不支持会话cookie的客户提供会话粘性,适用于需要session会话保持但不支持cookie和缓存的场景

源地址有两种转发客户端请求到后端服务器的服务器选取计算方式,分别是取模法和一致性hash

#map-base 取模法(不支持动态调整权重值,静态)
所谓取模运算,就是计算两个数相除之后的余数,10%7=3, 7%4=3
map-based算法:基于权重取模,hash(source_ip)%所有后端服务器相加的总权重

[root@haproxy conf.d]#vim web.cfg 
listen web_site
  bind 172.20.0.230:80
  mode http
  log  global
  balance source
  hash-type map-based
  server web1 10.0.0.206:80 weight 1 check inter 3000 fall 2 rise 5
  server web2 10.0.0.207:80 weight 2 check inter 3000 fall 2 rise 5

[root@haproxy conf.d]#systemctl restart haproxy.service 

#一致性hash(动态)
1、key1=hash(source_ip)%(2^32) [0---4294967295]
2、keyA=hash(后端服务器虚拟ip)%(2^32)
3、将key1和keyA都放在hash环上,将用户请求调度到离key1最近的keyA对应的后端服务器

[root@haproxy conf.d]#vim web.cfg 
listen web_site
  bind 172.20.0.230:80
  mode http
  log  global
  balance source
  hash-type consistent
  server web1 10.0.0.206:80 weight 1 check inter 3000 fall 2 rise 5
  server web2 10.0.0.207:80 weight 2 check inter 3000 fall 2 rise 5

[root@haproxy conf.d]#systemctl restart haproxy.service 

uri 算法

基于对用户请求的URI的左半部分或整个uri做hash,再将hash结果对总权重进行取模后,根据最终结果将请求转发到后端指定服务器,适用于后端是缓存服务器场景,默认是静态算法,也可以通过hash-type指定map-based和consistent,来定义使用取模法还是一致性hash。

注意:此算法基于应用层,所以只支持 mode http ,不支持 mode tcp

<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>
左半部分:/<path>;<params>
整个uri:/<path>;<params>?<query>#<frag>

[root@haproxy conf.d]#vim web.cfg 
listen web_site
  bind 172.20.0.230:80
  mode http
  log  global
  balance uri
  hash-type consistent
  server web1 10.0.0.206:80 weight 1 check inter 3000 fall 2 rise 5
  server web2 10.0.0.207:80 weight 2 check inter 3000 fall 2 rise 5

[root@haproxy conf.d]#systemctl restart haproxy.service 

url_param 算法

url_param对用户请求的url中的 params 部分中的一个参数key对应的value值作hash计算,并由服务器总权重相除以后派发至某挑出的服务器;通常用于追踪用户,以确保来自同一个用户的请求始终发往同一个real server,如果无没key,将按roundrobin算法

[root@haproxy conf.d]#vim web.cfg 
listen web_site
  bind 172.20.0.230:80
  mode http
  log  global
  balance url_param userid #对url_param的值取hash
  hash-type consistent
  server web1 10.0.0.206:80 weight 1 check inter 3000 fall 2 rise 5
  server web2 10.0.0.207:80 weight 2 check inter 3000 fall 2 rise 5

[root@haproxy conf.d]#systemctl restart haproxy.service 

hdr 算法

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

[root@haproxy conf.d]#vim web.cfg 
listen web_site
  bind 172.20.0.230:80
  mode http
  log  global
  balance hdr(User-Agent)
  hash-type consistent

  server web1 10.0.0.206:80 weight 1 check inter 3000 fall 2 rise 5
  server web2 10.0.0.207:80 weight 2 check inter 3000 fall 2 rise 5

[root@haproxy conf.d]#systemctl restart haproxy.service 

rdp-cookie 算法(windows远程桌面)

rdp-cookie对远windows远程桌面的负载,使用cookie保持会话,默认是静态,也可以通过hash-type指定map-based和consistent,来定义使用取模法还是一致性hash。

[root@haproxy conf.d]#vim web.cfg 
listen web_site
  bind 172.20.0.230:80
  mode http
  log  global
  balance rdp-cookie
  hash-type consistent

  server web1 10.0.0.206:80 weight 1 check inter 3000 fall 2 rise 5
  server web2 10.0.0.207:80 weight 2 check inter 3000 fall 2 rise 5

[root@haproxy conf.d]#systemctl restart haproxy.service

算法总结

#静态
static-rr--------->tcp/http
first------------->tcp/http
#动态
roundrobin-------->tcp/http
leastconn--------->tcp/http
random------------>tcp/http
#以下静态和动态取决于hash_type是否consistent
source------------>tcp/http
Uri--------------->http
url_param--------->http
hdr--------------->http
rdp-cookie-------->tcp
#各种算法使用场景
first #使用较少
static-rr #做了session共享的 web 集群
roundrobin
random
leastconn #数据库
source #基于客户端公网 IP 的会话保持
Uri--------------->http #缓存服务器,CDN服务商,蓝汛、百度、阿里云、腾讯
url_param--------->http #可以实现session保持
hdr #基于客户端请求报文头部做下一步处理
rdp-cookie #基于Windows主机,很少使用

高级功能

基于cookie会话保持

cookie value:为当前server指定cookie值,实现基于cookie的会话黏性,相对于基于 source 地址hash 调度算法对客户端的粒度更精准,但同时也加重了haproxy负载,目前此模式使用较少, 已经被session共享服务器代替
注意:不支持 tcp mode,使用 http mode

配置选项
cookie name [ rewrite | insert | prefix ][ indirect ] [ nocache ][ postonly ] [
preserve ][ httponly ] [ secure ][ domain ]* [ maxidle <idle> ][ maxlife ]
name: #cookie 的 key名称,用于实现持久连接
insert: #插入新的cookie,默认不插入cookie
indirect: #如果客户端已经有cookie,则不会再发送cookie信息
nocache: #当client和hapoxy之间有缓存服务器(如:CDN)时,不允许中间缓存器缓存cookie,因为这会导致很多经过同一个CDN的请求都发送到同一台后端服务器

[root@haproxy conf.d]#vim web.cfg 
listen web_site
  bind 172.20.0.230:80
  mode http
  log  global
  cookie WEBSRV insert nocache indirect
  server web1 10.0.0.206:80 weight 1 check inter 3000 fall 2 rise 5 cookie web01
  server web2 10.0.0.207:80 weight 2 check inter 3000 fall 2 rise 5 cookie web02
[root@haproxy conf.d]#systemctl restart haproxy.service 

Haproxy状态页

stats enable #基于默认的参数启用stats page
stats hide-version #将状态页中haproxy版本隐藏
stats refresh <delay> #设定自动刷新时间间隔,默认不自动刷新,以秒为单位
stats uri <prefix> #自定义stats page uri,默认值:/haproxy?stats
stats realm <realm> #账户认证时的提示信息,示例:stats realm HAProxy\
Statistics
stats auth <user>:<passwd> #认证时的账号和密码,可定义多个用户,每行指定一个用户.默认:no
authentication
stats admin { if | unless } <cond> #启用stats page中的管理功能


listen stats
    mode http
    bind 0.0.0.0:9999
    stats enable
    log global
    stats uri /haproxy-status
    stats auth admin:123456
    stats admin if TRUE

IP穿透

web服务器中需要记录客户端的真实IP地址,用于做访问统计、安全防护、行为分析、区域排行等场景。

Layer 4 与 Layer 7
四层:IP+PORT转发
七层:协议+内容交换

四层负载
在LVS 传统的四层负载设备中,把client发送的报文目标地址(原来是负载均衡设备的IP地址),根据均衡设备设置的选择web服务器的规则选择对应的web服务器IP地址,这样client就可以直接跟此服务器建立TCP连接并发送数据,而四层负载自身不参与建立连接
而和LVS不同,haproxy是伪四层负载均衡,因为haproxy 需要分别和前端客户端及后端服务器建立连接

七层代理
七层负载均衡服务器起了一个反向代理服务器的作用,服务器建立一次TCP连接要三次握手,而client要访问Web Server要先与七层负载设备进行三次握手后建立TCP连接,把要访问的报文信息发送给七层负载均衡;然后七层负载均衡再根据设置的均衡规则选择特定的 Web Server,然后通过三次握手与此台Web Server建立TCP连接,然后Web Server把需要的数据发送给七层负载均衡设备,负载均衡设备再把数据发送给client;所以,七层负载均衡设备起到了代理服务器的作用,七层代理需要和Client和后端服务器分别建立连接

#四层IP透传
[root@haproxy ~]#vim /etc/haproxy/conf.d/web.cfg 
listen web_site
  bind 172.20.0.230:80
  mode http
  log  global
  server web1 10.0.0.206:80 weight 1 send-proxy check inter 3000 fall 2 rise 5
  server web2 10.0.0.207:80 weight 2 send-proxy check inter 3000 fall 2 rise 5
[root@haproxy ~]#systemctl restart haproxy.service 
#在nginx中配置日志
[root@nginx01 nginx]#vim nginx.conf 
    log_format main '$remote_addr - $remote_user [$time_local] "$request" "$proxy_protocol_addr"';
    access_log /var/log/nginx/access.log main;
...
server {
    listen 80 default_server proxy_protocol;
...

#查看nginx日志
[root@nginx01 nginx]#tail -f /var/log/nginx/access.log 
10.0.0.205 - - [25/Oct/2022:09:26:11 +0800] "PROXY TCP4 10.0.0.205 10.0.0.206 50552 80" "-"
10.0.0.205 - - [25/Oct/2022:09:26:14 +0800] "PROXY TCP4 10.0.0.205 10.0.0.206 46416 80" "-"
10.0.0.205 - - [25/Oct/2022:09:26:17 +0800] "PROXY TCP4 10.0.0.205 10.0.0.206 46420 80" "-"
10.0.0.205 - - [25/Oct/2022:09:26:20 +0800] "PROXY TCP4 10.0.0.205 10.0.0.206 46424 80" "-"
10.0.0.205 - - [25/Oct/2022:09:26:23 +0800] "PROXY TCP4 10.0.0.205 10.0.0.206 37848 80" "-"
10.0.0.205 - - [25/Oct/2022:09:26:26 +0800] "PROXY TCP4 10.0.0.205 10.0.0.206 37852 80" "-"
10.0.0.205 - - [25/Oct/2022:09:26:29 +0800] "PROXY TCP4 10.0.0.205 10.0.0.206 37856 80" "-"
10.0.0.205 - - [25/Oct/2022:09:26:58 +0800] "GET / HTTP/1.1" "172.20.0.208"
10.0.0.205 - - [25/Oct/2022:09:26:58 +0800] "GET / HTTP/1.1" "172.20.0.208"
10.0.0.205 - - [25/Oct/2022:09:27:00 +0800] "GET / HTTP/1.1" "172.20.0.208"
10.0.0.205 - - [25/Oct/2022:09:27:57 +0800] "GET / HTTP/1.1" "172.20.0.208"
10.0.0.205 - - [25/Oct/2022:09:27:58 +0800] "GET / HTTP/1.1" "172.20.0.208"
10.0.0.205 - - [25/Oct/2022:09:28:00 +0800] "GET / HTTP/1.1" "172.20.0.208"

#七层穿透
[root@haproxy ~]#vim /etc/haproxy/haproxy.cfg 
defaults
option forwardfor  #此为默认值,首部字段默认为:X-Forwarded-For
[root@haproxy ~]#vim /etc/haproxy/conf.d/web.cfg 
listen web_site
  bind 172.20.0.230:80
  mode http
  log  global
  server web1 10.0.0.206:80 weight 1  check inter 3000 fall 2 rise 5             
  server web2 10.0.0.207:80 weight 2  check inter 3000 fall 2 rise 5    
[root@haproxy ~]#systemctl restart haproxy.service 

#$proxy_add_x_forwarded_for:包括客户端IP和中间经过的所有代理的IP
[root@nginx01 nginx]#vim nginx.conf 
    log_format main '$remote_addr - $remote_user [$time_local] "$request" "$proxy_add_x_forwarded_for"';
[root@nginx01 nginx]#systemctl restart nginx
[root@nginx01 nginx]#tail -f /var/log/nginx/access.log 
10.0.0.205 - - [25/Oct/2022:09:32:21 +0800] "GET / HTTP/1.1" "172.20.0.208, 10.0.0.205"
10.0.0.205 - - [25/Oct/2022:09:32:22 +0800] "GET / HTTP/1.1" "172.20.0.208, 10.0.0.205"
10.0.0.205 - - [25/Oct/2022:09:32:23 +0800] "GET / HTTP/1.1" "172.20.0.208, 10.0.0.205"

#$http_x_forwarded_For:只有客户端IP
[root@nginx02 ~]#vim /etc/nginx/nginx.conf 
    log_format main '$remote_addr - $remote_user [$time_local] "$request" "$http_x_forwarded_For"';
[root@nginx02 ~]#systemctl restart nginx
[root@nginx02 ~]#tail -f /var/log/nginx/access.log 
10.0.0.205 - - [25/Oct/2022:09:27:56 +0800] "GET / HTTP/1.1" "172.20.0.208"
10.0.0.205 - - [25/Oct/2022:09:27:56 +0800] "GET / HTTP/1.1" "172.20.0.208"

修改报文

在http模式下,基于实际需求修改客户端的请求报文与响应报文,通过reqadd和reqdel在请求报文添加删除字段,通过rspadd与rspidel在响应报文中添加与删除字段。

http://cbonte.github.io/haproxy-dconv/2.6/configuration.html#4-rspadd

#修改请求host首部,默认host首部会保留客户端原首部haproxy不会修改
http-request set-header host www.wangxiaochun.com
#添加向后端服务器发送的请求报文首部
http-request add-header <name> <fmt> [ { if | unless } <condition> ]
#示例:http-request add-header X-Haproxy-Current-Date %T
#删除向后端服务器发送的请求报文首部
http-request del-header <name> [ { if | unless } <condition> ]
#修改响应首部
http-response set-header server wangserver
#添加向客户端发送的响应报文首部
http-response add-header <name> <fmt> [ { if | unless } <condition> ]
#删除向客户端发送的响应报文首部
http-response del-header <name>
#示例:http-response del-header Server
#案例添加首部字段发往后端服务器
[root@haproxy ~]#vim /etc/haproxy/conf.d/web.cfg 
listen web_site
  bind 172.20.0.230:80
  mode http
  log  global
  http-request add-header X-Haproxy-Current-Date %T
  server web1 10.0.0.206:80 weight 1  check inter 3000 fall 2 rise 5
  server web2 10.0.0.207:80 weight 2  check inter 3000 fall 2 rise 5
[root@haproxy ~]#systemctl restart haproxy.service 
#案例返回时添加字段
[root@haproxy ~]#vim /etc/haproxy/conf.d/web.cfg 
listen web_site
  bind 172.20.0.230:80
  mode http
  log  global
  http-response add-header X-user shuhong
  server web1 10.0.0.206:80 weight 1  check inter 3000 fall 2 rise 5
  server web2 10.0.0.207:80 weight 2  check inter 3000 fall 2 rise 5

自定义日志格式

og global 开启日志功能,默认只会在记录下面格式的日志

[root@haproxy ~]#tail -f /var/log/haproxy.log 
Oct 25 09:33:56 localhost haproxy[45366]: Connect from 172.20.0.208:52772 to 172.20.0.230:80 (web_site/HTTP)

option httplog 可以采用 http 格式记录下来,并且可以使用相关指令将特定信息记录在haproxy的日志中
但一般不建议开启,这会加重 HAProxy 负载

log global #开启记录日志,默认不开启
option httplog #开启记录httplog日志格式选项
capture cookie <name> len <length> #捕获请求和响应报文中的 cookie及值的长度,将之记录到日志
capture request header <name> len <length> #捕获请求报文中指定的首部内容和长度并记录日志
capture response header <name> len <length> #捕获响应报文中指定的内容和长度首部并记录日志
#示例:
log global
option httplog
capture request header Host len 256
capture request header User-Agent len 512
capture request header Referer len 15
capture request header X-Forwarded-For len 15

压缩功能

对响应给客户端的报文进行压缩,以节省网络带宽,但是会占用部分CPU性能
建议在后端服务器开启压缩功能,而非在HAProxy上开启压缩

compression algo <algorithm> ... #启用http协议中的压缩机制,常用算法有
gzip,deflate
#压缩算法<algorithm>支持下面类型:
identity #debug调试使用的压缩方式
gzip #常用的压缩方式,与各浏览器兼容较好
deflate #有些浏览器不支持
raw-deflate #新式的压缩方式
compression type <mime type> ... #要压缩的文件类型
#示例:
compression algo gzip deflate
compression type text/html text/css text/plain

后端服务的健康性检查

#三种状态监测方式
基于四层的传输端口做状态监测,此为默认方式
基于指定 URI 做状态监测,需要访问整个页面资源,占用更多带宽
基于指定 URI 的 request 请求头部内容做状态监测,占用较少带宽,建议使用此方式

基于应用层http协议,采有不同的监测方式,对后端real server进行状态监测
注意: 此方式会导致在后端服务器生成很多的HAProxy发起的访问日志
option httpchk #启用七层健康性检测,对tcp 和 http 模式都支持,默认为:OPTIONS /
HTTP/1.0
option httpchk <uri>
option httpchk <method> <uri>
option httpchk <method> <uri> <version>
#期望以上检查得到的响应码
http-check expect [!] <match> <pattern>
#示例:
http-check expect status 200
http-check expect ! rstatus ^5 #支持正则表达式
#关于HTTP/1.1的说明
<version> is the optional HTTP version string. It defaults to "HTTP/1.0" butsome servers might behave incorrectly in HTTP 1.0, so turning it to HTTP/1.1 maysometimes help. Note that the Host field is mandatory in HTTP/1.1, andas a trick, it is possible to pass it after "\r\n" following the version string.

#配置示例
option httpchk HEAD /index.html HTTP/1.1\r\nHost:\ 10.0.0.7 #使用HEAD减少网络流量
[root@haproxy ~]#vim /etc/haproxy/conf.d/web.cfg 
listen web_site
  bind 172.20.0.230:80
  mode http
  log  global
  #option httpchk GET /index.nginx-debian.html HTTP/1.0 #默认HTTP/1.0
  option httpchk HEAD /index.nginx-debian.html HTTP/1.1\r\nHost:\ 172.20.0.230 #使用HEAD减少网络流量,注意:HTTP/1.1强制要求必须有Host字段
  server web1 10.0.0.206:80 weight 1  check inter 3000 fall 2 rise 5
  server web2 10.0.0.207:80 weight 2  check inter 3000 fall 2 rise 5
[root@haproxy ~]#systemctl restart haproxy.service 

ACL

访问控制列表(ACL,Access Control Lists)是一种基于包过滤的访问控制技术,它可以根据设定的条件对经过服务器传输的数据包进行过滤(条件匹配),即对接收到的报文进行匹配和过滤,基于请求报文头部中的源地址、源端口、目标地址、目标端口、请求方法、URL、文件后缀等信息内容进行匹配并执行进一步操作,比如允许其通过或丢弃

http://cbonte.github.io/haproxy-dconv/2.6/configuration.html#7

定义ACL配置选项
acl <aclname> <criterion> [flags] [operator] [<value>]
acl 名称 匹配规范 匹配模式 具体操作符 操作对象类型

ACL-Name
acl image_service hdr_dom(host) -i img.wang.com
#ACL名称,可以使用大字母A-Z、小写字母a-z、数字0-9、冒号:、点.、中横线和下划线,并且严格区分大小写,比如:my_acl和My_Acl就是两个完全不同的acl

ACL-criterion

hdr string,提取在一个HTTP请求报文的首部
hdr([<name> [,<occ>]]):完全匹配字符串,header的指定信息,<occ> 表示在多值中使用的值的出现次数
hdr_beg([<name> [,<occ>]]):前缀匹配,header中指定匹配内容的begin
hdr_end([<name> [,<occ>]]):后缀匹配,header中指定匹配内容end
hdr_dom([<name> [,<occ>]]):域匹配,header中的domain name
hdr_dir([<name> [,<occ>]]):路径匹配,header的uri路径
hdr_len([<name> [,<occ>]]):长度匹配,header的长度匹配
hdr_reg([<name> [,<occ>]]):正则表达式匹配,自定义表达式(regex)模糊匹配
hdr_sub([<name> [,<occ>]]):子串匹配,header中的uri模糊匹配

#示例:
hdr(<string>) 用于测试请求头部首部指定内容
hdr_dom(host) 请求的host名称,如 www.wang.com,m.wang.com
hdr_beg(host) 请求的host开头,如 www. img. video. download. ftp.
hdr_end(host) 请求的host结尾,如 .com .net .cn

#示例:
acl bad_agent hdr_sub(User-Agent) -i curl wget
http-request deny if bad_agent

#block if bad_agent 2.1版本后不再支持,用上面替代
hdr(host) ==>www.wang.org:8080
hdr_domain(host) ==> www.wang.org

#有些功能是类似的,比如以下几个都是匹配用户请求报文中host的开头是不是www
acl short_form hdr_beg(host) www.
acl alternate1 hdr_beg(host) -m beg www.
acl alternate2 hdr_dom(host) -m beg www.
acl alternate3 hdr(host) -m beg www.
base : string

#返回第一个主机头和请求的路径部分的连接,该请求从主机名开始,并在问号之前结束,对虚拟主机有用,下面的例子中是两个#中间的内容,实际#是没有的
<scheme>://<user>:<password>@#<host>:<port>/<path>;<params>#?<query>#<frag>
base : exact string match
base_beg : prefix match
base_dir : subdir match
base_dom : domain match
base_end : suffix match
base_len : length match
base_reg : regex match
base_sub : substring match
path : string

#提取请求的URL路径,该路径从第一个斜杠开始,并在问号之前结束(无主机部分)
<scheme>://<user>:<password>@<host>:<port>#/<path>;<params>#?<query>#<frag>
path : exact string match
path_beg : prefix match #请求的URL开头,如/static、/images、/img、/css
path_end : suffix match #请求的URL中资源的结尾,如 .gif .png .css .js .jpg.jpeg
path_dom : domain match
path_dir : subdir match
path_len : length match
path_reg : regex match
path_sub : substring match

#示例:
path_beg -i /haproxy-status/
path_end .jpg .jpeg .png .gif
path_reg ^/images.*\.jpeg$
path_sub image
path_dir jpegs
path_dom wang
url : string

#提取请求中的整个URL。一个典型的应用是具有预取能力的缓存,以及需要从数据库聚合多个信息并将它们保存在缓存中的网页门户入口,推荐使用path
url :exact string match
url_beg : prefix match
url_dir : subdir match
url_dom : domain match
url_end : suffix match
url_len : length match
url_reg : regex match
url_sub : substring match

src #源IP
src_port #源PORT

dst #目标IP
dst_port #目标PORT

#示例:
acl invalid_src src 10.0.0.7 192.168.1.0/24
acl invalid_src src 172.16.0.0/24
acl invalid_port src_port 0:1023
status : integer #返回在响应报文中的状态码

#七层协议
acl valid_method method GET HEAD
http-request deny if ! valid_method

ACL-flags

整数比较:eq、ge、gt、le、lt
字符比较:
- exact match (-m str) :字符串必须完全匹配模式
- substring match (-m sub) :在提取的字符串中查找模式,如果其中任何一个被发现,ACL将匹配
- prefix match (-m beg) :在提取的字符串首部中查找模式,如果其中任何一个被发现,ACL将匹配
- suffix match (-m end) :将模式与提取字符串的尾部进行比较,如果其中任何一个匹配,则ACL进行匹配
- subdir match (-m dir) :查看提取出来的用斜线分隔(“/")的字符串,如其中任一个匹配,则ACL进行匹配
- domain match (-m dom) :查找提取的用点(“.")分隔字符串,如果其中任何一个匹配,则ACL进行匹配

ACL-value

The ACL engine can match these types against patterns of the following types :
- Boolean #布尔值
- integer or integer range #整数或整数范围,比如用于匹配端口范围
- IP address / network #IP地址或IP范围, 192.168.0.1 ,192.168.0.1/24
- string--> www.wang.com
exact #精确比较
substring #子串
suffix #后缀比较
prefix #前缀比较
subdir #路径, /wp-includes/js/jquery/jquery.js
domain #域名,www.wang.com
- regular expression #正则表达式
- hex block #16进制

多个ACL的组合调用方式

与:隐式(默认)使用
或:使用“or" 或 “||"表示
否定:使用 "!" 表示

#示例:
if valid_src valid_port #与关系,ACL中A和B都要满足为true,默认为与
if invalid_src || invalid_port #或,ACL中A或者B满足一个为true
if ! invalid_src #非,取反,不满足ACL才为true

ACL示例:域名匹配

[root@haproxy ~]#vim /etc/haproxy/conf.d/web.cfg 
frontend web_site
  bind 172.20.0.230:80
  mode http
  log  global
  acl web01_domain hdr_dom(host) -i www.shuhong.com
  use_backend web01 if web01_domain
  default_backend web02


backend web01
  server web1 10.0.0.206:80 weight 1  check inter 3000 fall 2 rise 5

backend web02
  server web2 10.0.0.207:80 weight 2  check inter 3000 fall 2 rise 5 
[root@haproxy ~]#systemctl restart haproxy.service 

自定义错误界面

对指定的报错进行重定向,进行优雅的显示错误页面
使用errorfile和errorloc指令的两种方法,可以实现自定义各种错误页面

基于自定义的错误页面文件

#自定义错误页
errorfile <code> <file>
<code> #HTTP status code.支持200, 400, 403, 405, 408, 425, 429, 500, 502,503,504
<file> #包含完整HTTP响应头的错误页文件的绝对路径。 建议后缀为".http",以和一般的html文件相区
分
#示例:
errorfile 400 /etc/haproxy/errorfiles/400badreq.http
errorfile 403 /etc/haproxy/errorfiles/403forbid.http
errorfile 503 /etc/haproxy/errorfiles/503sorry.http

#范例
[root@haproxy ~]#vim /etc/haproxy/haproxy.cfg 
default
errorfile 503 /apps/haproxy/html/503.http

[root@haproxy ~]#mkdir /apps/haproxy/html -p
[root@haproxy ~]#vim /apps/haproxy/html/503.http
HTTP/1.1 503 Service Unavailable
content-type: text/html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>报错页面</title>
</head>
<body>
<center><h1>网站维护中......请稍候再试</h1></center>
<center><h2>联系电话:400-123-4567</h2></center>
<center><h3>503 Service Unavailable</h3></center>
</body>
[root@haproxy ~]#systemctl restart haproxy.service 


[root@ubuntu2004 ~]#curl 172.20.0.230
<html><body><h1>503 Service Unavailable</h1>
No server is available to handle this request.
</body></html>
[root@ubuntu2004 ~]#curl 172.20.0.230 -I
HTTP/1.1 503 Service Unavailable
content-length: 107
cache-control: no-cache
content-type: text/html

[root@ubuntu2004 ~]#curl 172.20.0.230 -I
HTTP/1.1 503 Service Unavailable
content-type: text/html
connection: close

[root@ubuntu2004 ~]#curl 172.20.0.230 
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>报错页面</title>
</head>
<body>
<center><h1>网站维护中......请稍候再试</h1></center>
<center><h2>联系电话:400-123-4567</h2></center>
<center><h3>503 Service Unavailable</h3></center>
</body>

重定向错误页面

[root@centos7 ~]#vim /etc/haproxy/haproxy.cfg
defaults
#option http-keep-alive
#option forwardfor
#no option http-use-htx
#...... 加以下一行
#errorfile 503 /apps/haproxy/html/503.http
errorloc 503 http://10.0.0.8/error_page/503.html
[root@centos8 ~]#cat /var/www/html/error_page/503.html
6.10 HAProxy 四层负载
针对除HTTP以外的TCP协议应用服务访问的应用场景
问题: 后端服务器到底是与haproxy还是和客户端建立三次握手呢?
6.10.1 四层负载示例
注意:如果使用frontend和backend,一定在 frontend 和 backend 段中都指定mode tcp
范例:对 MySQL 服务实现四层负载
<!DOCTYPE html>
<html lang="en">
<head>
<title>报错页面</title>
</head>
<body>
<center><h1>网站维护中......请稍侯再试</h1></center>
<center><h2>联系电话:400-123-4567</h2></center>
<center><h3>503 Service Unavailable</h3></center>
</body>

四层负载

针对除HTTP以外的TCP协议应用服务访问的应用场景

MySQL
Redis
Memcached
RabbitMQ

注意:如果使用frontend和backend,一定在 frontend 和 backend 段中都指定mode tcp
listen redis-port
bind 10.0.0.7:6379
mode tcp
balance leastconn
server server1 10.0.0.17:6379 check
server server2 10.0.0.27:6379 check backup

https实现

#配置HAProxy支持https协议,支持ssl会话;
bind *:443 ssl crt /PATH/TO/SOME_PEM_FILE
#指令 crt 后证书文件为PEM格式,需要同时包含证书和所有私钥
cat demo.key demo.crt > demo.pem
#把80端口的请求利用302重向定443
bind *:80
redirect scheme https if !{ ssl_fc }
#向后端传递用户请求的协议和端口(frontend或backend)
http_request set-header X-Forwarded-Port %[dst_port]
http_request add-header X-Forwared-Proto https if { ssl_fc }
#制作证书
[root@haproxy ~]#mkdir /etc/haproxy/certs
[root@haproxy ~]#cd /etc/haproxy/certs/
[root@haproxy certs]#openssl genrsa -out haproxy.key 2048
Generating RSA private key, 2048 bit long modulus (2 primes)
...........................................................+++++
.................................................................+++++
e is 65537 (0x010001)
[root@haproxy certs]#openssl req -new -x509 -key haproxy.key -out haproxy.crt -subj "/CN=www.shuhong.com"
[root@haproxy certs]#cat haproxy.key haproxy.crt > haproxy.pem
[root@haproxy certs]#openssl x509 -in haproxy.pem -noout -text
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            3c:4d:67:0a:96:74:24:7a:b2:6a:03:6c:0b:ce:51:2f:2f:f9:04:e1
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN = www.shuhong.com
        Validity
            Not Before: Oct 25 02:54:33 2022 GMT
            Not After : Nov 24 02:54:33 2022 GMT
        Subject: CN = www.shuhong.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (2048 bit)
                Modulus:
                    00:e3:6f:20:87:85:4a:11:3c:31:dc:2a:93:69:e8:
                    7c:52:a3:0e:3e:07:b8:a8:3f:0d:25:00:62:55:bf:
                    45:10:9c:90:2f:9b:a1:40:e3:6e:e3:e2:8f:e1:d0:
                    0e:69:95:03:ca:2b:1d:da:7c:02:b1:e5:76:d4:ad:
                    23:cf:34:23:d6:fe:10:24:08:41:43:66:d7:7c:28:
                    2b:3b:67:df:fe:1c:a5:d0:9b:85:f3:cf:b5:6f:d4:
                    f5:71:09:5d:bf:b2:37:2d:3f:77:5a:ff:b7:3f:e7:
                    79:a8:39:8d:8b:75:b2:b5:fd:6f:c6:6c:61:ec:66:
                    78:8c:7c:7e:26:56:7c:29:12:c2:72:49:f5:b3:63:
                    eb:e9:f6:43:40:79:2d:1c:33:be:3d:8f:d3:18:a0:
                    ec:9a:11:b7:20:42:f4:d7:64:fb:f4:79:54:f1:e3:
                    38:ee:41:62:8c:57:92:ee:eb:14:1c:97:b4:35:cc:
                    73:c8:75:f3:36:7f:41:8f:2c:00:15:2a:26:7b:f8:
                    24:3a:ab:d2:f3:ff:9c:67:6c:25:bb:a2:ce:fe:90:
                    7d:97:10:d4:30:f5:08:20:a9:e4:51:37:f3:04:ac:
                    3b:f7:af:4f:f1:1a:01:a6:54:ca:14:1d:c7:6b:63:
                    df:8d:92:b6:a9:f1:82:f7:a2:25:0e:9e:b1:d4:bf:
                    03:d7
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                55:71:7D:F9:D6:A9:82:2C:2B:96:44:36:15:56:E5:80:1C:52:B2:AA
            X509v3 Authority Key Identifier: 
                keyid:55:71:7D:F9:D6:A9:82:2C:2B:96:44:36:15:56:E5:80:1C:52:B2:AA

            X509v3 Basic Constraints: critical
                CA:TRUE
    Signature Algorithm: sha256WithRSAEncryption
         b6:00:b3:52:d6:c5:24:1e:1a:88:56:71:d9:44:e3:9b:98:31:
         95:2c:65:fe:39:d2:04:39:5d:3f:12:dd:69:4a:c2:8f:1e:ef:
         80:ef:d5:27:5b:d7:b2:ec:97:f8:1e:95:d2:24:41:2a:4e:18:
         9b:9a:38:ec:ea:5f:d1:05:f0:16:7e:6f:6a:c4:99:f5:62:1a:
         9e:fb:22:c7:4b:95:ad:f9:e5:17:62:26:97:87:ad:4f:75:8d:
         32:ca:9e:49:f4:bd:58:86:a1:cf:77:ee:3c:81:7f:db:ff:ab:
         67:62:42:16:55:a8:6a:05:a3:0d:f5:de:1c:83:3f:49:b1:c3:
         26:b0:dd:a2:e3:3a:16:33:5e:9e:50:32:e6:b3:38:70:cc:7b:
         8d:33:3b:96:a1:6a:41:14:8a:b8:8a:a7:43:f6:df:4b:dc:f9:
         14:ea:b5:cd:b2:68:d4:e6:f3:28:2f:a9:e1:d5:e6:29:f0:6a:
         4a:54:c9:4a:5b:72:44:0b:85:87:19:b4:2a:f7:13:42:9f:67:
         77:b6:1d:1c:68:bc:aa:53:f3:e3:43:97:85:69:b4:cc:3a:d6:
         3c:b2:39:2a:0d:d7:06:20:54:55:28:a2:b5:dd:00:38:95:bf:
         68:97:26:1b:86:cf:3f:08:22:2a:90:46:76:fd:12:f6:68:ad:
         07:83:10:c9

#配置证书
[root@haproxy certs]#vim /etc/haproxy/conf.d/web.cfg
frontend web_site
  bind 172.20.0.230:80
  bind 172.20.0.230:443 ssl crt /etc/haproxy/certs/haproxy.pem
  redirect scheme https if !{ ssl_fc }     #注意{}内前面必须有空格
  http-request set-header X-forwarded-Port %[dst_port]
  http-request add-header X-forwarded-Proto https if { ssl_fc }

  mode http
  log  global
  acl web01_domain hdr_dom(host) -i www.shuhong.com
  use_backend web01 if web01_domain
  default_backend web02


backend web01
  server web1 10.0.0.206:80 weight 1  check inter 3000 fall 2 rise 5

backend web02
  server web2 10.0.0.207:80 weight 2  check inter 3000 fall 2 rise 5