深度解析HAProxy:构建高可用负载均衡的终极指南

目录

haproxy配置文件组成

实验环境

haproxy安装

haproxy的配置文件说明

全局配置段global

多进程和多线程配置

代理配置段proxies

server配置说明

实验相关配置

测试效果:

haproxy的状态页

socat命令

socat命令的一些常用示例

HAProxy的调度算法

静态算法

static-rr(静态轮询)

first(优先调度)

动态算法

roundrobin(加权轮询)

leastconn(最少连接数)

其他算法

source(源地址哈希)

uri(URI哈希)

​编辑

url_param(URL参数哈希)

​编辑

hdr(HTTP头部哈希)

haproxy的高级功能配置

基于cookie的会话保持

配置选项说明

IP透传

四层IP透

未开启四层IP透传时

开启四层IP透传后

七层IP透传

ACL

ACL配置选项说明

aclname名称

criterion匹配规范

flags匹配模式

多个acl的组合调用方式

ACL相关实验

ACL域名匹配

ACL基于源IP或子网调度访问

ACL基于源地址的访问控制

ACL匹配浏览器类型

ACL基于文件后缀名实现动静分离 

ACL匹配访问路径实现动静分离

自定义HAProxy错误页面

基于自定义的错误页面配置

基于http重定向错误页面配置

HAProxy四层负载

对于MySQL服务实现四层负载

HAProxy的https实现

证书的制作

haproxy配置


HAProxy(高可用代理)是一款开源的、高性能的负载均衡和反向代理软件,它在网络服务架构中扮演着至关重要的角色,主要负责分发网络流量,以实现负载均衡和高可用性。HAProxy采用C语言编写,能够有效地处理大量并发连接,并支持多种负载均衡算法,如轮询、最少连接、源地址哈希等。它通常运行在透明模式下,将客户端请求转发到多个服务器上,从而分散负载,提升系统整体性能和吞吐量。

haproxy配置文件组成

实验环境

操作系统:RHEL9.3
haproxy    
    ens160    172.25.254.100 ​    

    ens224    192.168.0.100
webserver1    ens160    192.168.0.10
webserver2    ens160    192.168.0.20

haproxy安装

[root@haproxy ~]# yum install haproxy -y

haproxy的配置文件说明

haproxy的配置文件为/etc/haproxy/haproxy.cfg,主要有全局配置段global、代理配置段proxies组成。

全局配置段global

