HAproxy

HAproxy

一、负载均衡

1.1什么是负载均衡

负载均衡:Load Balance,简称LB,是一种服务或基于硬件设备等实现的高可用反向代理技术,负载均

衡将特定的业务(web服务、网络流量等)分担给指定的一个或多个后端特定的服务器或设备,从而提高了

公司业务的并发处理能力、保证了业务的高可用性、方便了业务后期的水平动态扩展

阿里云SLB介绍:https://yq.aliyun.com/articles/1803

1.2为什么要用负载均衡

  • Web服务器的动态水平扩展-->对用户无感知
  • 增加业务并发访问及处理能力-->解决单服务器瓶颈问题
  • 节约公网IP地址-->降低IT支出成本
  • 隐藏内部服务器IP-->提高内部服务器安全性
  • 配置简单-->固定格式的配置文件
  • 功能丰富-->支持四层和七层,支持动态下线主机
  • 性能较强-->并发数万甚至数十万

1.3负载均衡类型

1.3.1四层负载均衡

1.通过ip+port决定负载均衡的去向。

2.对流量请求进行NAT处理,转发至后台服务器。

3.记录tcp、udp流量分别是由哪台服务器处理,后续该请求连接的流量都通过该服务器处理。

4.支持四层的软件

  • lvs:重量级四层负载均衡器。、
  • Nginx:轻量级四层负载均衡器,可缓存。(nginx四层是通过upstream模块)
  • Haproxy:模拟四层转发。
1.3.2七层负载均衡

1.通过虚拟ur|或主机ip进行流量识别,根据应用层信息进行解析,决定是否需要进行负载均衡。

2.代理后台服务器与客户端建立连接,如nginx可代理前后端,与前端客户端tcp连接,与后端服务器建立 tcp连接,

3.支持7层代理的软件:

  • Nginx:基于http协议(nginx七层是通过proxy_pass)
  • Haproxy:七层代理,会话保持、标记、路径转移等。
1.3.3四层和七层的区别

所谓的四到七层负载均衡,就是在对后台的服务器进行负载均衡时,依据四层的信息或七层的信息来决 定怎么样转发流量

四层的负载均衡,就是通过发布三层的IP地址(VIP),然后加四层的端口号,来决定哪些流量需要做负 载均衡,对需要处理的流量进行NAT处理,转发至后台服务器,并记录下这个TCP或者UDP的流量是由哪 台服务器处理的,后续这个连接的所有流量都同样转发到同一台服务器处理

七层的负载均衡,就是在四层的基础上(没有四层是绝对不可能有七层的),再考虑应用层的特征,比 如同一个Web服务器的负载均衡,除了根据VIP加80端口辨别是否需要处理的流量,还可根据七层的 URL、浏览器类别、语言来决定是否要进行负载均衡。

1.分层位置:四层负载均衡在传输层及以下,七层负载均衡在应用层及以下

2.性能 :四层负载均衡架构无需解析报文消息内容,在网络吞吐量与处理能力上较高:七层可支持解析应用 层报文消息内容,识别URL、Cookie、HTTP header等信息。

3.原理 :四层负载均衡是基于ip+port;七层是基于虚拟的URL或主机IP等。

4.功能类比:四层负载均衡类似于路由器;七层类似于代理服务器。

5.安全性:四层负载均衡无法识别DDoS攻击;七层可防御SYN Cookie/Flood攻击

二、haproxy简介

HAProxy是法国开发者 威利塔罗(Willy Tarreau) 在2000年使用C语言开发的一个开源软件 是一款具备高并发(万级以上)、高性能的TCP和HTTP负载均衡器

支持基于cookie的持久性,自动故障切换,支持正则表达式及web状态统计

企业版网站:https://www.haproxy.com

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

github:https://github.com/haprox

企业版和社区版功能对比

功能 社区版 企业版
高级HTTP/TCP负载平衡和持久性
高级健康检查
应用程序加速
高级安全特性
高级管理
HAproxy Dev Branch新功能
24*7支持服务
实时仪表盘
VRRP和Route Health Injrection HA 工具
ACL,映射和TLS票证密钥同步
基于应用程序的高级DDos和Bot保护(自动保护)
Bot(机器人)检测
web应用防火墙
HTTP协议验证
实时集群追踪

三、haproxy的安装和服务信息

3.1实验环境

功能 IP
haproxy 172.25.250.100
RS1 172.25.250.10
RS2 172.25.250.20

