负载均衡Haproxy

简介

HAProxy是一款高性能、开源的负载均衡器反向代理服务器 ,主要用于 HTTPTCP 等协议的流量分发,广泛应用于高并发高可用的网络架构中

HAProxy是法国威利塔罗(Willy Tarreau)使用C语言开发的一个开源软件

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

社区版:https://www.haproxy.org/

GitHub:https://github.com/haprox

配置

官方文档:https://docs.haproxy.org/

配置文件:/etc/haproxy/haproxy.cfg

Haproxy配置由两大部分组成,分别是

全局配置段:global 代理配置段:proxies
进程及安全配置相关参数 defaults段:为frontend、backend、listen提供默认配置
性能调整相关参数 frontend段:前端配置
Debug参数 backend段:后端配置
listen:前端 + 后端配置,生成推荐使用

global部分

配置名 数值 功能
log 127.0.0.1 local2 全局的syslog服务器,最多定义两个,需要开启UDP协议
chroot /var/lib/haproxy 指定运行目录
pidfile /var/run/haproxy.pid 指定pid文件路径
maxconn 4000 每个Haproxy进程的最大并发连接数
maxsslconn n 每个Haproxy进程ssl最大连接数,适用于haproxy配置证书的情况下
maxconnrate n 每个进程每秒创建的最大连接数量
nbproc n 开启Haproxy worker进程数,默认一个
cpu-map 1 0 绑定Haproxy worker进程到指定CPU
cpu-map 2 1 将2个work进程绑定到1号CPU上
nbthread(与nbproc互斥) n 每个Haproxy进程的线程数,默认1进程1线程
user,group,uid,gid haproxy,haproxy,xxx,xxx 运行Haproxy的用户身份
spread-checks n 后端Server状态check随机提前或延迟百分比时间,建议20%-50%之间,默认值0
daemon 以守护进程运行
stats socket /var/lib/haproxy/stats /var/lib/haproxy/stats 套接字文件
ssl-default-bind-ciphers PROFILE=SYSTEM PROFILE=SYSTEM HAProxy作为服务器使用的加密套件
ssl-default-bind-ciphers PROFILE=SYSTEM ssl-default-server-ciphers PROFILE=SYSTEM PROFILE=SYSTEM HAProxy作为客户端使用的加密套件
多进程
bash 复制代码
[root@Haproxy ~]# yum install haproxy -y
[root@Haproxy ~]# systemctl enable --now haproxy
[root@Haproxy ~]# pstree -p | grep haproxy
复制代码
[root@Haproxy ~]# vim /etc/haproxy/haproxy.cfg
stats socket /var/lib/haproxy/stats
nbproc  2
cpu-map 1   0
cpu-map 2   1
[root@Haproxy ~]# systemctl restart haproxy.servic
[root@Haproxy ~]# pstree -p | grep haproxy

多进程和多线程互斥,两个不能同时配置

