目录
一、HAproxy介绍
1. 概述
2. 关于4/7层负载均衡
2.1 无负载均衡
2.1.1 图示
2.1.2 说明
2.2 四层负载均衡
2.2.1 图示
2.2.2 说明
2.3 七层负载
2.3.1 图示
2.3.2 说明
3. 特性
4. HAProxy负载均衡常见策略
5. 处理模式
二、HAproxy安装
1. yum安装
2. 第三方安装包
3. 编译安装
三、HAproxy配置与调优
1. 配置文件详解
2. global配置
2.1 状态页
2.2 指定进程线程个数
2.3 cpu亲缘性
2.4 日志
2.4.1 指定本地路径
2.4.2 指定远端路径
2.5 Proxies配置
2.5.1 Proxies配置-defaults
2.5.2 Proxies配置-listen 简化配置
一、HAproxy介绍
1. 概述
HAProxy提供高可用性、负载均衡以及基于TCP和HTTP应用的代理,支持虚拟主机,它是免费、快速并且可靠的一种解决方案。HAProxy特别适用于那些负载特大的web站点, 这些站点通常又需要会话保持或七层处理。HAProxy运行在当前的硬件上,完全可以支持数以万计的并发连接。并且它的运行模式使得它可以很简单安全的整合进您当前的架构中, 同时可以保护你的web服务器不被暴露到网络上。
支持的功能:
- TCP 和 HTTP反向代理
- SSL/TSL服务器
- 可以针对HTTP请求添加cookie,进行路由后端服务器
- 可平衡负载至后端服务器,并支持持久连接
- 支持所有主服务器故障切换至备用服务器 keepalive
- 支持专用端口实现监控服务
- 支持停止接受新连接请求,而不影响现有连接
- 可以在双向添加,修改或删除HTTP报文首部字段
- 响应报文压缩
- 支持基于pattern实现连接请求的访问控制
- 通过特定的URI(url)为授权用户提供详细的状态信息
2. 关于4/7层负载均衡
2.1 无负载均衡
没有负载平衡的简单Web应用程序环境可能如下所示
2.1.1 图示
2.1.2 说明
在此示例中,用户直接连接到Web服务器,在yourdomain.com上,并且没有负载平衡。如果单个Web服务器出现故障,用户将无法再访问Web服务器。此外,如果许多用户试图同时访问服务器并且无法处理负载,他们可能会遇到缓慢的体验,或者可能根本无法连接。
2.2 四层负载均衡
将网络流量负载,平衡到多个服务器的最简单方法,是使用第4层(传输层)负载平衡。以这种方式进行负载均衡将根据IP范围和端口转发用户流量(即,如果请求进入http://yourdomain.com/anything,则流量将转发到处理yourdomain.com的所有请求的后端。端口80)。
2.2.1 图示
2.2.2 说明
用户访问负载均衡器,负载均衡器将用户的请求转发给后端服务器的Web后端组。无论选择哪个后端服务器,都将直接响应用户的请求。通常,Web后端中的所有服务器应该提供相同的内容 - 否则用户可能会收到不一致的内容。
2.3 七层负载
7层负载平衡是更复杂的负载均衡网络流量的方法是使用第7层(应用层)负载均衡。使用第7层允许负载均衡器根据用户请求的内容将请求转发到不同的后端服务器。这种负载平衡模式允许您在同一域和端口下运行多个Web应用程序服务器。
2.3.1 图示
2.3.2 说明
示例中,如果用户请求yourdomain.com/blog,则会将其转发到博客后端,后端是一组运行博客应用程序的服务器。其他请求被转发到web-backend,后端可能正在运行另一个应用程序。
3. 特性
① 支持tcp / http 两种协议层的负载均衡,使得其负载均衡功能非常丰富
② 支持8种左右的负载均衡算法,尤其是在http模式时,有许多非常实在的负载均衡算法,适用各种需求
③ 性能非常优秀,基于事件驱动的链接处理模式及单进程处理模式(和Nginx类似)让其性能卓越。
④ 拥有一个功能出色的监控页面,实时了解系统的当前状况
⑤ 功能强大的ACL支持,给用户极大的方便
4. HAProxy负载均衡常见策略
① Round Robin(轮询):按照请求顺序依次将请求分发给后端服务器;static-rr,表示根据权重
② Least Connections(最小连接数):将请求发送到当前连接数最少的服务器上,以确保负载更加均衡。
③ Source(源IP):根据客户端的源IP地址来决定将请求发送到哪台后端服务器上,这样可以确保相同的客户端IP每次都会被发送到相同的后端服务器。
④ URI(基于URI):根据请求中的URI信息来进行负载均衡,通常用于特定类型的应用或者内容分发。
⑤ URL参数:类似于URI策略,但是它会考虑URL参数来进行负载均衡。
⑥ Static-rr(静态轮询):类似于Round Robin,但是在长期运行的负载均衡环境中,该策略会尽量避免频繁的切换。
⑦ Cookie(基于Cookie):根据请求中的Cookie信息来进行负载均衡,适用于需要会话保持的场景。
⑧ Custom(自定义):HAProxy还支持自定义负载均衡策略,管理员可以根据具体需求编写自己的负载均衡算法。
5. 处理模式
单进程处理模式:
所有客户端连接全部都由同一个服务进程来处理,目标就是等待连接,来一个分配一个,主要消耗cpu
多进程模式:
适合于需要更好利用多核处理器的情况,多进程模式可以充分利用硬件资源,但需要更多的系统资源以及进程间通信开销。
多线程处理模式:
适合于需要更好利用多核处理器的情况,相比多进程模式,多线程模式可以减少一些进程间通信的开销,但需要更复杂的线程管理和同步机制。
二、HAproxy安装
1. yum安装
CentOS 7 的默认的base仓库中包含haproxy的安装包文件,但是版本比较旧,是1.5.18的版本,距离当前版本已经有较长时间没有更新,由于版本比较旧所以有很多功能不支持,如果对功能和性能没有要求可以使用此版本,否则推荐使用新版本。
[root@localhost ~]# yum list haproxy #列出所有可用的软件包
已加载插件:fastestmirror, langpacks
Loading mirror speeds from cached hostfile
* base: mirrors.ustc.edu.cn
* epel: mirrors.bfsu.edu.cn
* extras: mirrors.ustc.edu.cn
* updates: mirrors.ustc.edu.cn
可安装的软件包
haproxy.x86_64 1.5.18-9.el7_9.1 update
[root@localhost ~]# yum provides haproxy #搜索可用的软件包列表,包括软件包名称、版本和来源等
已加载插件:fastestmirror, langpacks
Loading mirror speeds from cached hostfile
* base: mirrors.ustc.edu.cn
* epel: mirror.nju.edu.cn
* extras: mirrors.ustc.edu.cn
* updates: mirrors.ustc.edu.cn
haproxy-1.5.18-9.el7.x86_64 : TCP/HTTP proxy and load balancer for high availability environments
源 :base
haproxy-1.5.18-9.el7_9.1.x86_64 : TCP/HTTP proxy and load balancer for high availability environments
源 :updates
haproxy-1.5.18-9.el7_9.1.x86_64 : TCP/HTTP proxy and load balancer for high availability environments
源 :@updates
[root@localhost ~]# yum install haproxy -y
已安装:
haproxy.x86_64 0:1.5.18-9.el7_9.1
[root@localhost ~]# systemctl start haproxy.service
2. 第三方安装包
官方没有提供rpm相关的包,可以通过第三方仓库的rpm包
从第三方网站下载rpm包:https://pkgs.org/download/haproxy,基于互联网第三方仓库在线安装
[root@localhost data]# ls
keepalived.log rh-haproxy18-haproxy-1.8.24-3.el7.x86_64.rpm rh-haproxy18-runtime-3.1-2.el7.x86_64.rpm
[root@localhost data]# yum install rh-haproxy18-runtime-3.1-2.el7.x86_64.rpm -y #依赖包
[root@localhost data]# yum install rh-haproxy18-haproxy-1.8.24-3.el7.x86_64.rpm -y
已安装:
rh-haproxy18-haproxy.x86_64 0:1.8.24-3.el7
[root@localhost data]# systemctl start rh-haproxy18-haproxy.service
第三方yum仓库:
yum install centos-release-scl-rh
yum install rh-haproxy18-haproxy
3. 编译安装
编译安装HAProxy 2.0 LTS版本,更多源码包下载地址:http://www.haproxy.org/download/
AProxy 支持基于lua实现功能扩展, 由于CentOS7 之前版本自带的lua版本比较低并不符合HAProxy要求的lua最低版本(5.3)的要求,因此需要编译安装较新版本的lua环境,然后才能编译安装HAProxy。
① 查看本地lua语言版本,安装依赖环境
[root@localhost ~]# lua -v
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
[root@localhost ~]# yum -y install gcc openssl-devel pcre-devel systemd-devel
② 访问官网下载新版本Lua: download
③ 查看安装方法,并安装
[root@localhost data]# curl -L -R -O https://www.lua.org/ftp/lua-5.4.6.tar.gz
[root@localhost data]# ls
lua-5.4.6.tar.gz
[root@localhost data]# tar zxf lua-5.4.6.tar.gz
[root@localhost data]# ls
lua-5.4.6 lua-5.4.6.tar.gz
[root@localhost data]# cd lua-5.4.6
[root@localhost lua-5.4.6]# make all
[root@localhost lua-5.4.6]# cd ..
[root@localhost data]# ls
lua-5.4.6 lua-5.4.6.tar.gz
[root@localhost data]# ln -s lua-5.4.6 lua
[root@localhost data]# ls
lua lua-5.4.6 lua-5.4.6.tar.gz
④ 官网下载HAproxy源码包
⑤ 查看说明,安装
[root@localhost data]# cd haproxy-2.4.25/
[root@localhost haproxy-2.4.25]# cat INSTALL
[root@localhost haproxy-2.4.25]# make ARCH=x86_64 TARGET=linux-glibc USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 USE_SYSTEMD=1 USE_LUA=1 LUA_INC=/data/lua/src/ LUA_LIB=/data/lua/src/
[root@localhost haproxy-2.4.25]# make install PREFIX=/apps/haproxy
[root@localhost haproxy-2.4.25]# ls /apps/haproxy/
doc sbin share
[root@localhost haproxy-2.4.25]# ln -s /apps/haproxy/sbin/haproxy /usr/sbin/
[root@localhost haproxy-2.4.25]# haproxy -v
HAProxy version 2.4.25-6cfe787 2023/12/14 - https://haproxy.org/
⑥ 配置system服务
[root@localhost ~]# tee /usr/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
> LimitNOFILE=100000
>
> [Install]
> WantedBy=multi-user.target
>
> eof
⑦ 创建配置文件
[root@localhost ~]# mkdir /etc/haproxy
[root@localhost ~]# mkdir /var/lib/haproxy
[root@localhost ~]# vim /etc/haproxy/haproxy.cfg
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 haadmin:123456
listen web_port
bind 0.0.0.0:8899
mode http
log global
server web1 127.0.0.1:8080 check inter 3000 fall 2 rise 5
⑧ 设置用户和目录权限,立即启动并自启
[root@localhost ~]# useradd -r -s /sbin/nologin haproxy
[root@localhost ~]# id haproxy
uid=990(haproxy) gid=985(haproxy) 组=985(haproxy)
[root@localhost ~]# systemctl enable --now haproxy
三、HAproxy配置与调优
HAProxy 的配置文件haproxy.cfg由两大部分组成,分别是global和proxies部分
global:全局配置段
进程及安全配置相关的参数
性能调整相关参数调优
Debug参数
proxies:代理配置段(块)
defaults:为frontend, backend, listen提供默认配置
frontend:前端,相当于nginx中的server {},定义虚拟机,监听分配请求
backend:后端,相当于nginx中的upstream {},真实服务器
listen:同时拥有前端和后端配置,配置简单,生产推荐使用
1. 配置文件详解
配置文件目录:/etc/haproxy/haproxy.cfg
global #全局部分
maxconn 100000 #最大并发连接数为 100,000
chroot /apps/haproxy #在启动后将当前目录更改为 /apps/haproxy,锁定运行目录
stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin
#定义用于统计的 UNIX 套接字,并设置了受限访问权限
uid 99 #设置 HAProxy 运行时的用户和组ID
gid 99
daemon #以守护进程的形式在后台运行 HAProxy
#nbproc 4 #开启4个进程
#cpu-map 1 0 #cpu亲缘性
#cpu-map 2 1
#cpu-map 3 2
#cpu-map 4 3
maxconn n #每个haproxy进程的最大并发连接数
maxsslconn n #每个haproxy进程ssl最大连接数,用于haproxy配置了证书的场景下
maxconnrate n #每个进程每秒创建的最大连接数量
spread-checks n #后端server状态check随机提前或延迟百分比时间,建议2-5(20%-50%)之间,默认值0
pidfile /var/lib/haproxy/haproxy.pid #指定主进程的进程 ID 文件位置
log 127.0.0.1 local3 info #将日志消息发送到指定地址和 "info" 级别的设施
defaults #默认部分
option http-keep-alive #启用 HTTP keep-alive 以提高性能
option forwardfor #添加 X-Forwarded-For 头部以转发给服务器的请求
maxconn 100000 #将最大并发连接数设置为 100,000
mode http #为所有后续的 listen 部分设置模式为 HTTP
timeout connect 300000ms #配置连接、客户端和服务器交互的各种超时时间
timeout client 300000ms
timeout server 300000ms
listen stats #监听统计信息部分
mode http #为此监听器设置模式为 HTTP
bind 0.0.0.0:9999 #将监听器绑定到端口 9999 上的所有可用 IPv4 地址
stats enable #启用此监听器上的统计信息
log global #将日志发送到全局日志设置
stats uri /haproxy-status #设置访问统计信息的 URI
stats auth haadmin:123456 #为访问统计信息设置基本身份验证凭据
listen web_port #监听 web_port 部分
bind 0.0.0.0:8899 #将监听器绑定到端口 8899 上的所有可用 IPv4 地址
mode http #为此监听器设置模式为 HTTP
log global #将日志发送到全局日志设置
server web1 127.0.0.1:8080 check inter 3000 fall 2 rise 5
定义名为 "web1" 的服务器,位于本地 8080 端口,带有健康检查
2. global配置
2.1 状态页
listen stats
mode http
bind 0.0.0.0:9999
stats enable
log global
stats uri /haproxy-status
stats auth haadmin:123456
访问http://192.168.190.100:9999/haproxy-status
2.2 指定进程线程个数
进程与线程会有冲突,即如果开启单进程可以多线程,但是开启多进程则无法开启线程。
nbproc n #开启的haproxy work 进程数,默认进程数是一个
#nbthread 1 #和多进程 nbproc配置互斥(版本有关,CentOS8的haproxy1.8无此问题),指定每个haproxy进程开启的线程数,默认为每个进程一个线程
#如果同时启用nbproc和nbthread 会出现以下日志的错误,无法启动服务
默认未开启进程:
[root@localhost ~]# pstree -p | grep haproxy
|-haproxy(4186)---haproxy(4192)---{haproxy}(4193)
主进程 worker进程 线程
开启进程后:
[root@localhost ~]# vim /etc/haproxy/haproxy.cfg
nbproc 2 #根据cpu核心数修改
[root@localhost ~]# systemctl restart haproxy.service
[root@localhost ~]# pstree -p | grep haproxy
|-haproxy(42377)-+-haproxy(42380)
| `-haproxy(42381)
2.3 cpu亲缘性
CPU亲缘性是指操作系统和硬件平台提供的一种特性,用于控制进程或线程与特定处理器核心之间的关联关系。这种关联可以影响性能和资源利用情况。
nbproc 2
cpu-map 1 0 #绑定haproxy worker 进程至指定CPU,将第1个work进程绑定至0号CPU
cpu-map 2 1 #绑定haproxy worker 进程至指定CPU,将第2个work进程绑定至1 号CPU ps axo pid,cmd,psr |grep haprox
修改前cpu与进程和线程的绑定关系是随机的:
[root@localhost ~]# ps axo pid,cmd,psr | grep haproxy
42377 /usr/sbin/haproxy -Ws -f /e 0
42380 /usr/sbin/haproxy -Ws -f /e 1
42381 /usr/sbin/haproxy -Ws -f /e 0
42468 grep --color=auto haproxy 1
[root@localhost ~]# ps axo pid,cmd,psr | grep haproxy
42377 /usr/sbin/haproxy -Ws -f /e 1
42380 /usr/sbin/haproxy -Ws -f /e 1
42381 /usr/sbin/haproxy -Ws -f /e 0
42470 grep --color=auto haproxy 0
修改global参数:
root@localhost ~]# vim /etc/haproxy/haproxy.cfg
nbproc 2
cpu-map 1 0
cpu-map 2 1
[root@localhost ~]# systemctl restart haproxy.service
查看进程详情:cpu核心号与进程保持绑定
[root@localhost ~]# ps axo pid,cmd,psr | grep haproxy
42517 /usr/sbin/haproxy -Ws -f /e 1
42522 /usr/sbin/haproxy -Ws -f /e 0
42523 /usr/sbin/haproxy -Ws -f /e 1
42525 grep --color=auto haproxy 0
[root@localhost ~]# ps axo pid,cmd,psr | grep haproxy
42517 /usr/sbin/haproxy -Ws -f /e 1
42522 /usr/sbin/haproxy -Ws -f /e 0
42523 /usr/sbin/haproxy -Ws -f /e 1
42527 grep --color=auto haproxy 0
2.4 日志
HAproxy本身不记录客户端的访问日志,此外为减少服务器负载,一般生产中HAProxy不记录日志,也可以配置HAProxy利用rsyslog服务记录日志到指定日志文件中。
haproxy默认日志文件路径:/var/log/messages
2.4.1 指定本地路径
① 在配置文件第14行已经定义了 log 127.0.0.1 local3 info 级别
② 修改系统日志管理工具服务的配置文件
[root@localhost ~]# vim /etc/rsyslog.con
15 $ModLoad imudp #模块加载指令,用于加载 imudp 模块。imudp 模块是 rsyslog 的输入模块之一,它允许接收通过 UDP 协议发送的日志消息
16 $UDPServerRun 514 #配置 rsyslog 服务监听 UDP 端口 514 的指令。默认情况下,rsyslog 会监听 UDP 514 端口以接收通过 UDP 发送的日志消息。
#取消注释15,16行
74 local3.* /var/log/haproxy.log
#指定配置文件保存路径
[root@localhost ~]# systemctl restart haproxy.service rsyslog.service
③ 查看新路径是否生成日志
[root@localhost ~]# ll /var/log/haproxy.log
-rw-------. 1 root root 650 3月 10 21:48 /var/log/haproxy.log
2.4.2 指定远端路径
由于haproxy只能做单一的代理服务,建议将日志文件存放在远端日志服务器。
① 修改配置文件
[root@localhost ~]# vim /etc/haproxy/haproxy.cfg
log 192.168.190.101 local6 info
② 修改远端服务器系统日志管理工具服务的配置文件
[root@localhost ~]# vim /etc/rsyslog.conf
15 $ModLoad imudp
16 $UDPServerRun 514
74 local6.* /var/log/haproxy.log
[root@localhost ~]# systemctl restart rsyslog.service
③ 重启haproxy服务,查看日志服务器内容
haproxy代理端:
[root@localhost ~]# systemctl restart haproxy.service
日志服务器:
[root@localhost ~]# ll /var/log/haproxy.log
-rw-------. 1 root root 337 3月 10 22:00 /var/log/haproxy.log
2.5 Proxies配置
在HAProxy中,proxies部分通常用于定义服务器池和负载均衡策略。
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配置更简洁,生产常用
2.5.1 Proxies配置-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,建议和timeout server相同
timeout check 5s #对后端服务器的默认检测超时时间
default-server inter 1000 weight 3 #指定后端服务器的默认设置
2.5.2 Proxies配置-listen 简化配置
使用listen替换 frontend和backend的配置方式,可以简化设置,通常只用于TCP协议的应用
#官网业务访问入口
listen WEB_PORT_80 #业务名称
bind 10.0.0.7:80 #ip加端口
mode http #默认 可以不写
option forwardfor #透传客户端真实IP至后端web服务器
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
示例:
① 修改haproxy配置
listen web_port_80
bind 192.168.190.100:80
mode http
log global
server sr1 192.168.190.101:80
server sr1 192.168.190.102:80
② 后端服务器创建web文件
[root@localhost ~]# systemctl start httpd
[root@localhost ~]# echo 7-1 > /var/www/html/index.htm
[root@localhost ~]# systemctl start httpd
[root@localhost ~]# echo 7-2 > /var/www/html/index.html
③ 访问代理端
[root@localhost ~]# curl 192.168.190.100
7-1
[root@localhost ~]# curl 192.168.190.100
7-2
[root@localhost ~]# curl 192.168.190.100
7-1
[root@localhost ~]# curl 192.168.190.100
7-2
加入健康性检测 check
① 加入前,模拟sr1故障,测试访问
[root@localhost ~]# curl 192.168.190.100
<html><body><h1>503 Service Unavailable</h1>
No server is available to handle this request.
</body></html>
[root@localhost ~]# curl 192.168.190.100
7-2
② 加入健康检测
[root@localhost ~]# vim /etc/haproxy/haproxy.cfg
listen web_port_80
bind 192.168.190.100:80
mode http
log global
server rs1 192.168.190.101:80 check
server rs2 192.168.190.102:80 check
[root@localhost ~]# systemctl restart haproxy.service
③ 再次访问
[root@localhost ~]# curl 192.168.190.100
7-2
[root@localhost ~]# curl 192.168.190.100
7-2
[root@localhost ~]# curl 192.168.190.100
7-2
[root@localhost ~]# curl 192.168.190.100