3.2软件安装

安装软件包

bash 复制代码
dnf isntall haproxy -y

查看版本

bash 复制代码
haproxy -v
HAProxy version 2.4.22-f8e3218 2023/02/14 - https://haproxy.org/Status: long-term supported branch - will stop receiving fixes around Q2 2026.Known bugs: http://www.haproxy.org/bugs/bugs-2.4.22.htmlRunning on: Linux 5.14.0-427.13.1.el9_4.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Apr 10 10:29:16 EDT 2024 x86_64

haproxy的基本信息

bash 复制代码
软件安装包:  haproxy-2.4.22-3.el9_3.x86_64.rpm
启动文件:    /lib/systemd/system/haproxy.service
主配置目录:  /etc/haproxy/
主配置文件:  /etc/haproxy/haproxy.cfg
子配置目录:  /etc/haproxy/conf.d

3.3haproxy的基本配置信息

官方文档:http://cbonte.github.io/haproxy-dconv/

HAProxy 的配置文件haproxy.cfg由两大部分组成,分别是:

global:全局配置段

  • 进程及安全配置相关的参数
  • 性能调整相关参数
  • Debug参数

proxies:代理配置段

  • defaults:为frontend, backend, listen提供默认配置
  • frontend:前端,相当于nginx中的server {}
  • backend:后端,相当于nginx中的upstream {}
  • listen:同时拥有前端和后端配置,配置简单,生产推荐使用
3.3.1.global配置

3.3.1.1 global 配置参数说明

bash 复制代码
global   
   log         127.0.0.1 local2        #定义全局的syslog服务器;日志服务器需要开启UDP协议,最多可以定义两个   
   chroot      /var/lib/haproxy        #锁定运行目录   
   pidfile     /var/run/haproxy.pid    #指定pid文件     
   maxconn     100000                  #指定最大连接数   
   user        haproxy                 #指定haproxy的运行用户   
   group       haproxy                 #指定haproxy的运行组   
   daemon                              #指定haproxy以守护进程方式运行   
   # turn on stats unix socket   
   stats socket /var/lib/haproxy/stats     #指定haproxy的套接字文件 
    stats socket /var/lib/haproxy/haproxy.sock1 mode 600 level admin process 1  #启用多个sock文件   
    stats socket /var/lib/haproxy/haproxy.sock2 mode 600 level admin process 2
   nbproc  2                               #指定haproxy的work进程数量,默认是1个        cpu-map 1 0                             #指定第一个work绑定第一个cpu核心   
   cpu-map 2 1                             #指定第二个work绑定第二个cpu核心            nbthread 2                              #指定haproxy的线程数量,默认每个进程一个线程,此参数与nbproc互斥       
   maxsslconn 100000                       #每个haproxy进程ssl最大连接数,用于haproxy配置了证书的场景下   
   maxconnrate 100                         #指定每个客户端每秒建立连接的最大数量

3.3.1.2 多进程和线程

多进程文件配置如下:

bash 复制代码
# vim /etc/haproxy/haproxy.cfg
...上面内容省略...
log         127.0.0.1 local2

     chroot      /var/lib/haproxy   
     pidfile     /var/run/haproxy.pid   
     maxconn     100000   
     user        haproxy    
     group       haproxy    
     daemon

# turn on stats unix socket  
   nbproc 2            #启用多进程 
   cpu-map 1 0         #进程和cpu核心绑定防止cpu抖动从而减少系统资源消耗
   cpu-map 2 1         #2 表示第二个进程,1表示第二个cpu核心   
   #nbthread 2         #启用多线程    
   ##################多进程和多线程不可以同时开启##########################
   ...下面内容省略...

查看多进程信息