多线程
bash 复制代码
# 未开启多线程时
[root@Haproxy ~]# pstree -p | grep haproxy
[root@Haproxy ~]# cat /proc/31104/status | grep Threads
bash 复制代码
# 开启多线程时
[root@Haproxy ~]# vim /etc/haproxy/haproxy.cfg
stats socket /var/lib/haproxy/stats
nbthread    3
[root@Haproxy ~]# systemctl restart haproxy.service
bash 复制代码
[root@Haproxy ~]# pstree -p | grep haproxy
           |-haproxy(31186)---haproxy(31188)-+-{haproxy}(31189)
           |                                 `-{haproxy}(31190)
[root@Haproxy ~]# cat /proc/31188/status | grep Threads
Threads:        3
[root@Haproxy ~]# cat /proc/31189/status | grep Threads
Threads:        3

proxies部分

又细分为三小段;listen段将fronted和backend合并

配置段 功能
defaults 默认配置项;针对frontend、backend、listen生效
frontend 前端Servername,类似LVS的服务集群
backup 后端RealServer,类似LVS的RS服务器
listen 将frontend和backup合并配置
defaults段
配置名 数值 功能
defaults name 默认配置项,可以有多个name,也可以没有
mode http 使用的连接协议
log global 指定日志地址和记录日志的设备; global:使用global段中的log值
option httplog 日志记录选项; httplog:记录与HTTP相关属性值
option dontlognull 不记录空会话连接日志
option http-server-close 等待客户端完整HTTP请求的时间,此处等待10s
option forwardfor except 127.0.0.0/8 透传客户端真实IP到后端Web服务器;except 127.0.0.0/8:排除内网IP
option redispatch 当服务器不可用时,将请求重新分发到其他服务器(默认只重试一次)
option http-keep-alive 启用HTTP长连接支持,即会话保持
retries 3 连接后端服务器失败时的重试次数
timeout http-request 10s 等待客户端请求完全被接收和处理的最长时间
timeout queue 1m 请求在队列中等待的最长时间
timeout connect 10s 连接后端服务器的超时时间
timeout client 1m 客户端空闲超时时间,即允许客户端处于既不接收也不发送数据的非活动时间
timeout server 1m 服务器空闲超时时间,即允许服务器处于既不接收也不发送数据的非活动时间
timeout http-keep-alive 10s HTTP长连接的空闲超时时间
timeout check 10s 后端服务器健康检查的超时时间
maxconn 3000 每个进程允许的最大并发连接数
default-server inter 1000 weight 3 为所有后端服务器设置默认参数 inter 1000 表示健康检查间隔为 1秒 weight 3 表示默认权重为 3
frontend段
bash 复制代码
frontend name
	bind *:80
	mode http
	use_backend use_name
配置名 数值 功能
frontend xxx 定义frontend的名字
bind IP:Port,... 指定Haproxy监听地址;支持IPV4和IPV6;支持同时监听多个端口 如果需要绑定在非本机的IP,需要开启内核参数:net.ipv4.ip_nonlocal_bind=1
mode http、tcp、udp... 指定负载协议类型;frontend与调用的backend保持一致
use_backend backend name 将请求转发到backend name后端
backlog <back log> 当前端服务器的连接数达到上限时,等待处理的连接请求的后援队列长度 用于高并发场景下缓冲过量的连接请求,避免直接拒绝客户端连接 不支持backend
backend段

backend名称必须唯一,且必须在listen或fronted中事先定义才能使用,否则服务报错

bash 复制代码
backend name
	mode http
	server name 192.168.0.87:80 check inter 3s fall 3 rise 5
	server name 192.168.0.89:80 check inter 3s fall 3 rise 5
option参数 功能
httpchk 通过发送 HTTP 请求并验证响应状态码来检查服务健康
smtpchk 通过 SMTP 协议握手验证邮件服务器可用性
mysql-check 通过 MySQL 协议验证数据库服务可用性
pgsql-check 通过 PostgreSQL 协议验证数据库服务可用性
ssl-hello-chk 验证服务器是否能正常完成 SSL/TLS 握手,用于 HTTPS 服务
Server行
参数 功能
name 本行server的名字
addr 指定server的IP,可以是专门的数据网段
port 指定server的端口
check 对当前server进行健康状态检查,默认不开启检查; 对相应的IP和端口利用TCP连接进行周期性健康险检查 必须指定端口才能实现健康检查
inter 健康状态检查间隔时间,默认2000ms
fall 连续健康检查失败 n 次后标记为下线,默认 3
rise 连续健康检查成功 n 次后标记为上线,默认 2
weight 默认为1,最大256;0 表示不参与负载均衡,但能接受持久连接
backup 标记server为备份状态;仅当其他服务器全部宕机时提供服务
disabled 将server标记为不可用状态,即维护状态保留持久连接,不再接受新请求,状态页显示深黄色
pedirect <preix> 将请求临时重定向到其他URL,只适用于HTTP模式
maxconn 单server的最大并发连接数
listen段

通常只用于TCP协议的应用,是前两者的结合配置

bash 复制代码
listen name
	bind 192.168.0.87:80
	mode http
	balance static-rr	# 使用的负载均衡算法
	server mariadb1 192.168.0.87:3306 check inter 3s fall 3 rise 5
	server mariadb2 192.168.0.89:3306 check inter 3s fall 3 rise 5

socat工具

Socat 是 Linux 下的一个多功能的网络工具

它可以在两个数据流之间建立连接并转发数据,且支持众多协议和链接方式

可以对服务器权重和状态进行动态调整

基本应用

修改配置文件后,才能正常使用,默认情况下只能查看,不能进行修改

当Haproxy使用特定负载算法时,无法动态调整服务器权重

bash 复制代码
[root@Haproxy ~]# vim /etc/haproxy/haproxy.cfg
# turn on stats unix socket
stats socket /var/lib/haproxy/stats mode 600 level admin
[root@Haproxy ~]# systemctl restart haproxy.service
bash 复制代码
[root@Haproxy ~]# yum install socat -y
# 查看帮助
[root@Haproxy ~]# echo "help" | socat stdio /var/lib/haproxy/stats
disable server: disable a server for maintenance	# 下线服务器
enable server : enable a disabled server	# 上线服务器
set server : change a server's state, weight or address	# 修改状态、权重、IP
get weight : report a server's current weight	# 查看权重
set weight : change a server's weight (deprecated)	# 修改权重
......
bash 复制代码
# 查看Haproxy全局信息(Uptime、Maxsock、CurrConns...)
echo "show info" | socat stdio /var/lib/haproxy/stats
# 查看集群状态
echo "show servers state" | socat stdio /var/lib/haproxy/stats
# 查看集群权重
echo "get weight nginx/static" | socat stdio /var/lib/haproxy/stats
1 (initial 1)	# 当前动态权重(配置文件中设置的初始权重)
# 设置权重(范围为0 - 256)
echo "set weight nginx/static 3" | socat stdio /var/lib/haproxy/stats
3 (initial 1)
# 下线后端服务器
echo "disable server webcluster/web1" | socat stdio /var/lib/haproxy/stats
# 上线后端服务器
echo "enable server webcluster/web1" | socat stdio /var/lib/haproxy/stats
多进程处理

当Haproxy开启多进程,那么对进程的Sock文件进行操作时,会导致操作是随机,不够准确

需要指定操作进程,需要用多sock文件方式解决

bash 复制代码
[root@Haproxy ~]# vim /etc/haproxy/haproxy.cfg 
    # turn on stats unix socket
    stats socket /var/lib/haproxy/stats1 mode 600 level admin process 1
    stats socket /var/lib/haproxy/stats2 mode 600 level admin process 2
    nbproc 2
    cpu-map 1 0
    cpu-map 2 1
# 经过设置后,每个进程都有对应的sock文件提供操作
[root@Haproxy ~]# ll /var/lib/haproxy/

ACL

格式
acl aclname criterion flags operator value
acl 名称 匹配规范 匹配模式 具体操作符 操作对象
匹配规范

hdr string:提取HTTP请求报文的首部

hdr([<name>[,<occ>]]) 完全匹配 header的指定信息;occ表示在多值中使用的值出现的次数
hdr_beg 前缀匹配 header中指定匹配内容的begin
hdr_end 后缀匹配 header中指定匹配内容的end
hdr_dom 域名匹配 header中的dom(host)
hdr_dir 路径匹配 header的 uri 路径
hdr_len 长度匹配 header的长度匹配
hdr_reg 正则表达式匹配 自定义表达式模糊匹配
hdr_sub 子串匹配 header中的 uri 模糊匹配

匹配规范还包括(base类、path类、url类)

base string:返回主机头请求的路径部分的连接,请求从主机名开始,并在问号之前结束,对虚拟主机有用

<scheme>://<user>:<password>@#<host>:<port>/<path>;<params>#?<query>#<frag>

path:提取请求的URL路径,此路径从第一个斜杠开始,在问号之前结束(无主机部分)

url:提取请求中的整个URL

匹配模式
bash 复制代码
-i	不区分大小写
-m	使用指定的正在表达式匹配方法
-n	不做DNS解析
-u	禁止ACL重名,否则多个同名ACL匹配或关系
具体操作符
整数比较
eq 等于
ge 大于等于
gt 大于
le 小于等于
lt 小于
字符比较
-m str 提取的字符串必须与模式完全相同
-m sub 提取的字符串中包含指定子串
-m beg 提取的字符串以指定模式开头
-m end 提取的字符串以指定模式结尾
-m dir 路径中的任一目录部分匹配模式(用斜线 / 分隔的字符串)
-m dom 域名的任一组成部分匹配模式(用点 . 分隔字符串)
操作对象

对象类型

Boolean 布尔值
Integer/Range 整数或整数范围
IP Address/Network IP 地址 / IP 范围
String 字符串
-m str 精确匹配
-m sub 子串匹配
-m beg 前缀匹配
-m end 后缀匹配
-m dir 路径匹配
-m dom 域名匹配
Regular Expression 正则表达式
Hex Block 十六进制
组合调用方式
多个ACL逻辑处理

与:默认使用

或:or 或 || 表示

否定:! 表示

多个ACL调用方式
if a1 a2 与关系,acl中a和b 都要满足为true,默认调用方式
if a1 || a2 if a1 or a2 或关系,acl中a1或a2满足一个为true
if !a1 非,取反,不满足acl才为true

算法

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

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

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

静态算法

按照事先定义好的规则轮询公平调度,不关心后端服务器的当前负载、连接数和响应速度等,且无法实时修改权重,只能靠重启 HAProxy 生效

static-rr

基于权重的轮询调度,权重只能在配置文件中静态设置

  • 不支持权重动态调整
  • 不支持服务器慢启动
  • 后端服务器没有数量限制

慢启动:服务器刚刚启动时,先给一部分访问,承受住后,再逐渐增加

bash 复制代码
cat /etc/haproxy/haproxy.cfg
listen nginx
    bind 172.25.254.100:80
    mode http
    balance static-rr
    server rs1 192.168.0.87:80 weight 1 check inter 3s fall 3 rise 5
    server rs2 192.168.0.89:80 weight 1 check inter 3s fall 3 rise 5

for i in {1..10}; do curl 172.25.254.100; done
first

根据服务器在列表中的位置,自上而下进行调度,当第一台服务器的连接数达到上限,新请求才会分配给下一台服务

  • 忽略服务器权重
  • 不支持权重动态调整
bash 复制代码
vim /etc/haproxy/haproxy.cfg
listen WebCluster
    bind 172.25.254.87:80
    mode http
    balance first
    server RS1 172.25.254.88:80 weight 1 maxconn 1 check inter 3s fall 3 rise 5
    server RS2 172.25.254.99:80 weight 3 check inter 3s fall 3 rise 5
# 一个终端一直访问 while true; do curl 172.25.254.87; done
# 另一个终端也一样 while true; do curl 172.25.254.87; done 可以观察到有访问到 172.25.254.99
......
Web-Server - 172.25.254.88
Web-Server - 172.25.254.99
Web-Server - 172.25.254.88
......

动态算法

  • 基于后端服务器状态进行调度适当调整

  • 新请求将优先调度至当前负载较低的服务器

  • 权重可以在haproxy运行时动态调整无需重启

roundrobin

基于权重的轮询动态调度算法

  • 支持权重动态调整,不同于LVS中的 rr 轮询模式

  • 支持慢启动(新加的服务器会逐渐增加转发数)

  • 默认调度算法,使用广泛

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

bash 复制代码
vim /etc/haproxy/haproxy.cfg
listen WebCluster
    bind 172.25.254.87:80
    mode http
    balance roundrobin
    server RS1 172.25.254.88:80 weight 1 check inter 3s fall 3 rise 5
    server RS2 172.25.254.99:80 weight 2 check inter 3s fall 3 rise 5

for i in {1..10}; do curl 172.25.254.87; done
Web-Server - 172.25.254.99
Web-Server - 172.25.254.99
Web-Server - 172.25.254.99
Web-Server - 172.25.254.88
......

# 动态调整权重
echo "set weight WebCluster/RS2 1" | socat stdio /var/lib/haproxy/stats
echo get weight WebCluster/RS2 | socat stdio /var/lib/haproxy/stats
1 (initial 2)
echo get weight WebCluster/RS1 | socat stdio /var/lib/haproxy/stats
1 (initial 1)
for i in {1..10}; do curl 172.25.254.87; done
Web-Server - 172.25.254.88
Web-Server - 172.25.254.99
......
leastconn

加权最少连接

  • 根据当前连接数最少的后端服务器分配请求,而非权重
  • 当服务器连接数相同,以权重为主
  • 支持权重动态调整
  • 支持服务器慢启动
  • 适合长连接的场景

其他算法

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

source

源地址哈希,默认为静态方式

基于用户源地址hash并将请求转发到后端服务器,后续同一个源地址 请求将被转发至同一个后端Web服务器

但当后端服务器数据量发生变化时,会导致很多用户的请求转发至新的后端服务器

可以通过hash-type支持的选项更改运行模式

两种转发请求到后端服务器的计算方式,分别是取模法一致性hash

当客户端是一个家庭,所有家庭成员的访问流量都会被定向到一台服务器,这是source算法的缺陷

map-base

取模法

先对Source地址进行Hash计算,再基于服务器总权重的取模(取相除后的余数),最终结果会决定客户端请求被分配到哪个后端服务器上

静态算法:不支持在线调整权重,不支持慢启动,可实现对后端服务器均衡调度

当服务器的总权重发生变化时,即有服务器上线或下线 ,都会因总权重发生变化导致调度结果整体改变(导致已建立的会话内容全部丢失)

一致性hash

一致性哈希

当服务器的总权重发生变化时,对调度结果影响是局部的,不会引起大的变动

动态算法,支持使用socat等工具进行在线权重调整,支持慢启动

逆时针方向,就近原则选取服务器

hash环偏斜问题:

当多个服务器IP经过Hash运算后,彼此的值相差不大,在环上呈现紧靠的现象,此时最小Hash值对应的服务器需要处理大部分的服务请求,这种现象称为一致性Hash环倾斜

解决方案:

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

uri

基于对用户请求的URI的左半部分或整个uri做hash,再将hash结果对总权重进行取模后,根据最终结果将请求转发到后端指定服务器

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

默认是静态算法 ,也可以通过hash-type 指定map-basedconsistent,决定使用取模法还是一致性hash

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

url_param

对用户请求的url中的 params 部分中的一个参数key对应的value值作hash计算,并由服务器总权重相除以后派发至某挑出的服务器,后端搜索同一个数据会被调度到同一个服务器

通常用于追踪用户,以确保来自同一个用户的请求始终发往同一个real server

如果没有key,则会使用默认轮询调度算法(roundrobin)

hdr

针对用户每个http头部(header)请求中的指定信息做hash

由 name 指定的 http首部 将会被取出并做hash计算

然后由服务器总权重取模以后派发至某挑出的服务器,如果无有效值,则会使用默认轮询调度算法

算法总结

调度算法 适用协议
static-rr tcp/http
first tcp/http
roundrobin tcp/http
leastconn tcp/http
source tcp/http
Uri http
url_param http
hdr http

应用

环境

主机版本:Linux-9_4.x86_64

主机名 IP 网卡
Client 172.25.254.88 eth0
Haproxy 172.25.254.100(公网) eth0
192.168.0.100(私网) eth1(仅主机模式)
RS1 192.168.0.87 eth0(仅主机模式)
RS2 192.168.0.89 eth0(仅主机模式)

安装

软件包:https://github.com/haproxy/wiki/wiki/Packages

bash 复制代码
[root@Haproxy ~]# yum install haproxy.x86_64 -y &> /dev/null
[root@Haproxy ~]# haproxy -v
[root@Haproxy ~]# systemctl enable --now haproxy.service

基本应用

bash 复制代码
[root@RS1/2 ~]# yum install nginx -y &> /dev/null
[root@RS1/2 ~]# echo "192.168.0.87" > /usr/share/nginx/html/index.html
[root@RS1/2 ~]# systemctl enable --now nginx.service
[root@RS1 ~]# curl 192.168.0.89
192.168.0.89
[root@RS2 ~]# curl 192.168.0.87
192.168.0.87
bash 复制代码
# 除global和defaults段,其他地方均要注释掉
[root@Haproxy ~]# vim /etc/haproxy/haproxy.cfg
#---------------------------------------------------------------------
# main frontend which proxys to the backends
#---------------------------------------------------------------------
listen nginx
    bind 172.25.254.100:80
    mode http
    balance static-rr
    server rs1 192.168.0.87:80 weight 1 check
    server rs2 192.168.0.89:80 weight 1 check
[root@Haproxy ~]# systemctl restart haproxy.service
bash 复制代码
[root@Client ~]# for i in {1..10}; do curl 172.25.254.100; done

高级应用

Haproxy 错误页

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

使用 errorfile 和 errorloc 参数,实现自定义各种错误页面

bash 复制代码
# Haproxy默认使用的错误页面
[root@Haproxy ~]# rpm -ql haproxy | grep -E http$
自定义错误页面
bash 复制代码
[root@Haproxy ~]# vim /etc/haproxy/haproxy.cfg
......
    maxconn                 3000
    errorfile 503 /haproxy/errorpages/503page.http
#---------------------------------------------------------------------
# main frontend which proxys to the backends
#---------------------------------------------------------------------
[root@Haproxy ~]# mkdir /haproxy/errorpages/ -p
[root@Haproxy ~]# cp /usr/share/haproxy/503.http /haproxy/errorpages/503page.http

[root@Haproxy ~]# cat /haproxy/errorpages/503page.http
HTTP/1.0 503 Service Unavailable^M
Cache-Control: no-cache^M
Connection: close^M
Content-Type: text/html;charset=UTF-8^M
^M
<html><body><h1>什么水果最让人感到有压力?</h1>
<h1>鸭梨,因为"压力"(鸭梨)山大</h1>
</body></html>

[root@Haproxy ~]# systemctl restart haproxy.service
[root@RS1/2 ~]# systemctl stop nginx.service

通过浏览器访问172.25.254.100

重定向错误页面

使用 errorloc 指令,遇到错误代码时,重定向错误页面

bash 复制代码
[root@Haproxy ~]# vim /etc/haproxy/haproxy.cfg
......
    maxconn                 3000
    errorloc 503 https://www.baidu.com
#---------------------------------------------------------------------
# main frontend which proxys to the backends
#---------------------------------------------------------------------
[root@RS1/2 ~]# systemctl stop nginx
Haproxy HTTPS实现
bash 复制代码
[root@Haproxy ~]# mkdir /etc/haproxy/certs/

[root@Haproxy ~]# openssl req -newkey rsa:2048 -nodes -sha256 -keyout /etc/haproxy/certs/ooovooo.org.key -x509 -days 365 -out /etc/haproxy/certs/ooovooo.org.crt

# Country Name (2 letter code) [XX]:CN
# State or Province Name (full name) []:Shanghai
# Locality Name (eg, city) [Default City]:Shanghai
# Organization Name (eg, company) [Default Company Ltd]:QAQ
# Organizational Unit Name (eg, section) []:QWQ
# Common Name (eg, your name or your server's hostname) []:www.ooovooo.org
# Email Address []:admin@ovo.org

[root@Haproxy ~]# cat /etc/haproxy/certs/ooovooo.org.key /etc/haproxy/certs/ooovooo.org.crt > /etc/haproxy/certs/ooovooo.org.pem

[root@Haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen nginx
    bind *:443 ssl crt /etc/haproxy/certs/ooovooo.org.pem
    mode http
    balance static-rr
    server rs1 192.168.0.87:80 weight 1 check
    server rs2 192.168.0.89:80 weight 1 check

 [root@Haproxy ~]# systemctl restart haproxy.service
 [root@RS1/2 ~]# systemctl restart nginx.service
全站加密
bash 复制代码
[root@Haproxy ~]# vim /etc/haproxy/haproxy.cfg
frontend nginx-https
    bind *:80
    mode http
    redirect scheme https if !{ ssl_fc }

listen nginx
    bind *:443 ssl crt /etc/haproxy/certs/ooovooo.org.pem
    mode http
    balance static-rr
    server rs1 192.168.0.87:80 weight 1 check
    server rs2 192.168.0.89:80 weight 1 check
[root@Haproxy ~]# systemctl restart haproxy.service
Haproxy 状态页

Haproxy自带一个状态页,方便我们观察服务器的健康状态

参数 名称
stats enable 基于默认的参数启用stats page
stats hide-version 将状态页中haproxy版本隐藏
stats refresh <delay> 设定自动刷新时间间隔,默认不自动刷新,过快耗费性能
stats uri <prefix> 自定义stats page uri,默认值:/haproxy/status
stats auth : <user>:<passwd> 认证时的账号和密码,可定义多个用户,每行指定一个用户 默认:no authentication
stats admin { if | unless } <cond> 启用stats page中的管理功能
bash 复制代码
[root@Haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen status
    mode http
    bind *:7788
    stats enable
    stats uri /status
    stats auth haproxy:7788
[root@Haproxy ~]# systemctl restart haproxy.service
基于Cookie的会话保持
bash 复制代码
[root@Haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen nginx
    bind *:443 ssl crt /etc/haproxy/certs/ooovooo.org.pem
    mode http
    balance static-rr
    cookie QAQ-WebServer insert nocache indirect
    server rs1 192.168.0.87:80 cookie est1 weight 1 check
    server rs2 192.168.0.89:80 cookie est2 weight 1 check
[root@Haproxy ~]# systemctl restart haproxy.service
IP透传

NGinx日志:/var/log/nginx/access.log

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

四层透传

Apache不支持原生四层透传(TCP 转发),可以在四层代理的配合下做到透传

未配置透传
bash 复制代码
# 将前面的配置删掉,保证环境的干净
[root@HAproxy ~]# vim /etc/haproxy/haproxy.cfg
listen nginx
    bind *:80
    mode tcp
    balance roundrobin
    server rs1 192.168.0.87:80 weight 1 check
    server rs2 192.168.0.89:80 weight 1 check
[root@HAproxy ~]# systemctl restart haproxy.service
[root@RS1 ~]# > /var/log/nginx/access.log
[root@Client ~]# for i in {1..10}; do curl 172.25.254.100; done

# 不记录客户端真实 IP 地址
[root@RS1 ~]# cat /var/log/nginx/access.log
配置透传
bash 复制代码
# 仅开启RS2
[root@HAproxy ~]# vim /etc/haproxy/haproxy.cfg
listen WebServer
    bind *:80
    mode tcp
    balance roundrobin
    server rs1 192.168.0.87:80 weight 1 check
    server rs1 192.168.0.87:80 weight 1 check send-proxy # send-proxy 开启透传
[root@HAproxy ~]# systemctl restart haproxy.service
[root@Server2 ~]# vim /etc/nginx/nginx.conf
http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                        '"$proxy_protocol_addr"'	# 新增行
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
......
    server {
# 没有 proxy_protocol 参数无法访问,只能通过四层代理访问;
# 并且做七层透传时 proxy_protocol 参数不能有
        listen       80 proxy_protocol;
        listen       [::]:80;
[root@RS2 ~]# systemctl restart nginx.service

[root@RS1/2 ~]# > /var/log/nginx/access.log
[root@Client ~]# for i in {1..10}; do curl 172.25.254.100; done
# 记录客户端真实 IP 地址
[root@RS1/2 ~]# cat /var/log/nginx/access.log
七层透传

Nginx七层默认配置好透传,而Apache则没有,需要进行相应配置

bash 复制代码
[root@HAproxy ~]# vim /etc/haproxy/haproxy.cfg
listen WebServer
    bind *:80
    mode http
    balance roundrobin
    server rs1 192.168.0.87:80 weight 1 check
    server rs2 192.168.0.89:80 weight 1 check
[root@HAproxy ~]# systemctl restart haproxy.service
# 还原配置
[root@RS2 ~]# vim /etc/nginx/nginx.conf
http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
......
    server {
        listen	80;
[root@RS2 ~]# systemctl restart nginx.service

[root@RS1 ~]# > /var/log/nginx/access.log
[root@Client ~]# for i in {1..10}; do curl 172.25.254.88; done
# Nginx 七层默认开启透传
[root@RS1 ~]# cat /var/log/nginx/access.log
bash 复制代码
# 关闭 Nginx 七层透传
[root@HAproxy ~]# vim /etc/haproxy/haproxy.cfg
defaults
......
# 在转发客户端请求时,HAProxy会在HTTP请求头中添加X-Forwarded-For字段,其中包含客户端的真实IP地址
# 来自本地回环地址的请求,HAProxy 不会添加 X-Forwarded-For 头
#    option forwardfor       except 127.0.0.0/8
[root@HAproxy ~]# systemctl restart haproxy.service
[root@RS1 ~]# > /var/log/nginx/access.log
[root@Client ~]# for i in {1..10}; do curl 172.25.254.100; done
[root@RS1 ~]# cat /var/log/nginx/access.log
Apache七层透传
bash 复制代码
[root@RS1 ~]# systemctl stop nginx.service

[root@RS1 ~]# dnf install httpd -y
[root@RS1 ~]# systemctl enable --now httpd
[root@RS1 ~]# echo 192.168.0.87 > /var/www/html/index.html
[root@RS1 ~]# curl 192.168.0.87
192.168.0.87
[root@RS1 ~]# > /etc/httpd/logs/access_log
[root@Client ~]# for i in {1..10}; do curl 172.25.254.100; done
# 默认关透传
[root@RS1 ~]# cat /etc/httpd/logs/access_log
bash 复制代码
# 开透传
# /etc/haproxy/haproxy.cfg中需要option forwardfor except 127.0.0.0/8未被注释
[root@Haproxy ~]# vim /etc/haproxy/haproxy.cfg
    option forwardfor       except 127.0.0.0/8
[root@Haproxy ~]# systemctl restart haproxy.service

[root@RS1 ~]# vim /etc/httpd/conf/httpd.conf
201	LogFormat "%{X-Forwarded-For}i %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
202 LogFormat "%h %l %u %t \"%r\" %>s %b" common
[root@RS1 ~]# systemctl restart httpd

[root@RS1 ~]# > /etc/httpd/logs/access_log
[root@Client ~]# for i in {1..10}; do curl 172.25.254.100; done
[root@RS1 ~]# cat /etc/httpd/logs/access_log
ACL-匹配访问路径实现动静分离

注意:四层透传下,无法完成此实验

bash 复制代码
[root@RS1 ~]# yum remove httpd -y
[root@RS1/2 ~]# systemctl enable --now nginx.service
[root@Haproxy ~]# vim /etc/haproxy/haproxy.cfg
frontend nginx
    bind *:80
    mode http
    acl static	path_sub	-m	sub	static
    acl php		path_sub	-m  sub	php
    use_backend	php-server	if	php
    default_backend default-server
backend php-server
    mode http
    server php 192.168.0.87:80 check
backend default-server
    mode http
    server nginx 192.168.0.89:80 check
[root@Haproxy ~]# systemctl restart haproxy.service

[root@RS1 ~]# yum install php -y
[root@RS1 ~]# mkdir /usr/share/nginx/html/php -p
[root@RS1 ~]# vim /usr/share/nginx/html/php/index.php
<?php
        phpinfo();
?>
[root@RS1 ~]# systemctl enable --now php-fpm.service

[root@RS2 ~]# mkdir /usr/share/nginx/html/static -p
[root@RS2 ~]# echo static - 172.25.254.89 Nginx > /usr/share/nginx/html/static/index.html
Haproxy 四层负载
bash 复制代码
[root@Haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen mysql
    bind *:3306
    mode tcp
    balance static-rr
    server rs1 192.168.0.87:3306 check
    server rs2 192.168.0.89:3306 check
[root@Haproxy ~]# systemctl restart haproxy.service
bash 复制代码
[root@RS1/2 ~]# yum install mariadb-server -y
[root@RS1 ~]# vim /etc/my.cnf
!includedir /etc/my.cnf.d
[mysqld]
server-id=1
[root@RS2 ~]# vim /etc/my.cnf
!includedir /etc/my.cnf.d
[mysqld]
server-id=2
[root@RS1/2 ~]# systemctl enable --now mariadb
[root@RS1/2 ~]# mysql -e "grant all on *.* to ovo@'%' identified by 'aaa';"
[root@RS1/2 ~]# systemctl restart mariadb.service

[root@Client ~]# yum install mariadb -y
[root@Client ~]# mysql -uovo -paaa -h 172.25.254.100 -e 'select @@server_id;'
相关推荐
java叶新东老师3 小时前
git stash 命令详解
linux·运维·flink
写bug的羊羊4 小时前
CentOS 9 配置国内 YUM 源
linux·运维·centos
国科安芯5 小时前
抗辐照芯片在低轨卫星星座CAN总线通讯及供电系统的应用探讨
运维·网络·人工智能·单片机·自动化
gx23486 小时前
HCLP--MGER综合实验
运维·服务器·网络
angushine6 小时前
鲲鹏服务器部署Kafka2.8.1
运维·服务器
一个网络学徒7 小时前
MGRE综合实验
运维·服务器·网络
C++ 老炮儿的技术栈7 小时前
在 Scintilla 中为 Squirrel 语言设置语法解析器的方法
linux·运维·c++·git·ubuntu·github·visual studio
白鹭8 小时前
基于LNMP架构的分布式个人博客搭建
linux·运维·服务器·网络·分布式·apache
不辉放弃8 小时前
kafka的消费者负载均衡机制
数据库·分布式·kafka·负载均衡
java叶新东老师8 小时前
linux 部署 flink 1.15.1 并提交作业
linux·运维·flink