[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg

global    #用于定义全局参数,属于进程级的配置,通常和操作系统配置有关
    log         127.0.0.1 local2    #定义全局的syslog服务器;日志服务器需开启UDP协议

    chroot      /var/lib/haproxy    #更改当前工作目录
    pidfile     /var/run/haproxy.pid    #指定pid文件路径
    maxconn     4000    #每个haproxy进程的最大连接并发数,优先级最低,如果default或frontend也有,会优先选择frontend,default次之
    user        haproxy    #运行haproxy的所属用户
    group       haproxy    #运行haproxy的所属组
    daemon       #以守护进程方式运行haproxy

    stats socket /var/lib/haproxy/stats mode 600 level admin    #套接字文件
多进程和多线程配置

多进程和socket的配置

[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
global
    log         127.0.0.1 local2

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

    # turn on stats unix socket
    #这里启用了多个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核心绑定,防止cpu抖动从而减少系统资源消耗
    cpu-map 2 1    #2表示第二个进程,1表示第二个cpu核心

#每次完配置文件后,一定要重启haproxy,后面也一样,不再进行说明
[root@haproxy ~]# systemctl restart haproxy.service

#查看多进程信息
[root@haproxy ~]# pstree -p | grep haproxy
           |-haproxy(2360)-+-haproxy(2362)
           |               `-haproxy(2363)

多线程的配置

[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg

global
    log         127.0.0.1 local2

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

    # 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

    # utilize system-wide crypto-policies
    nbthread 2	#启动多线程

#未启动多线程时
[root@haproxy ~]# cat /proc/2363/status | grep -i thread	#2363为haproxy子进程的id(通过查看多进程信息获取),-i表示不区分大小写进行匹配
Threads:        1
Speculation_Store_Bypass:       thread vulnerable

#开启多线程后,我们可以发现,线程数变为2
[root@haproxy ~]# cat /proc/2447/status | grep -i thread
Threads:        2
Speculation_Store_Bypass:       thread vulnerable

代理配置段proxies

[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg

#defaults,用于配置默认参数,这些参数可以被用到frontend、backend、listen组件
defaults
  mode http				#默认的模式mode(tcp/http/health),tcp是4层,http是七层,health只会返回OK
  log global			#应用全局的日志配置
  option httplog		#启用日志记录http请求,默认haproxy日志记录是不记录http请求日志的
  option dontlognull	#启用该项,日志中将不会记录空连接。所谓空连接,就是在上游的负载均衡或者监控系统为了探测该服务是否存活可用时,需要定期的连接或者获取某一固定的组件或页面,或者探测扫描端口是否在**或开放等动作被称为空连接;官方文档中标注,如果该服务上游没有其他的负载均衡器的话,建议不要使用该参数,因为互联网上的恶意扫描或其它动作就不会被记录下来
  option http-server-close		#每次请求完毕后主动关闭http通道
  option forwardfor
  except 172.0.0.0/8	#如果服务器上的应用程序想记录发起请求的客户端的IP地址,需要再haproxy上配置该选项,这样haproxy会把客户端的IP信息发送给服务器,在http请求中添加"X-Forwarded-For"字段。启用X-Forwarded-For,在requests头部插入客户端IP发送给后端的server,使后端server获取到客户端的真实IP
  option redispatch	#当使用了cookie时,haproxy将会将其请求的后端服务器的serverID插入到cookie中,以保证会话的session持久性;而此时,如果后端的服务器宕机了,但是客户端的cookie是不会刷新的,如果设置此参数,将会将客户的请求强制定向到另外一个后端server上,以保证服务的正常运行
  retries 3		#定义连接后端服务器的失败重连次数,连接失败次数超出此值后,将会将对应后端服务器标记为不可用
  timeout http-request 10s	#http请求超时时间
  timeout queue 1m		#一个请求在队列里的超时时间
  timeout connect 10s	#连接超时时间
  timeout client 1m		#客户端超时时间
  timeout server 1m		#服务器超时时间
  timeout http-keep-alive 10s	#http-keep-alive的超时时间
  timeout check 10s		#检测超时时间
  maxconn 3000			#每个进程可用的最大连接数

#listen,常常用于状态页面的监控,以及后端server检查,是frontend和backend的组合体
listen webcluster
  bind *:80
  mode http
  balance roundrobin
  redirect prefix http://www.baidu.com
  server web1 192.168.0.10:80 check inter 2 fall 3 rise 5 weight 1
  server web2 192.168.0.20:80 check inter 2 fall 3 rise 5 weight 1
  server web_sorry 192.168.0.100:8080 backup

#frontend,用于定义前端服务的配置。在frontend中配置acl规则,可将请求定向到相关的backend
frontend main
  bind *:80		#设置所有IP的80端口为监听端口,即haproxy提供的web服务端口
  acl url_static	path_beg	-i /static /images /javascript /stylesheets	#定义acl规则
  use_backend static	if url_static		#匹配了url_static规则的请求转发给名称为static的后端
  default_backend	app		#默认请求转发至名称为app的后端

#backend,用来定义后端集群的配置,真实服务器,一个backend对应一个或者多个实体服务器
backend static		#使用了静态动态分离(如果url_path匹配/static /images /javascript /stylesheets静态文件,则访问此后端)
  balance	roundrobin		#负载均衡算法
  server	static 127.0.0.1:4331 check		#静态文件部署在本机(也可以部署在其他机器或者squid缓存服务器)
server配置说明
#对于一条server配置来说
check    #对指定real进行健康状态检查,如果不加此设置,默认不开启检查,只有check后面没有其它配置也可以开启检查功能
         #默认对应的后端服务器IP和端口,利用TCP连接进行周期性健康检查,注意必须指定端口才能进行检查
addr <IP>    #可指定的健康状态监测IP,可以是专门的数据网段,减少业务网络的流量
port <num>    #指定的健康状态监测端口
inter <num>    #健康状态检查间隔时间 ,默认2000ms
fall <num>    #后端服务器从线上转为线下的检查连续失效次数,默认为3次
rise <num>    #后端服务器从下线回复上线2的检查连续有效次数,默认为2次
weight  <num>    #默认权重为1,最大为256,0表示不参与负载均衡,但仍接受持久连接
disabled    #将后端服务器标记为不可用状态,即维护状态,除了持久模式,将不再接受连接
实验相关配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webcluster
  bind *:80
  mode http
  balance roundrobin
  server web1 192.168.0.10:80 check inter 2 fall 3 rise 5 weight 1
  server web2 192.168.0.20:80 check inter 2 fall 3 rise 5 weight 1
测试效果:

haproxy的状态页

#在配置文件中添加以下部分
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen stats
  mode http
  bind *:9999
  stats enable
  stats refresh 5	#浏览器自动刷新时间
  stats uri /status	#使用浏览器访问http://192.168.0.100:9999/status,即可看到服务器状态
  stats auth niu:niu	#用户认证,用户名:密码

编辑好配置文件后,重启服务,然后通过浏览器对http://192.168.0.100:9999/status进行访问,输入我们在配置文件中所指定的账号密码,即可看到haproxy的状态页面

socat命令

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

socat命令的一些常用示例

#编辑配置文件
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
global
    stats socket /var/lib/haproxy/stats mode 600 level admin

#查看haproxy的状态
[root@haproxy ~]# echo "show info" | socat stdio /var/lib/haproxy/stats
Name: HAProxy
Version: 2.4.22-f8e3218
Release_date: 2023/02/14
Nbthread: 2
Nbproc: 1
Process_num: 1
Pid: 2104
Uptime: 0d 0h00m26s
Uptime_sec: 26
……

#查看集群状态
[root@haproxy ~]# echo "show servers state" | socat stdio /var/lib/haproxy/stats
1
# be_id be_name srv_id srv_name srv_addr srv_op_state srv_admin_state srv_uweight srv_iweight srv_time_since_last_change srv_check_status srv_check_result srv_check_health srv_check_state srv_agent_state bk_f_forced_id srv_f_forced_id srv_fqdn srv_port srvrecord srv_use_ssl srv_check_port srv_check_addr srv_agent_addr srv_agent_port
2 webcluster 1 web1 192.168.0.10 2 0 1 1 80 6 3 7 6 0 0 0 - 80 - 0 0 - - 0
2 webcluster 2 web2 192.168.0.20 2 0 1 1 80 6 3 7 6 0 0 0 - 80 - 0 0 - - 0
2 webcluster 3 web_sorry 192.168.0.100 2 0 1 1 80 1 0 2 0 0 0 0 - 8080 - 0 0 - - 0
5 static 1 static 127.0.0.1 0 0 1 1 79 8 2 0 6 0 0 0 - 4331 - 0 0 - - 0
6 app 1 app1 127.0.0.1 0 0 1 1 79 8 2 0 6 0 0 0 - 5001 - 0 0 - - 0
6 app 2 app2 127.0.0.1 0 0 1 1 79 8 2 0 6 0 0 0 - 5002 - 0 0 - - 0
6 app 3 app3 127.0.0.1 0 0 1 1 79 8 2 0 6 0 0 0 - 5003 - 0 0 - - 0
6 app 4 app4 127.0.0.1 0 0 1 1 78 8 2 0 6 0 0 0 - 5004 - 0 0 - - 0

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

@临时修改权重
[root@haproxy ~]# echo "set weight webcluster/web1 2" | socat stdio /var/lib/haproxy/stats

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

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

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

如果开启多进程的话,我们在对进程的sock文件进行操作时其对进程的操作是随机的。

[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
global
    stats socket /var/lib/haproxy/stats1 mode 600 level admin process 1
    stats socket /var/lib/haproxy/stats2 mode 600 level admin process 2

这样每个进程都会有单独的socket文件夹进行单独的管理

[root@haproxy ~]# ll /var/lib/haproxy/
total 0
srw-------. 1 root root 0 Aug 11 09:58 stats
srw-------. 1 root root 0 Aug 11 10:10 stats1
srw-------. 1 root root 0 Aug 11 10:10 stats2

HAProxy的调度算法

HAProxy的调度算法主要分为静态算法、动态算法以及其他算法三大类。下面将分别详细介绍这三类算法及其优缺点。

静态算法

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

static-rr(静态轮询)

基于权重的轮询调度,不支持运行时利用socat进行权重的动态调整(有效值为0和1),及后端服务器慢启动,其后端主机数量没有限制。

  • 优点:

    • 配置简单,易于理解和使用。

    • 适用于后端服务器性能相近的场景。

  • 缺点:

    • 无法实时调整权重,灵活性较差。

    • 在后端服务器性能差异较大的情况下,可能导致负载不均衡。

实验相关配置

[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webcluster
  bind *:80
  mode http
  balance static-rr
  server web1 192.168.0.10:80 check inter 2 fall 3 rise 5 weight 1
  server web2 192.168.0.20:80 check inter 2 fall 3 rise 5 weight 1

测试效果

first(优先调度)

根据服务器在列表中的位置,自上而下进行调度,但是当第一台服务器的连接数达到上限时,新请求才会被分配到下一台服务器,因此会忽略服务器的权重设置。不支持用socat进行动态修改权重,有效值只有0和1

  • 优点:

    • 在某些特定场景下,如需要优先处理某些服务器的请求时,可以使用此算法。

  • 缺点:

    • 忽略服务器权重,可能导致负载不均衡。

    • 灵活性较差,无法根据服务器实际负载情况进行调整。

实验相关配置

[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webcluster
  bind *:80
  mode http
  balance first
  server web1 192.168.0.10:80 check inter 2 fall 3 rise 5 weight 1
  server web2 192.168.0.20:80 check inter 2 fall 3 rise 5 weight 1

测试效果

动态算法

动态算法基于后端服务器的当前状态进行调度,能够实时调整权重,无需重启HAProxy服务。

roundrobin(加权轮询)

基于权重的轮询动态调度算法,支持权重的运行时调整,支持慢启动(新加的服务器会逐渐增加转发数),每个后端backend中最多支持4095个server。

  • 优点:

    • 灵活性高,可以根据服务器实际负载情况动态调整权重。

    • 支持慢启动,有利于新加入服务器的平稳过渡。

  • 缺点:

    • 在高并发场景下,如果服务器性能差异较大,可能导致整体性能下降。

实验相关配置

[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webcluster
  bind *:80
  mode http
  balance roundrobin
  server web1 192.168.0.10:80 check inter 2 fall 3 rise 5 weight 1
  server web2 192.168.0.20:80 check inter 2 fall 3 rise 5 weight 1

测试效果

使用socat命令进行动态权重的调整

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

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

再次测试

leastconn(最少连接数)

当前后端服务器连接最少的优先调度,支持加权的最少连接和动态调整权重。

  • 优点:

    • 能够有效减少服务器过载的可能性,优化资源利用。

    • 适用于长连接会话场景,能够更好地平衡服务器负载。

  • 缺点:

    • 在某些情况下可能不够公平,如果某些请求处理时间非常长,可能导致这些服务器连接数持续增长。

其他算法

除了静态和动态算法外,HAProxy还支持一些基于特定规则的调度算法。

source(源地址哈希)

基于用户源地址hash并将请求转发到后端服务器,支持静态和动态hash方式(通过hash-type选项更改)。

  • 优点:

    • 能够实现会话保持,确保来自同一客户端的请求被转发到同一台服务器上。

  • 缺点:

    • 可能导致负载不均衡,特别是当客户端分布不均时。

    • 不适用于移动IP场景。

实验相关配置

[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webcluster
  bind *:80
  mode http
  balance source
  server web1 192.168.0.10:80 check inter 2 fall 3 rise 5 weight 1
  server web2 192.168.0.20:80 check inter 2 fall 3 rise 5 weight 1

测试效果

uri(URI哈希)

基于用户请求的URI做hash并将请求转发到后端指定服务器。

  • 优点:

    • 可以根据请求的资源进行负载均衡,有利于缓存和性能优化。

  • 缺点:

    • 配置复杂度较高,需要定义URI的哈希规则。

    • 可能导致负载不均衡,特别是当某些资源的访问量非常大时。

实验相关配置

#取模法配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webcluster
  bind *:80
  mode http
  balance uri
  server web1 192.168.0.10:80 check inter 2 fall 3 rise 5 weight 1
  server web2 192.168.0.20:80 check inter 2 fall 3 rise 5 weight 1

测试效果

#一致性hash配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webcluster
  bind *:80
  mode http
  balance uri
  hash-type consistent
  server web1 192.168.0.10:80 check inter 2 fall 3 rise 5 weight 1
  server web2 192.168.0.20:80 check inter 2 fall 3 rise 5 weight 1

测试效果

访问不通的uri,可将用户同样的请求转发至相同的服务器

[root@webserver1 ~]# echo webserver1 192.168.0.10 > /var/www/html/index1.html
[root@webserver1 ~]# echo webserver1 192.168.0.10 > /var/www/html/index2.html
[root@webserver2 ~]# echo webserver2 192.168.0.20 > /var/www/html/index1.html
[root@webserver2 ~]# echo webserver2 192.168.0.20 > /var/www/html/index2.html

url_param(URL参数哈希)

对用户请求的URL中的params部分中的参数name(key)作hash计算,并由服务器总权重相除以后派发至某挑出的服务器。

  • 优点:

    • 可以根据URL中的特定参数进行负载均衡,有利于处理特定业务逻辑。

  • 缺点:

    • 配置复杂度较高,需要定义URL参数的哈希规则。

    • 可能导致负载不均衡,特别是当某些参数的访问量非常大时。

实验相关配置

#取模法配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webcluster
  bind *:80
  mode http
  balance url_param name,userid
  server web1 192.168.0.10:80 check inter 2 fall 3 rise 5 weight 1
  server web2 192.168.0.20:80 check inter 2 fall 3 rise 5 weight 1

测试效果

#一致性hash配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webcluster
  bind *:80
  mode http
  balance url_param name,userid
  hash-type consistent
  server web1 192.168.0.10:80 check inter 2 fall 3 rise 5 weight 1
  server web2 192.168.0.20:80 check inter 2 fall 3 rise 5 weight 1

hdr(HTTP头部哈希)

针对用户每个HTTP头部(header)请求中的指定信息做hash,并由服务器总权重相除以后派发至某挑选出的服务器。

  • 优点:

    • 可以根据HTTP请求中的特定头部信息进行负载均衡,实现更细粒度的控制。

  • 缺点:

    • 配置复杂度较高,需要定义头部字段的哈希规则。

    • 解析HTTP头部信息可能会增加一定的处理时间,影响系统性能。

实验相关配置

#一致性hash配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webcluster
  bind *:80
  mode http
  balance hdr(User-Agent)
  hash-type consistent
  server web1 192.168.0.10:80 check inter 2 fall 3 rise 5 weight 1
  server web2 192.168.0.20:80 check inter 2 fall 3 rise 5 weight 1

测试效果

haproxy的高级功能配置

基于cookie的会话保持

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

配置选项说明

name      #cookie的key名称,用于实现持久连接
insert    #插入新的cookie,默认不插入cookie
indirect  #如果客户端已经有cookie了,则不会再发送cookie信息
nocache   #当client和haproxy之间有缓存服务器(如CDN)时,不允许中间缓存器缓存cookie,因为这会导致很多经过同一个CDN的请求都发送到同一台后端服务器上

实验配置

[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webcluster
  bind *:80
  mode http
  cookie WEBCOOKIE insert nocache indirect
  server web1 192.168.0.10:80 cookie webserver1 check inter 2 fall 3 rise 5 weight 1
  server web2 192.168.0.20:80 cookie webserver2 check inter 2 fall 3 rise 5 weight 1

我们可以通过浏览器访问http://192.168.0.100来验证cookie信息

同样,我们通过命令行也是可以访问到cookie信息的

IP透传

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

四层IP透

未开启四层IP透传时
#haproxy配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webcluster
  bind *:80
  mode tcp
  balance roundrobin
  server web1 192.168.0.10:80 check inter 2 fall 3 rise 5 weight 1
  server web2 192.168.0.20:80 check inter 2 fall 3 rise 5 weight 1

#nginx配置
[root@webserver1 ~]# 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;
        listen       [::]:80;
        server_name  _;
        root         /usr/share/nginx/html;
        ……
    }
}

对后端服务器进行访问后,我们通过nginx日志可以看出,是无法看到真实的访问源地址的

开启四层IP透传后
#haproxy配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webcluster
  bind *:80
  mode tcp
  balance roundrobin
  server web1 192.168.0.10:80 send-proxy check inter 2 fall 3 rise 5 weight 1
  server web2 192.168.0.20:80 check inter 2 fall 3 rise 5 weight 1

#nginx配置
[root@webserver1 ~]# vim /etc/nginx/nginx.conf
http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$proxy_protocol_addr"'
                      '"$http_user_agent" "$http_x_forwarded_for"';
        ……
    server {
        listen       80 proxy_protocol;
        listen       [::]:80;
        server_name  _;
        root         /usr/share/nginx/html;
        ……
    }
}

再次对后端服务器进行访问后,我们通过nginx日志可以看出,看到了真实的访问源地址

七层IP透传

当haproxy工作在七层的时候,也可以透传客户端真实IP至后端服务器

#haproxy配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webcluster
  bind *:80
  mode http
  option forwardfor
  balance roundrobin
  server web1 192.168.0.10:80 send-proxy check inter 2 fall 3 rise 5 weight 1
  server web2 192.168.0.20:80 check inter 2 fall 3 rise 5 weight 1

#nginx配置
root@webserver1 ~]# vim /etc/nginx/nginx.conf
http {
        #proxy_add_x_forwarded_for,包括客户端IP和中间经过的所有代理的IP
        log_format  main  '"$proxy_add_x_forwarded_for" - $remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
}

测试效果

ACL

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

ACL配置选项说明

#用acl来定义或者声明一个acl
acl <aclname> <criterion> [flags] [operator] [<value>]

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

命名规范:可以使用大写字母A-Z,小写字母a-z,数字0-9,冒号:,点.,中横线-和下划线_,并且严格区分大小写,例如:my_acl和My_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中的dom(host)
hdr_dir([<name> [, <occ>]])路径匹配,header中的uri路径
hdr_len([<name> [, <occ>]])长度匹配,header中的长度匹配
hdr_reg([<name> [, <occ>]])正则表达式匹配,自定义表达式(regex)模糊匹配
hdr_sub([<name> [, <occ>]])子串匹配,header中的uri模糊匹配,模糊匹配c,报文中的a/b/c也会被匹配到
flags匹配模式

-i        不区分大小写

-m      使用指定的正则表达式

-n       不做DNS解析

-u       禁止acl重名,否则多个同名acl匹配或关系

多个acl的组合调用方式

多个acl的逻辑处理

        与:隐式(默认)使用

        或:使用“or”或者“||”表示

        非:使用“!”表示

ACL相关实验

由于我们以下实验是通过Windows来进行验证的,所以我们现在C:\Windows\System32\drivers\etc\hosts文件中编写访问地址的域名解析

ACL域名匹配
#haproxy配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
frontend webcluster
  bind *:80
  mode http
  acl domain hdr_dom(host) -i www.super.org

  use_backend webcluster-host if domain
  default_backend default-host

backend webcluster-host
  mode http
  server web1 192.168.0.10:80 check inter 2 fall 2 rise 5

backend default-host
  mode http
  server web2 192.168.0.20:80 check inter 2 fall 2 rise 5

测试效果

ACL基于源IP或子网调度访问
#haproxy配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
frontend webcluster
  bind *:80
  mode http
  acl ctrl_ip src 192.168.0.100

  use_backend webcluster-host if ctrl_ip 
  default_backend default-host

backend webcluster-host
  mode http
  server web1 192.168.0.10:80 check inter 2 fall 2 rise 5

backend default-host
  mode http
  server web2 192.168.0.20:80 check inter 2 fall 2 rise 5

测试效果

ACL基于源地址的访问控制

拒绝指定IP或者IP范围访问

#haproxy配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
frontend webcluster
  bind *:80
  mode http
  acl ctrl_ip src 172.25.254.0/24

  http-request deny if ctrl_ip

  use_backend webcluster-host if ctrl_ip 
  default_backend default-host

backend webcluster-host
  mode http
  server web1 192.168.0.10:80 check inter 2 fall 2 rise 5

backend default-host
  mode http
  server web2 192.168.0.20:80 check inter 2 fall 2 rise 5

测试效果

ACL匹配浏览器类型
#haproxy配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
frontend webcluster
  bind *:80
  mode http
  #拒绝curl和wget的访问
  acl badwebbrowers hdr_sub(User-Agent) -i curl wget

  http-request deny if badwebbrowers
  default_backend default-host

backend webcluster-host
  mode http
  server web1 192.168.0.10:80 check inter 2 fall 2 rise 5

backend default-host
  mode http
  server web2 192.168.0.20:80 check inter 2 fall 2 rise 5

测试效果

ACL基于文件后缀名实现动静分离 
#haproxy配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
frontend webcluster
  bind *:80
  mode http
  
  acl static path_end -i .html .jpg .png .css .js
  acl php    path_end -i .php


  use_backend webcluster-host if php
  default_backend default-host

backend webcluster-host
  mode http
  server web1 192.168.0.10:80 check inter 2 fall 2 rise 5

backend default-host
  mode http
  server web2 192.168.0.20:80 check inter 2 fall 2 rise 5

#我们还需要再webserver1上安装php,并配置其访问界面
[root@webserver1 ~]# yum install php -y
[root@webserver1 ~]# cat /var/www/html/index.php
<?php
  phpinfo();
?>

测试效果

php动态

html静态

ACL匹配访问路径实现动静分离
#haproxy配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
frontend webcluster
  bind *:80
  mode http
  
  acl static path_end -i .html .jpg .png .css .js
  acl php    path_end -i .php


  use_backend webcluster-host if php
  default_backend default-host

backend webcluster-host
  mode http
  server web1 192.168.0.10:80 check inter 2 fall 2 rise 5

backend default-host
  mode http
  server web2 192.168.0.20:80 check inter 2 fall 2 rise 5

#webserver访问配置
[root@webserver1 ~]# mkdir /var/www/html/static
[root@webserver1 ~]# mkdir /var/www/html/php
[root@webserver1 ~]# echo static - 192.168.0.10 > /var/www/html/static/index.html
[root@webserver1 ~]# echo php - 192.168.0.10 > /var/www/html/php/index.html

[root@webserver2 ~]# mkdir /var/www/html/static
[root@webserver2 ~]# mkdir /var/www/html/php
[root@webserver2 ~]# echo static - 192.168.0.20 > /var/www/html/static/index.html
[root@webserver2 ~]# echo php - 192.168.0.20 > /var/www/html/php/index.html

测试效果

自定义HAProxy错误页面

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

基于自定义的错误页面配置

#haproxy配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
defaults
    mode                    http
    log                     global
    option                  httplog
    option                  dontlognull
    option http-server-close
    option forwardfor       except 127.0.0.0/8
    option                  redispatch
    retries                 3
    timeout http-request    10s
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 3000
    errorfile 503 /etc/haproxy/errorpage/503.http

#创建错误文件
[root@haproxy ~]# mkdir /etc/haproxy/errorpage/
[root@haproxy errorpage]# cat 503.http
HTTP/1.0 503 Service Unavailable
Cache-Control: no-cache
Connection: close
Content-Type: text/html;charset=UTF-8

<html><body><h1>哈哈</h1>
hhhhhhhhhhhhhhhhh
</body></html>

#关闭webserver的web服务
[root@webserver1 ~]# systemctl stop httpd.service

测试效果

基于http重定向错误页面配置

#haproxy配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
defaults
    mode                    http
    log                     global
    option                  httplog
    option                  dontlognull
    option http-server-close
    option forwardfor       except 127.0.0.0/8
    option                  redispatch
    retries                 3
    timeout http-request    10s
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 3000
    #我们通过503重定向到百度的URL
    errorloc 503 https://www.baidu.com

#关闭webserver的web服务
[root@webserver1 ~]# systemctl stop httpd.service

测试效果

我们访问192.168.0.100,即重定向到百度页面

HAProxy四层负载

主要针对于除http外的tcp协议协议应用服务访问的应用场景,例如MySQL、Redis、Memcache、RabbitMQ等

对于MySQL服务实现四层负载

#haproxy配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen dbserver
  bind *:3306
  mode tcp    #注意:这里使用的是四层tcp模式
  balance roundrobin
  server db1 192.168.0.10:3306 check inter 2 fall 2 rise 5
  server db2 192.168.0.20:3306 check inter 2 fall 2 rise 5

#在webserver上配置mariadb服务
[root@webserver1 ~]# yum install mariadb-server -y
[root@webserver2 ~]# yum install mariadb-server -y
[root@webserver1 ~]# cat /etc/my.cnf.d/mariadb-server.cnf | grep server-id
server-id=1
[root@webserver2 ~]# cat /etc/my.cnf.d/mariadb-server.cnf | grep server-id
server-id=2
#启动mariadb服务
[root@webserver1 ~]# systemctl start mariadb.service
[root@webserver2 ~]# systemctl start mariadb.service
#我们通过命令行创建mysql用户,并对其进行授权
[root@webserver1 ~]# mysql -e "grant all on *.* to niu@'%' identified by 'niu'"
[root@webserver2 ~]# mysql -e "grant all on *.* to niu@'%' identified by 'niu'"

#在测试机上也要安装mariadb服务,这里我们使用haproxy主机进行测试
[root@haproxy ~]# yum install mariadb -y
[root@haproxy ~]# systemctl start mariadb

测试效果

HAProxy的https实现

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

证书的制作

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

haproxy配置

[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
frontend webcluster-https
  bind *:443 ssl crt /etc/haproxy/certs/super.org.pem
  mode http
  use_backend webcluster-host
frontend webcluster
  bind *:80
  mode http
  redirect scheme https if !{ ssl_fc }    #进行全站加密

backend webcluster-host
  mode http
  server web1 192.168.0.10:80 check inter 2 fall 2 rise 5

backend default-host
  mode http
  server web2 192.168.0.20:80 check inter 2 fall 2 rise 5

测试效果

命令行测试

网页测试

  • 9
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SUPER COW

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值