bash 复制代码
#pstree -p | grep haproxy
           |-haproxy(83443)-+-haproxy(83445)
           |                `-haproxy(83446)

查看多线程

多线程对比

复制代码
未开启多线程
haproxy ~]# cat /proc/xxxx(haproxy子进程id)/status
...上面内容省略...
Threads:        1
...下面内容省略...

开启
haproxy ~]# cat /proc/xxxx(haproxy子进程id)/status
...上面内容省略...
Threads:        2
...下面内容省略.
bash 复制代码
#改缩进和tab键间隔
[root@haproxy ~]#  cat ~/.vimrc
set nu ts=4 sw=4 ai et
3.3.2 proxies配置

3.3.2.1.proxies参数说明proxies

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

3.3.2.2 Proxies配置-defaults

bash 复制代码
defaults   
	mode                    http                #HAProxy实例使用的连接协议             
	log                     global              #指定日志地址和记录日志条目的syslog/rsyslog日志设备               #此处的global表示使用 global配置段中设定的log值。     
	option                  httplog             #日志记录选项,httplog表示记录与 HTTP会话相关的各种属性值          #包括 HTTP请求、会话状态、连接数、源地址以及连接时间等       
	option                  dontlognull         #dontlognull表示不记录空会话连接日志     
	option http-server-close                    #等待客户端完整HTTP请求的时间,此处为等待10s。        
	option forwardfor       except 127.0.0.0/8  #透传客户端真实IP至后端web服务器                                                #在apache配置文件中加入:<br>%{X-Forwarded-For}i                                                   #后在webserver中看日志即可看到地址透传信息        
	option                  redispatch          #当server Id对应的服务器挂掉后,强制定向到其他健康的服务器,重新派发        
	option                  http-keep-alive     #开启与客户端的会话保持                 retries                 3                   #连接后端服务器失败次数
    timeout http-request    10s                 #等待客户端请求完全被接收和处理的最长时间        
    timeout queue           1m                  #设置删除连接和客户端收到503或服务不可用等提示信息前的等待时间       
    timeout connect         120s                #设置等待服务器连接成功的时间        
    timeout client          600s                #设置允许客户端处于非活动状态,即既不发送数据也不接收数据的时间        
    timeout server          600s                #设置服务器超时时间,即允许服务器处于既不接收也不发送数据的非活动时间        
    timeout http-keep-alive 60s                 #session 会话保持超时时间,此时间段内会转发到相同的后端服务器        
    timeout check           10s                 #指定后端服务器健康检查的超时时间        
    maxconn                 3000        default-server inter 1000 weight 3 
	
	
	

3.3.2.3 Proxies配置-frontend

frontend 配置参数:

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

frontend配置示例:

bash 复制代码
#frontend webcluster
 60 #    bind        *:80
 61 #    mode        http
 62 #    use_backend webserver

3.3.2.4 Proxies配置-backend

  • 定义一组后端服务器,backend服务器将被frontend进行调用。
  • 注意: backend 的名称必须唯一,并且必须在listen或frontend中事先定义才可以使用,否则服务无法启动
bash 复制代码
mode http|tcp       #指定负载协议类型,和对应的frontend必须一致
option              #配置选项
server              #定义后端real server,必须指定IP和端口
balance              #定义调度算法

注意:option后面加 httpchk,smtpchk,mysql-check,pgsql-check,ssl-hello-chk方法,可用于实现更多应用层检测功能。

server配置

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

代码示例:

bash 复制代码
vim /etc/haproxy/haproxy.cfg


 48     backend_webserver 
 49     balance roundrobin
 50     server web1 172.25.250.10:80 check inter 5s fall 3 rise 2
 51     server web2 172.25.250.20:80 check inter 5s fall 3 rise 2

测试效果:

3.3.2.5 Proxies配置-listen 简化配置

使用listen替换 frontend和backend的配置方式,可以简化设置,通常只用于TCP协议的应用listen配置示例:

bash 复制代码
 listen  webcluster
 47     bind    *:80
 48     mode    http
 49     balance roundrobin
 50     server web1 172.25.250.10:80 check inter 5s fall 3 rise 2 disabled
 51     server web2 172.25.250.20:80 check inter 5s fall 3 rise 2 disabled
 52     server sorry 172.25.250.100:8080 backup  #备用服务器,当后台真实主机挂掉后,访问该服务器
 53     #redirect prefix https://www.baidu.com   #请求前缀重定向到百度网站

backup,备用服务器的效果图

redirect重定向

3.4.socat 工具

对服务器动态权重和其它状态可以利用 socat工具进行调整,Socat 是 Linux 下的一个多功能的网络工具,名字来由是Socket CAT,相当于netCAT的增强版.Socat 的主要特点就是在两个数据流之间建立双向通道,且支持众多协议和链接方式。如 IP、TCP、 UDP、IPv6、Socket文件等

范例:利用工具socat 对服务器动态权重调整

bash 复制代码
vim /etc/haproxy/haproxy.cfg
stats socket /var/lib/haproxy/stats mode 600 level admin

haproxy ~]# socat -hhaproxy ~]# echo "help" | socat stdio /var/lib/haproxy/stats
The following commands are valid at this level:
help           : this message
prompt         : toggle interactive mode with prompt
quit           : disconnect
。。。省略 。。。
enable server : enable a disabled server (use 'set server' instead)   #启用服务器
set maxconn server : change a server's maxconn setting
set server     : change a server's state, weight or address           #设置服务器 
get weight     : report a server's current weight                     #查看权重

set weight     : change a server's weight (deprecated)                #设置权重

#示例
#查看集群权重[root@haproxy ~]# echo get weight webcluster/web1 | socat stdio /var/lib/haproxy/stats
2 (initial 2)

root@haproxy ~]# echo get weight webcluster/web2 | socat stdio /var/lib/haproxy/stats
1 (initial 1)



#设置权重
[root@haproxy ~]# echo "set  weight  webcluster/web1 1 " | socat stdio /var/lib/haproxy/stats

[root@haproxy ~]# echo "set  weight  webcluster/web1 2 " | socat stdio /var/lib/haproxy/stats

#下线后端服务器
[root@haproxy ~]# echo "disable server  webserver_80/webserver1 "  | socat stdio /var/lib/haproxy/stats
#上线后端服务器
[root@haproxy ~]# echo "enable server  webserver_80/webserver1 "  | socat stdio  /var/lib/haproxy/stats

3.5.haproxy的状态页

bash 复制代码
#defaults模块
。
。
。
  listen  stats
        mode    http
        bind    *:8888#自定义端口
        stats   enable#开启状态页功能
        log     global#继用全局日志
        stats   uri /haproxy-status #自定义访问状态页的路径
        stats   auth    gee:gee#状态页用户认证
。
。
。
测试:
浏览器访问:172.25.250.112:8888/haproxy-status

可以查看到对应的版本以及后端真是服务器的状态

3.5.1登录页状态
bash 复制代码
#pid为当前pid号,process为当前进程号,nbproc和nbthread为一共多少进程和每个进程多少个线程
pid = 27134 (process #1, nbproc = 1, nbthread = 1) 
#启动了多长时间
uptime = 0d 0h00m04s 
#系统资源限制:内存/最大打开文件数/
system limits: memmax = unlimited; ulimit-n = 200029 
#最大socket连接数/单进程最大连接数/最大管道数maxpipes
maxsock = 200029; maxconn = 100000; maxpipes = 0 
#当前连接数/当前管道数/当前连接速率
current conns = 2; current pipes = 0/0; conn rate = 2/sec; bit rate = 0.000 kbps 

#运行的任务/当前空闲率
Running tasks: 1/14; idle = 100 % 
active UP: #在线服务器
backup UP: #标记为backup的服务器
active UP, going down: #监测未通过正在进入down过程
backup UP, going down: #备份服务器正在进入down过程
active DOWN, going up: #down的服务器正在进入up过程
backup DOWN, going up: #备份服务器正在进入up过程
active or backup DOWN: #在线的服务器或者是backup的服务器已经转换成了down状态
not checked: #标记为不监测的服务器
#active或者backup服务器人为下线的
active or backup DOWN for maintenance (MAINT)
#active或者backup被人为软下线(人为将weight改成0)
active or backup SOFT STOPPED for maintenance 

四、算法

HAProxy通过固定参数 balance 指明对后端服务器的调度算法

balance参数可以配置在listen或backend选项中。

HAProxy的调度算法分为静态和动态调度算法 ,有些算法可以根据参数在静态和动态算法中相互转换

4.1 静态算法

静态算法:按照事先定义好的规则轮询公平调度,不关心后端服务器的当前负载、连接数和响应速度 等,且无法实时修改权重(只能为0和1,不支持其它值),只能靠重启HAProxy生效

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

**注释:**慢启动是指在服务器刚刚启动上不会把他所应该承担的访问压力全部给它,而是先给一部分,当没问题后在给一部分

bash 复制代码
haproxy ~]# vim /etc/haproxy/haproxy.cfg
...上面内容省略...
listen webserver_80
   bind *:80
   mode http
   balance static-rr
   server webserver1 172.25.250.10:80 weight 2 check inter 3s fall 3 rise 2
   server webserver2 172.25.250.20:80 weight 1 check inter 3s fall 3 rise 2
...上面内容省略...
4.1.2 first
  • 根据服务器在列表中的位置,自上而下进行调度
  • 其只会当第一台服务器的连接数达到上限,新请求才会分配给下一台服务 其会忽略服务器的权重设置
  • 不支持用socat进行动态修改权重,可以设置0和1,可以设置其它值但无效
bash 复制代码
haproxy ~]# vim /etc/haproxy/haproxy.cfg
...
listen webserver_80
   bind *:80
   mode http
   balance first                 
   server webserver1 172.25.250.10:80 maxconn 3 check inter 3s fall 3 rise 2
   server webserver2 172.25.250.20:80 check inter 3s fall 3 rise 2
...

4.2 动态算法

动态算法

  • 基于后端服务器状态进行调度适当调整,
  • 新请求将优先调度至当前负载较低的服务器
  • 权重可以在haproxy运行时动态调整无需重启
4.2.1 roundrobin
  1. 基于权重的轮询动态调度算法,

  2. 支持权重的运行时调整,不同于lvs中的rr轮训模式,

  3. HAProxy中的roundrobin支持慢启动(新加的服务器会逐渐增加转发数),

  4. 其每个后端backend中最多支持4095个real server,

  5. 支持对real server权重动态调整,

  6. roundrobin为默认调度算法,此算法使用广泛

bash 复制代码
haproxy ~]# vim /etc/haproxy/haproxy.cfg
...
listen webserver_80
   bind *:80
   mode http
   balance roundrobin                 
   server webserver1 172.25.250.10:80 weight 1 check inter 3s fall 3 rise 2 
   server webserver2 172.25.250.20:80 weight 1 check inter 3s fall 3 rise 2

动态调整权重

bash 复制代码
[root@haproxy ~]# echo "set weight webserver_80/server1 2" | socat stdio  /var/lib/haproxy/haproxy.sock
4.2.2 leastconn
  • leastconn加权的最少连接的动态
  • 支持权重的运行时调整和慢启动,即:根据当前连接最少的后端服务器而非权重进行优先调度(新客户 端连接)
  • 比较适合长连接的场景使用,比如:MySQL等场景
bash 复制代码
haproxy ~]# vim /etc/haproxy/haproxy.cfg
...
listen webserver_80
   bind *:80
   mode http
   balance leastconn
   server webserver1 192.168.0.101:80 weight 2 check inter 3s fall 3 rise 5 
   server webserver2 192.168.0.102:80 weight 1 check inter 3s fall 3 rise 5

4.3 其他算法

其它算法即可作为静态算法,又可以通过选项成为动态算法

4.3.1 source

源地址hash,基于用户源地址hash并将请求转发到后端服务器,后续同一个源地址请求将被转发至同一 个后端web服务器。此方式当后端服务器数据量发生变化时,会导致很多用户的请求转发至新的后端服 务器,默认为静态方式,但是可以通过hash-type支持的选项更改这个算法一般是在不插入Cookie的TCP 模式下使用,也可给拒绝会话cookie的客户提供最好的会话粘性,适用于session会话保持但不支持 cookie和缓存的场景源地址有两种转发客户端请求到后端服务器的服务器选取计算方式,分别是取模法 和一致性hash

bash 复制代码
haproxy ~]# vim /etc/haproxy/haproxy.cfg
...
listen webserver_80
   bind *:80
   mode http
   balance source
   #hash-type consistent 加了就是动态算法,一致性hash
   server webserver1 172.25.250.10:80 weight 1 check inter 3s fall 3 rise 2 
   server webserver2 172.25.250.20:80 weight 1 check inter 3s fall 3 rise 2

注意:如果访问客户端时一个家庭,那么所有的家庭的访问流量都会被定向到一台服务器,这时source算 法的缺陷

4.3.2map-base 取模法

map-based:取模法,对source地址进行hash计算,再基于服务器总权重的取模,最终结果决定将此请 求转发至对应的后端服务器。 此方法是静态的,即不支持在线调整权重,不支持慢启动,可实现对后端服务器均衡调度 缺点是当服务器的总权重发生变化时,即有服务器上线或下线,都会因总权重发生变化而导致调度结果 整体改变hash-type 指定的默值为此算法

bash 复制代码
haproxy ~]# vim /etc/haproxy/haproxy.cfg
...
listen webserver_80
   bind *:80
   mode http
   balance source
   server webserver1 192.168.0.101:80 weight 1 check inter 3s fall 3 rise 5 
   server webserver2 192.168.0.102:80 weight 1 check inter 3s fall 3 rise 5
...
#不支持动态调整权重值
[root@haproxy ~]# echo "set weight webserver_80/webserver1 2" | socat stdio 
/var/lib/haproxy/haproxy.sock
Backend is using a static LB algorithm and only accepts weights '0%' and '100%'.
#只能动态上线和下线
[root@haproxy ~]# echo "set weight webserver_80/webserver1 0" | socat stdio 
/var/lib/haproxy/haproxy.sock
[root@haproxy ~]# echo "get weight webserver_80/webserver1" | socat stdio 
/var/lib/haproxy/haproxy.sock
0 (initial 1)
4.3.3一致性hash

一致性哈希,当服务器的总权重发生变化时,对调度结果影响是局部的,不会引起大的变动hash(o) mod n 该hash算法是动态的,支持使用 socat等工具进行在线权重调整,支持慢启动

算法:

bash 复制代码
1、后端服务器哈希环点keyA=hash(后端服务器虚拟ip)%(2^32)
2、客户机哈希环点key1=hash(client_ip)%(2^32) 得到的值在[0---4294967295]之间,
3、将keyA和key1都放在hash环上,将用户请求调度到离key1最近的keyA对应的后端服务器

hash环偏斜问题

bash 复制代码
增加虚拟服务器IP数量,比如:一个后端服务器根据权重为1生成1000个虚拟IP,再hash。而后端服务器权
重为2则生成2000的虚拟IP,再bash,最终在hash环上生成3000个节点,从而解决hash环偏斜问题

hash对象

Hash对象到后端服务器的映射关系:

一致性hash示意图

后端服务器在线与离线的调度方式

4.3.4uri

基于对用户请求的URI的左半部分或整个uri做hash,再将hash结果对总权重进行取模后

根据最终结果将请求转发到后端指定服务器

适用于后端是缓存服务器场景

默认是静态算法,也可以通过hash-type指定map-based和consistent,来定义使用取模法还是一致性 hash

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

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

4.3.2.1 uri 取模法配置示例

bash 复制代码
haproxy ~]# vim /etc/haproxy/haproxy.cfg
...
listen webserver_80
   bind *:80
   mode http
   balance uri
   hash-type consistent 加了就是动态算法,一致性hash
   server webserver1 172.25.250.10:80 weight 1 check inter 3s fall 3 rise 2 
   server webserver2 172.25.250.20:80 weight 1 check inter 3s fall 3 rise 2
4.3.5url_param

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

4.3.5.1 url_param取模法配置示例

bash 复制代码
haproxy ~]# vim /etc/haproxy/haproxy.cfg
...
listen webserver_80
   bind *:80
   mode http
   balance url_param name
   hash-type consistent 加了就是动态算法,一致性hash
   server webserver1 172.25.250.10:80 weight 1 check inter 3s fall 3 rise 2 
   server webserver2 172.25.250.20:80 weight 1 check inter 3s fall 3 rise 2
4.3.6算法总结
bash 复制代码
#静态
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     



#使用场景
first #使用较少
static-rr #做了session共享的web集群
roundrobin
random
leastconn #数据库
source
 
#基于客户端公网IP的会话保持
Uri--------------->http #缓存服务器,CDN服务商,蓝汛、百度、阿里云、腾讯
url_param--------->http #可以实现session保持

五、高级功能及配置

5.1haproxy基于cookie的会话粘滞

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

注释:不支持 tcp mode,使用 http mode

5.1.1配置选项
bash 复制代码
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的请求都发送到同一台后端服务器
5.1.2配置示例
bash 复制代码
.
.
.
listen  webserver
    bind    *:80
    mode    http
    balance roundrobin
    cookie WEBCOOKIE insert nocache indirec#
    server web1 172.25.250.10:80 check cookie servera inter 3s fall 3 rise 2
    server web2 172.25.250.20:80 check cookie serverb inter 3s fall 3 rise 2
.
.
.
5.1.3验证cookie信息
bash 复制代码
 curl -b WEBCOOKIE=servera 172.25.250.112 #指定cookie值实现会话粘滞
RS-1 172.25.250.10

5.2IP透传

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

5.2.1四层IP透传

基于真实服务器上web服务开启四层透传,走的是tcp协议

bash 复制代码
#vim /etc/haproxy/haproxy.cfg
listen  webserver
    bind    *:80
    mode    tcp
    balance roundrobin
    cookie WEBCOOKIE insert nocache indirect
    server web1 172.25.250.10:80 check cookie servera send-proxy inter 3s fall 3 rise 2
    server web2 172.25.250.20:80 check cookie serverb send-proxy inter 3s fall 3 rise 2
#send-proxy 会透传IP
bash 复制代码
#真实服务器上的配置
#vim /etc/nginx/nginx.conf
http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '"$proxy_protocol_addr"' #记录ip透传信息
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 4096;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf;

    server {
        listen       80 proxy_protocol;#proxy_protocol不允许直接访问,只能走代理
        listen       [::]:80;
        server_name  _;
        root         /usr/share/nginx/html;

客户端的IP透传过来了

5.2.2七层透传

在由haproxy发往后端主机的请求报文中添加"X-Forwarded-For"首部,其值为前端客户端的地址;用于 向后端主发送真实的客户端IP

bash 复制代码
option forwardfor [ except <network> ] [ header <name> ] [ if-none ]
[ except <network> ]:请求报请来自此处指定的网络时不予添加此首部,如haproxy自身所在网络
[ header <name> ]: 使用自定义的首部名称,而非"X-Forwarded-For",示例:X-client
[ if-none ] 如果没有首部才添加首部,如果有使用默认值

关闭后在看效果

5.3ACL

5.4自定义HAProxy错误页面

对指定的报错进行重定向,进行优雅的显示错误页面

使用errorfile和errorloc指令的两种方法,可以实现自定义各种错误页面

bash 复制代码
#haproxy默认使用的错误错误页面
[root@haproxy ~]# rpm -ql haproxy24z-2.4.27-1.el7.zenetys.x86_64 | grep -E http$
/usr/share/haproxy/400.http
/usr/share/haproxy/403.http
/usr/share/haproxy/408.http
/usr/share/haproxy/500.http
/usr/share/haproxy/502.http
/usr/share/haproxy/503.http
/usr/share/haproxy/504.http
5.4.1基于自定义的错误页面
bash 复制代码
[root@cle ~]# mkdir /etc/haproxy/errorpage/
[root@cle ~]# cp /usr/share/haproxy/503.http /etc/haproxy/errorpage/ #自定义错误页面
[root@cle ~]# vim /etc/haproxy/errorpage/503.http

HTTP/1.0 503 Service Unavailable
Cache-Control: no-cache
Connection: close
Content-Type: text/html

<html><body><h1>杯莫停</h1>
the poem is very famous in china.
</body></html>


[root@cle ~]# vim /etc/haproxy/haproxy.cfg
。
defaults
。。。
 errorfile   503     /etc/haproxy/errorpage/503.http #重定向错误页
    #errorloc  503 http://www.baidu.com   #重定向资源路径
。。。


关闭后端真实服务器测试,

重定向资源路径到百度

5.5 HAProxy 四层负载

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

bash 复制代码
MySQL
Redis
Memcache
RabbitMQ

四层负载示例

注意:如果使用frontend和backend,一定在 frontend 和 backend 段中都指定mode tcp

bash 复制代码
listen mysqlserver
   bind *:3306
   mode tcp
   balance leastconn
   server server1 172.25.250.10:3306 check
   server server2 172.25.250.20:3306 check 
   #或者
frontend sqlserver
	bind	*:3306
	mode	tcp
	use_backend	sql_rs
backend	sql_rs
	balance	roundrobin
	server	server1172.25.250.10:3306 check
	server server2 172.25.250.20:3306 check
	
#后端真实服务器需安装提供msyql服务的程序-mariadb
rs1 ~]# yum install mariadb-server -y
rs2 ~]# yum install mariadb-server -y
rs1 ~]# vim /etc/my.cnf
[mysqld]
server-id=10 #在另一台主机为
rs2 ~]# vim /etc/my.cnf
[mysqld]
server-id=20 #在另一台主机为
rs1 ~]# systemctl start mariadb
rs2 ~]# systemctl start mariadb
rs1 ~]# mysql -e "grant all on *.* to gee@'%' identified by 'gee';"
rs2 ~]# mysql -e "grant all on *.* to gee@'%' identified by 'gee';"
测试:

5.6HAproxy https实现

haproxy可以实现https的证书安全,从用户到haproxy为https,从haproxy到后端服务器用http通信 但基于性能考虑,生产中证书都是在后端服务器比如nginx上实现

bash 复制代码
#配置HAProxy支持https协议,支持ssl会话;
 bind *:443 ssl crt /PATH/TO/SOME_PEM_FILE 
#指令 crt 后证书文件为PEM格式,需要同时包含证书和所有私钥
 cat demo.key demo.crt > demo.pem 
#把80端口的请求重向定443
 bind *:80
 redirect scheme https if !{ ssl_fc }
5.6.1制作证书
bash 复制代码
openssl req -newkey rsa:2048 -nodes -sha256 -keyout /etc/haproxy/certs/gee.key -x509 -days 356 -out /etc/haproxy/certs/gee.crt
#-nodes 服务开启或关闭免密认证 -sha256:md5sha256非对称加密

#把证书和私钥放到同一文件中
[root@cle certs]# ll
总用量 8
-rw-r--r-- 1 root root 1391  7月 28 20:56 gee.crt
-rw------- 1 root root 1704  7月 28 20:52 gee.key
-rw-r--r-- 1 root root    0  7月 28 20:57 gee.pem
[root@cle certs]# cat gee.key gee.crt > gee.pem
5.6.2https配置示例
bash 复制代码
[root@cle certs]# vim /etc/haproxy/haproxy.cfg
frontend web-443
    bind *:443 ssl crt /etc/haproxy/certs/gee.pem #私钥和证书存放的路径
    mode http
    use_backend server-443
backend server-443
    balance roundrobin
    server app1 172.25.250.10:80 check inter 2s fall 3 rise 2
    server app2 172.25.250.20:80 check inter 2s fall 3 rise 2

#重启服务
[root@cle certs]# systemctl restart haproxy.service
#测试
curl -k https://172.25.250.112 #客户一般不会这样访问

#把客户端的scheme重定向到https
frontend-80
    bind    *:80
    mode    http
    redirect scheme https if !{ ssl_fc }
    use_backend server-443

#重启服务测试
curl -ik http://172.25.250.112  #-i 查看报文信息,非内容,如果想查看内容加-v
#浏览器测试

证书信息

1 root root 0 7月 28 20:57 gee.pem

root@cle certs\]# cat gee.key gee.crt \> gee.pem [外链图片转存中...(img-RjKPT7sU-1753710769671)] #### 5.6.2https配置示例 ```bash [root@cle certs]# vim /etc/haproxy/haproxy.cfg frontend web-443 bind *:443 ssl crt /etc/haproxy/certs/gee.pem #私钥和证书存放的路径 mode http use_backend server-443 backend server-443 balance roundrobin server app1 172.25.250.10:80 check inter 2s fall 3 rise 2 server app2 172.25.250.20:80 check inter 2s fall 3 rise 2 #重启服务 [root@cle certs]# systemctl restart haproxy.service #测试 curl -k https://172.25.250.112 #客户一般不会这样访问 #把客户端的scheme重定向到https frontend-80 bind *:80 mode http redirect scheme https if !{ ssl_fc } use_backend server-443 #重启服务测试 curl -ik http://172.25.250.112 #-i 查看报文信息,非内容,如果想查看内容加-v #浏览器测试 \[外链图片转存中...(img-vYQRGgk5-1753710769671)

外链图片转存中...(img-nhKmFCos-1753710769671)

外链图片转存中...(img-c779d8m4-1753710769671)

外链图片转存中...(img-uQAoof7S-1753710769671)

证书信息

外链图片转存中...(img-UJVbNACv-1753710769671)

相关推荐
宴之敖者、22 分钟前
Linux——\r,\n和缓冲区
linux·运维·服务器
LuDvei23 分钟前
LINUX错误提示函数
linux·运维·服务器
未来可期LJ30 分钟前
【Linux 系统】进程间的通信方式
linux·服务器
Abona31 分钟前
C语言嵌入式全栈Demo
linux·c语言·面试
心理之旅41 分钟前
高校文献检索系统
运维·服务器·容器
Lenyiin44 分钟前
Linux 基础IO
java·linux·服务器
The Chosen One9851 小时前
【Linux】深入理解Linux进程(一):PCB结构、Fork创建与状态切换详解
linux·运维·服务器
大佐不会说日语~1 小时前
使用Docker Compose 部署时网络冲突问题排查与解决
运维·网络·spring boot·docker·容器
Kira Skyler1 小时前
eBPF debugfs中的追踪点format实现原理
linux
2501_927773072 小时前
uboot挂载
linux·运维·服务器