HAProxy算法、实践、高级用法

在这里插入图片描述

HAProxy(High Availability Proxy)是一款开源的、高性能的负载均衡器和反向代理软件。它主要用于将客户端请求分配到多台后端服务器上,从而实现应用的高可用性、负载均衡和故障转移。HAProxy广泛应用于企业级环境中,特别是在需要处理大量并发连接和请求的Web服务中。

主要功能和特点:

  1. 负载均衡
    HAProxy可以根据多种算法(如轮询、最少连接数、源IP哈希等)将客户端请求分配到不同的后端服务器,均衡负载以提高整体性能。
  2. 高可用性
    HAProxy能够监控后端服务器的健康状态,并在检测到某台服务器故障时,自动将流量转移到健康的服务器上,确保服务的连续性。
  3. 反向代理
    HAProxy可以作为反向代理,将客户端的请求转发到后端服务器,同时隐藏后端服务器的实际IP地址。
  4. 访问控制和安全性
    通过ACL(访问控制列表),HAProxy可以对请求进行精细的控制,如基于源IP、HTTP头信息、URL路径等进行过滤或重定向。
  5. 性能优化
    HAProxy非常轻量级,能够处理数十万甚至上百万的并发连接,且对系统资源的消耗非常低。
  6. 日志记录和监控
    HAProxy提供详细的日志记录功能,能够记录请求的详细信息,并通过集成监控工具来实时查看服务器的健康状态和流量情况。

常见使用场景:

  • Web服务器负载均衡:在多台Web服务器之间分配流量,确保请求的均衡分发。
  • 应用高可用性:监控后端服务器的健康状态,自动切换到备用服务器,避免服务中断。
  • SSL卸载:在HAProxy处终止SSL连接,将解密后的流量转发到后端服务器,减轻后端服务器的负载。
  • 访问控制:基于多种条件(IP地址、URL路径、HTTP方法等)控制访问权限。

一、Haproxy简单搭建:

在这里插入图片描述

1.Haproxy主机配置:
#安装haproxy软件包
[root@Haproxy ~]# yum install haproxy -y

#编写haproxy配置文件 写入粗体内容:
[root@Haproxy ~]# vim /etc/haproxy/haproxy.cfg

#---------------------------------------------------------------------
# main frontend which proxys to the backends
#---------------------------------------------------------------------
frontend webclst
        bind *:80
        mode http
        use_backend webclst-host

backend webclst-host
        balance roundrobin
        server web1 10.211.55.10:80
        server web2 10.211.55.20:80
       
       # mode http是七层转发 
       #   前后端可以使用listen合并在一起
        
       listen webclst
       bind *:80
       mode http
       balance rounderobin
       server web1 10.211.55.10:80 check inter 2 fall 3 rise 5 weight 3 maxconn 20 
       server web2 10.211.55.20:80 check inter 2 fall 3 rise 5 weight 1
       #80后的命令分别表示: 检查主机状态 每间隔2s 3次不通即down 5次通则up 权重为3  最大并发数为20(多个用户同时访问、而不是一个用户多次访问(并发数还是1,只是连接数多了而已))
       
       #开启sorry-server :
       server web-sorry 10.211.55.100:8080 backup
        #在haproxy主机上搭建简单的Apache服务器并修改默认端口为8080 (应为配置文件写的haproxy转发使用了80的监听,所以如果不修改端口会直接是haproxy响应去了 , 把/etc/httpd/conf/httpd.conf 的Listen 修改为8080即可)然后写入一个明确意义的主机无法访问而不是默认的503 
        # 作用是在所有主机都down时候 , 才访问的server,不会参与到轮询中
        
        
        #开启网页重定向
        #需要关闭现在的server主机,haproxy主机相当于作为重定向转发服务器
        redirect prefix https://www.baidu.com
                  
        
#重启haproxy服务
[root@Haproxy ~]# systemctl restart haproxy.service
RS1/2 配置(以RS2为例):

RS1和RS2负责搭建测试页面,使用nginx搭建基础测试页面

#安装nginx软件包
[root@RS2 ~]# yum install -y nginx
[root@RS2 ~]# echo Hello! Welcome Visit MyWebSite My IP is .20  >  /usr/share/nginx/html/index.html
[root@RS2 ~]# cat   /usr/share/nginx/html/index.html
Hello! Welcome Visit MyWebSite My IP is .20
#重启nginx服务
[root@RS2 ~]# systemctl restart nginx.service
补充:

在这里插入图片描述

# Save boot messages also to boot.log
local7.*                          /var/log/boot.log
local2                            /var/log/haproxy.log #添加一行log记录

加一行重启服务即可

[root@Haproxy ~]# rm  /var/log/haproxy.log
rm:是否删除普通空文件 '/var/log/haproxy.log'?y

[root@Haproxy ~]# systemctl restart rsyslog.service
[root@Haproxy ~]# cat /var/log/haproxy.log
Aug  9 00:11:59 Haproxy systemd[1]: Stopping System Logging Service...
Aug  9 00:12:00 Haproxy rsyslogd[54569]: [origin software="rsyslogd" swVersion="8.2310.0-4.el9" x-pid="54569" x-info="https://www.rsyslog.com"] exiting on signal 15.
Aug  9 00:12:00 Haproxy systemd[1]: rsyslog.service: Deactivated successfully.
Aug  9 00:12:00 Haproxy systemd[1]: Stopped System Logging Service.
Aug  9 00:12:00 Haproxy systemd[1]: Starting System Logging Service...
Aug  9 00:12:00 Haproxy systemd[1]: Started System Logging Service.
Aug  9 00:12:00 Haproxy rsyslogd[54589]: action 'local2' treated as ':omusrmsg:local2' - please use ':omusrmsg:local2' syntax instead, 'local2' will not be supported in the future [v8.2310.0-4.el9 try https://www.rsyslog.com/e/2184 ]
Aug  9 00:12:00 Haproxy rsyslogd[54589]: error during parsing file /etc/rsyslog.conf, on or before line 68: warnings occurred in file '/etc/rsyslog.conf' around line 68 [v8.2310.0-4.el9 try https://www.rsyslog.com/e/2207 ]
Aug  9 00:12:00 Haproxy rsyslogd[54589]: [origin software="rsyslogd" swVersion="8.2310.0-4.el9" x-pid="54589" x-info="https://www.rsyslog.com"] start
Aug  9 00:12:00 Haproxy rsyslogd[54589]: imjournal: journal files changed, reloading...  [v8.2310.0-4.el9 try https://www.rsyslog.com/e/0 ]
2.使用Socat 热管理Haproxy

在这里插入图片描述

#安装socat 软件包
yum install -y socat

#在haproxy配置文件中全局部分开启stat socket
stats socket /var/lib/haproxy/stats1 mode 600 level admin  process 1    #不加admin权限无法修改

stats socket /var/lib/haproxy/ststs2 mode 600 level admin process 2
#第二个是开启多进程情况下 nbproc 2;cpu-map 1 0; cpu-map 2 1            多线程使用nbthread 2
#分别用不同的stats文件管理不同进程
#重启haproxy服务器
systemctl restart haproxy


#使用:

#获取所有状态:
[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 webclst 1 web1 10.211.55.10 2 0 1 1 2 7 0 3 7 0 0 0 - 80 - 0 0 - - 0
2 webclst 2 web2 10.211.55.20 2 0 1 1 2 6 0 4 7 0 0 0 - 80 - 0 0 - - 0
5 static 1 static 127.0.0.1 0 0 1 1 129 8 2 0 6 0 0 0 - 4331 - 0 0 - - 0
6 app 1 app1 127.0.0.1 0 0 1 1 129 8 2 0 6 0 0 0 - 5001 - 0 0 - - 0
6 app 2 app2 127.0.0.1 0 0 1 1 129 8 2 0 6 0 0 0 - 5002 - 0 0 - - 0
6 app 3 app3 127.0.0.1 0 0 1 1 129 8 2 0 6 0 0 0 - 5003 - 0 0 - - 0
6 app 4 app4 127.0.0.1 0 0 1 1 128 8 2 0 6 0 0 0 - 5004 - 0 0 - - 0

#获取指定服务器的权重
[root@Haproxy ~]# echo "get weight webclst/web1" | socat stdio /var/lib/haproxy/stats
1 (initial 1)         #这里指1是当前的,inital表示是配置文件中的权重值

#设定指定服务器的权重
[root@Haproxy ~]# echo "set weight  webclst/web1 3" | socat stdio /var/lib/haproxy/stats

#测试
[root@Client ~]# curl 10.211.55.100
Hello!
Welcome to MyWebSite
My IP is .10
[root@Client ~]# curl 10.211.55.100
Hello!
Welcome to MyWebSite
My IP is .10
[root@Client ~]# curl 10.211.55.100
Hello!
Welcome to MyWebSite
My IP is .10
[root@Client ~]# curl 10.211.55.100
Hello! Welcome Visit MyWebSite My IP is .20
[root@Client ~]# curl 10.211.55.100
Hello!
Welcome to MyWebSite
My IP is .10
[root@Client ~]# curl 10.211.55.100
Hello!
Welcome to MyWebSite
My IP is .10
[root@Client ~]# curl 10.211.55.100
Hello!
Welcome to MyWebSite
My IP is .10

#下线指定的服务器
[root@Haproxy ~]# echo " disable server  webclst/web1" | socat stdio /var/lib/haproxy/stats
#测试 10下线、只有20在线咯
[root@Client ~]# curl 10.211.55.100
Hello! Welcome Visit MyWebSite My IP is .20
[root@Client ~]# curl 10.211.55.100
Hello! Welcome Visit MyWebSite My IP is .20
[root@Client ~]# curl 10.211.55.100
Hello! Welcome Visit MyWebSite My IP is .20
[root@Client ~]# curl 10.211.55.100
Hello! Welcome Visit MyWebSite My IP is .20
[root@Client ~]# curl 10.211.55.100
Hello! Welcome Visit MyWebSite My IP is .20

#上线指定的服务器
[root@Haproxy ~]# echo " enable server  webclst/web1" | socat stdio /var/lib/haproxy/stats

#测试 10 20 轮询
[root@Client ~]# curl 10.211.55.100
Hello! Welcome Visit MyWebSite My IP is .20
[root@Client ~]# curl 10.211.55.100
Hello!
Welcome to MyWebSite
My IP is .10
[root@Client ~]# curl 10.211.55.100
Hello! Welcome Visit MyWebSite My IP is .20
[root@Client ~]# curl 10.211.55.100
Hello!
Welcome to MyWebSite
My IP is .10


#socat的好处是刻意热管理haproxy 修改配置无需重启 
#注意这些热修改都是临时的,即haproxy重启后丢失

#举例
[root@Haproxy ~]# echo "set weight  webclst/web1 3" | socat stdio /var/lib/haproxy/stats

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

[root@Haproxy ~]# systemctl restart haproxy.service
[root@Haproxy ~]# echo "get weight  webclst/web1 " | socat stdio /var/lib/haproxy/stats
1 (initial 1)

二、haproxy的算法:

1.静态算法:

Static-rr

1.不支持socat(weight只能是0/1)

2.不支持慢启动 (慢启动即指服务器在刚接入到集群中的时候流量请求是缓慢增加的而不是一上来就处理大量流量,保证了服务器的稳定性)

慢启动 适用于逐步增加服务器的负载,以确保在服务器启动或恢复后逐渐将流量引导到该服务器,避免突然的高负载导致性能问题。

3.后端主机数量无限制

First

1.不支持socat(weight只能是0/1)

2.根据列表位置自上而下顺序调度服务器

3.当第一台服务器连接数达到上限才会,把多余请求分配给下一台服务器,以此内推

4.忽略权重设置

2.动态算法:

根据后端服务器的状态适度调整、优先给负载低的服务器、可使用socat热管理(动态调整),无需重启服务

Roundrobin :

先考虑负载,负载相同时,再考虑权重.

1.基于权重的轮询动态调度、支持权重动态调节

2.动态轮训,支持scout

3.支持慢启动

4.后端支持4095个RealServer

5.默认调度算法、应用最为广泛

Leastconn:

(新客户连接)先考虑连接数,数少的优先,连接数相同时,再考虑权重.

1.加权的最少连接动态调度算法

2.支持慢启动

3.适合长连接场景,如MySQL等

source:

默认静态 指定hash-type consistent -->动态

配置文件:
listen  webclst
        bind *:80
        mode http
        balance source
        server web1 10.211.55.10:80 check inter 1
        server web2 10.211.55.20:80 check inter 1

#重启haproxy服务器



#测试结果       发现客服端与20主机产生粘性
[root@Client ~]# curl 10.211.55.100
Hello! Welcome Visit MyWebSite My IP is .20
[root@Client ~]# curl 10.211.55.100
Hello! Welcome Visit MyWebSite My IP is .20
[root@Client ~]# curl 10.211.55.100
Hello! Welcome Visit MyWebSite My IP is .20
[root@Client ~]# curl 10.211.55.100
Hello! Welcome Visit MyWebSite My IP is .20
[root@Client ~]# curl 10.211.55.100
Hello! Welcome Visit MyWebSite My IP is .20
[root@Client ~]# curl 10.211.55.100
Hello! Welcome Visit MyWebSite My IP is .20

#缺点是如果是很多台客服端在同一个局域网内,则局域网内每次流量都会打到同一台主服务器

map-base:

#对分配根据取模运算结果来分配对应服务器 
# hash(source IP)值%后端所有服务器总weight 
#缺点是静态、不支持慢启动不能动态调整权值、但是可以上下线服务器

一致性hash

在这里插入图片描述

listen  webclst
        bind *:80
        mode http
        balance source
        hash-type consistent
        server web1 10.211.55.10:80 check inter 1
        server web2 10.211.55.20:80 check inter 1
        
        
        
#重启服务器
[root@Haproxy ~]# systemctl restart haproxy.service


[root@Client ~]# curl 10.211.55.100
Hello! Welcome Visit MyWebSite My IP is .20
[root@Client ~]# curl 10.211.55.100
Hello! Welcome Visit MyWebSite My IP is .20
[root@Client ~]# curl 10.211.55.100
Hello! Welcome Visit MyWebSite My IP is .20
[root@Client ~]# curl 10.211.55.100
Hello! Welcome Visit MyWebSite My IP is .20
[root@Client ~]# curl 10.211.55.100
Hello! Welcome Visit MyWebSite My IP is .20
#这里把web2关了:
[root@Haproxy ~]# echo "disable server  webclst/web2 " | socat stdio /var/lib/haproxy/stats
#就自动顺时针跳到下一个server了
[root@Client ~]# curl 10.211.55.100
Hello!
Welcome to MyWebSite
My IP is .10
[root@Client ~]# curl 10.211.55.100
Hello!
Welcome to MyWebSite
My IP is .10
[root@Client ~]# curl 10.211.55.100
Hello!
Welcome to MyWebSite
My IP is .10

uri

在这里插入图片描述

基于应用层 ; 只支持mode http,mode TCP不支持

默认静态 指定hash-type consistent 动态

listen  webclst
        bind *:80
        mode http
        balance uri
        hash-type consistent
        server web1 10.211.55.10:80 check inter 1
        server web2 10.211.55.20:80 check inter 1


#重启haproxy服务
[root@Haproxy ~]# systemctl restart haproxy.service

#RS1 、RS2写入测试页面:
[root@RS1 ~]# echo RS1 index1 > /usr/share/nginx/html/index1.html
[root@RS1 ~]# echo RS1 index2 > /usr/share/nginx/html/index2.html

[root@RS2 ~]# echo RS2 index1 > /usr/share/nginx/html/index1.html
[root@RS2 ~]# echo RS2 index2 > /usr/share/nginx/html/index2.html
#测试结果: 不同的uri 绑定到了服务器 

[root@Client ~]# curl 10.211.55.100/index.html
Hello! Welcome Visit MyWebSite My IP is .20
[root@Client ~]# curl 10.211.55.100/index1.html
RS1 index1
[root@Client ~]# curl 10.211.55.100/index2.html
RS2 index2
[root@Client ~]# curl 10.211.55.100/index2.html
RS2 index2
[root@Client ~]# curl 10.211.55.100/index1.html
RS1 index1

url_param

#HAProxy参数
listen webclst
  bind *:80
  mode http
  balance url_param name,userid
  hash-type consistent

  server web1 10.211.55.10:80 check inter 2 fall 3 rise 5 weight 1
  server web2 10.211.55.20:80 check inter 2 fall 3 rise 5 weight 1
  
  #重启服务

测试结果

[root@Client ~]# curl 10.211.55.100/index.html?name=123
This is 10.211.55.20 RS2
[root@Client ~]# curl 10.211.55.100/index.html?name=test
This is 10.211.55.10 RS1
[root@Client ~]# curl 10.211.55.100/index.html?name=test123
This is 10.211.55.10 RS1
[root@Client ~]# curl 10.211.55.100/index.html?name=123test
This is 10.211.55.10 RS1
[root@Client ~]# curl 10.211.55.100/index.html?name=123
This is 10.211.55.20 RS2
[root@Client ~]# curl 10.211.55.100/index.html?name=123test
This is 10.211.55.10 RS1
[root@Client ~]# curl 10.211.55.100/index.html?name=test123
This is 10.211.55.10 RS1
[root@Client ~]# curl 10.211.55.100/index.html?name=test
This is 10.211.55.10 RS1

hdr

#HAProxy配置
 listen webclst
   bind *:80
   mode http
   balance hdr(User-Agent)
   hash-type consistent

#重启服务

#测试结果
[root@Client ~]# curl -A "Curl"  10.211.55.100/index.html
This is 10.211.55.10 RS1
[root@Client ~]# curl -A "Curl"  10.211.55.100/index.html
This is 10.211.55.10 RS1
[root@Client ~]# curl -A "wget"  10.211.55.100/index.html
This is 10.211.55.20 RS2
[root@Client ~]# curl -A "wget"  10.211.55.100/index.html
This is 10.211.55.20 RS2
3.Haproxy算法总结:
#静态
static-rr--------->tcp/http
first------------->tcp/http
#动态
roundrobin-------->tcp/http
leastconn--------->tcp/http
#以下静态和动态取决于hash_type是否consistent
source------------>tcp/http
Uri--------------->http
url_param--------->http
hdr--------------->http

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

三、Haproxy高级用法

(一).Cookie会话保持:

mode仅支持http模式,不支持tcp

在配置文件中添加一行Cookie 再设置对应server对应的cookie值

  listen webclst
  bind *:80
  mode http
  balance roundrobin
  #添加cookie 名称为WebCookie  
  #insert 表示插入cookie
  #nocache 不允许Haproxy与Client之间存在CDN缓存cache,否则经过CDN的都到同一台RS服务器
  #indirect  如果有cookie,则不再发送cookie
  
  cookie WebCookie insert nocache indirect

  server web1 10.211.55.10:80 cookie cookie1  check inter 2 fall 2 rise 2 weight 1  
  #启用cookie 并设置cookie值
  server web2 10.211.55.20:80 cookie cookie2  check inter 2 fall 2 rise 2 weight 1

#重启HAProxy服务器

#客户端测试:
[root@Client ~]# curl -i 10.211.55.100
...
set-cookie: WebCookie=cookie1; path=/
cache-control: private

This is 10.211.55.10 RS1
[root@Client ~]# curl -i 10.211.55.100
...
set-cookie: WebCookie=cookie2; path=/
cache-control: private

This is 10.211.55.20 RS2
[root@Client ~]# curl -i 10.211.55.100
...
set-cookie: WebCookie=cookie1; path=/
cache-control: private

This is 10.211.55.10 RS1
[root@Client ~]# curl -i 10.211.55.100
...
set-cookie: WebCookie=cookie2; path=/
cache-control: private

在这里插入图片描述
在这里插入图片描述

这里来个浏览器刷新,不会采用轮询,而是cookie持久化到同一台RS服务器

(二).IP透传:
1.七层IP透传

在这里插入图片描述

#开启转发 http七层模式 nginx默认记录来源于Client(99)
[root@RS1 ~]# cat /var/log/nginx/access.log
10.211.55.100 - - [10/Aug/2024:02:51:25 +0800] "GET / HTTP/1.1" 200 43 "-" "curl/7.76.1" "10.211.55.99"
10.211.55.100 - - [10/Aug/2024:02:51:27 +0800] "GET / HTTP/1.1" 200 43 "-" "curl/7.76.1" "10.211.55.99"

-----------------------------------------------------------------------------------------------

#Apache Server 
[root@RS2 ~]# systemctl stop nginx.service
[root@RS2 ~]# systemctl start httpd
[root@RS2 ~]# echo This is 10.211.55.20 RS > /var/www/html/index.html
#这时候是看不到来源的❌:
[root@RS2 ~]# cat /var/log/httpd/access_log
10.211.55.100 - - [10/Aug/2024:02:55:48 +0800] "GET / HTTP/1.1" 200 24 "-" "curl/7.76.1"



#编辑httpd主配置文件:找到日志格式(200左右)添加
[root@RS2 ~]# vim /etc/httpd/conf/httpd.conf
194 LogLevel warn
195
196 <IfModule log_config_module>
197     #
198     # The following directives define some format nicknames for use with
199     # a CustomLog directive (see below).
200     #
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
203
204     <IfModule logio_module>
205       # You need to enable mod_logio.c to use %I and %O
206       LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\    " %I %O" combinedio
207     </IfModule>


---------------------------------------------------------------------------------------------
[root@RS2 ~]# systemctl restart httpd
#现在apache记录开启成功✅
[root@RS2 ~]# cat /var/log/httpd/access_log
10.211.55.100 - - [10/Aug/2024:02:55:48 +0800] "GET / HTTP/1.1" 200 24 "-" "curl/7.76.1"
10.211.55.99  10.211.55.100 - - [10/Aug/2024:03:04:42 +0800] "GET / HTTP/1.1" 200 24 "-" "curl/7.76.1"
2.TCP 四层 IP透传
默认nginx:
Haproxy 配置文件只改了mode 为tcp
[root@RS1 ~]# > /var/log/nginx/access.log
[root@RS1 ~]# cat /var/log/nginx/access.log
10.211.55.100 - - [10/Aug/2024:03:09:35 +0800] "GET / HTTP/1.1" 200 43 "-" "curl/7.76.1" "-"
 

#haproxy配置文件 加上 send-proxy
listen  webclst
        bind *:80
        mode tcp
        balance roundrobin
        cookie WC insert nocache indirect
        server web1 10.211.55.10:80  send-proxy   cookie web1  check inter 1
        server web2 10.211.55.20:80 cookie web2  check inter 1
        
        
#再次访问10 报错

[root@Client ~]# curl  10.211.55.100
<html>
<head><title>400 Bad Request</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
<hr><center>nginx/1.20.1</center>
</body>
</html>

#RS1
#修改nginx配置文件
    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;
        
        ...
        
        
        
        
   
  #重启nginx服务      
  #结果
  [root@Client ~]# curl  10.211.55.100
Hello!
Welcome to MyWebSite
My IP is .10
  
  
[root@RS1 ~]# > /var/log/nginx/access.log
[root@RS1 ~]# cat /var/log/nginx/access.log
[root@RS1 ~]# cat /var/log/nginx/access.log
10.211.55.100 - - [10/Aug/2024:03:26:04 +0800] "GET / HTTP/1.1" 200 43 "-" "10.211.55.99""curl/7.76.1" "-"
        
#apache 无法在此版本配置四层IP透传

        
(三).ACL
1.根据主机名匹配ACL
#HAProxy设置
frontend webclst
  bind *:80
  mode http
  acl test hdr(host) -i www.test.com
  use_backend webclst-host if test
  default_backend default-host

backend webclst-host
  mode http
  server web1 10.211.55.10:80 check inter 2 fall 2 rise 2
backend default-host
  mode http
  server web2 10.211.55.20:80 check inter 2 fall 2 rise 2

#重启Haproxy服务器
#在客服端添加几条本地解析
[root@Client ~]# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
10.211.55.99        Client
10.211.55.100     www.test.com
10.211.55.100     test.org
10.211.55.100     www.server.com
10.211.55.100     server.org

#测试结果: 只有在主机名为ACL规定的值时才访问到RS1、否则都是RS2
[root@Client ~]# curl test.org
This is 10.211.55.20 RS2
[root@Client ~]# curl www.test.com
This is 10.211.55.10 RS1
[root@Client ~]# curl www.server.com
This is 10.211.55.20 RS2
[root@Client ~]# curl server.org
This is 10.211.55.20 RS2
2.根据主机名后缀匹配ACL
#HAProxy设置
frontend webclst
  bind *:80
  mode http
  acl test hdr_end(host) -i .org
  use_backend webclst-host if test
  default_backend default-host

backend webclst-host
  mode http
  server web1 10.211.55.10:80 check inter 2 fall 2 rise 2
backend default-host
  mode http
  server web2 10.211.55.20:80 check inter 2 fall 2 rise 2


#重启HAProxy服务器


#测试结果
[root@Client ~]# curl test.org
This is 10.211.55.10 RS1
[root@Client ~]# curl www.server.com
This is 10.211.55.20 RS2
[root@Client ~]# curl www.test.com
This is 10.211.55.20 RS2
3.根据主机名前缀匹配ACL
#Haproxy设置
frontend webclst
  bind *:80
  mode http
  acl test hdr_beg(host) -i www
  use_backend webclst-host if test
  default_backend default-host


#重启haproxy

#测试结果:
[root@Client ~]# curl www.test.com
This is 10.211.55.10 RS1
[root@Client ~]# curl www.server.com
This is 10.211.55.10 RS1
[root@Client ~]# curl server.org
This is 10.211.55.20 RS2
[root@Client ~]# curl test.org
This is 10.211.55.20 RS2
4.基于子串匹配ACL规则:
#HAProxy设置        #含有test到子串的就访问RS1
  acl test base_sub -m sub test
  
#重启Haproxy服务
  
#测试结果:
 
[root@Client ~]# curl www.test.com
This is 10.211.55.10 RS1
[root@Client ~]# curl www.server.com
This is 10.211.55.20 RS2
[root@Client ~]# curl test.org
This is 10.211.55.10 RS1
[root@Client ~]# curl server.org
This is 10.211.55.20 RS2
5.基于域名匹配ACL
  #HAProxy配置
  acl domain hdr_dom(host) -i www.test.com
  use_backend webclst-host if domain
  
  #重启Haproxy服务
  
  #测试结果        域名是www.test.com才能装到RS1
[root@Client ~]# curl www.test.com
This is 10.211.55.10 RS1
[root@Client ~]# curl www.server.com
This is 10.211.55.20 RS2
[root@Client ~]# curl test.org
This is 10.211.55.20 RS2
[root@Client ~]# curl server.org
This is 10.211.55.20 RS2
  
6.基于IP匹配ACL
#HAProxy配置
  acl Ctrl_IP src 10.211.55.90 192.168.0.0/24    #相当于对于RS1访问的白名单功能,只有写在名单内的才能访问
    use_backend webclst-host if Ctrl_IP

#重启Haproxy服务

#测试结果
#客户端没在白名单内,无法访问到RS1

[root@Client ~]# curl www.test.com
This is 10.211.55.20 RS2
[root@Client ~]# curl server.org
This is 10.211.55.20 RS2
[root@Client ~]# curl test.org
This is 10.211.55.20 RS2
[root@Client ~]# curl www.server.com
This is 10.211.55.20 RS2

#在允许的主机测试:
[root@RHEL9 ~]# curl 10.211.55.100
This is 10.211.55.10 RS1
[root@RHEL9 ~]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.211.55.90  netmask 255.255.255.0  broadcast 10.211.55.255
        inet6 fe80::bf13:f34f:717b:8cd3  prefixlen 64  scopeid 0x20<link>
        ether 00:1c:42:73:f5:dd  txqueuelen 1000  (Ethernet)
        RX packets 89  bytes 10302 (10.0 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 147  bytes 19671 (19.2 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
7.如何将把白名单模式改为黑名单模式?
#HAProxy配置文件注释掉原来的if , 使用http-request deny 方式转为黑名单模式
 ...
   acl Ctrl_IP src 10.211.55.99 192.168.0.0/24
  #use_backend webclst-host if Ctrl_IP
  http-request deny if Ctrl_IP
  default_backend default-host
  ...
  
#重启haproxy服务

#测试结果:相当于RS1保护起来了,但是想要RS1访问的话使用ACL组合即可
#对于没有明确写入到黑名单内的访问到RS2
[root@Haproxy ~]# curl 10.211.55.100
This is 10.211.55.20 RS2

#在黑名单内的403拒绝
[root@Client ~]# curl www.test.com
<html><body><h1>403 Forbidden</h1>
Request forbidden by administrative rules.
</body></html>
8.基于浏览器的ACL规则

限制部分浏览器的访问

#HAProxy配置
frontend webclst
  bind *:80
  mode http
  acl BadWebBrowers hdr_sub(User-Agent) -i curl wget
  http-request deny if BadWebBrowers
  default_backend default-host


#重启haproxy服务


#测试结果:

在这里插入图片描述

#####9. 基于动静分离ACL匹配规则

在这里插入图片描述

#HAProxy配置
frontend webclst
  bind *:80
  mode http

  acl static path_end -i .html .png .css .js .jpg
  acl dynamic path_end -i .php
  use_backend webclst-host if dynamic
  default_backend default-host

#重启haproxy服务


#测试结果: 这里RS1作为动态资源服务器,RS2作为静态资源服务器,访问不同文件的时候自动分配到对应服务器

在这里插入图片描述
在这里插入图片描述

10.多条ACL组合

不同的ACL组合逻辑

test1 || test2 ----------------或关系,满足其一即可

test1 test2 ----------------与关系,两者都需满足 (默认)

!test1 ----------------表示否定

#HAProxy设置
  acl test1 base_sub -m sub test
  acl test2 path_sub -m sub www
  use_backend webclst-host if test1 test2       #test1 和 test2 同时满足才到RS1


#RS1上做一个目录及页面
[root@RS1 ~]# mkdir /usr/share/nginx/html/www -p
[root@RS1 ~]# echo ALC test! >  /usr/share/nginx/html/www/index.html


#测试结果:
[root@Client ~]# curl www.test.com/www/index.html
ALC test!
(四).HAProxy的HTTPS实现
[root@Haproxy ~]# mkdir -p /etc/haproxy/certs
[root@Haproxy ~]# cd /etc/haproxy/certs/

[root@Haproxy certs]# openssl req -newkey rsa:2048 -nodes -sha256 -keyout /etc/haproxy/certs/https.key -x509 -days 365 -out /etc/haproxy/certs/https.crt
..+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*...+............+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.....+...+..........+.....+...+....+...+............+.....+......+.+......+...............+..............+.+..+.+..+.......+..+..........+.....+...............+...+................+..+....+........+......+..........+..........................+.+.........+...+..+.+...+...........+.+.....+.......+.....+...+...+....+......+....................+.+......+..+.......+...+.....+......+....+........+...+....+..+......+....+...+.....+......+....+.....+.......+.....+...+............+....+..+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.+.+.....+.+.....+...+.......+..+.+......+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*......+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*......+..+...+......+.+...+...+............+............+..............+....+.....+.+..+...+.........+.+.....+.+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:China
String too long, must be at most 2 bytes long
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:ShaanXi
Locality Name (eg, city) [Default City]:Xian
Organization Name (eg, company) [Default Company Ltd]:PeiHua
Organizational Unit Name (eg, section) []:PH
Common Name (eg, your name or your server's hostname) []:https
Email Address []:test@163.com



#证书和密钥写到一起:
[root@Haproxy certs]# ll
总用量 8
-rw-r--r-- 1 root root 1387  8月 10 21:12 https.crt
-rw------- 1 root root 1704  8月 10 21:10 https.key
[root@Haproxy certs]# cat https.crt https.key  > https.pem


#HAProxy配置文件添加HTTPS 测试server

listen web-https
  bind *:443 ssl crt /etc/haproxy/certs/https.pem
  mode http
  balance roundrobin
  server web1 10.211.55.10:80 check inter 2 fall 2 rise 2
  server web2 10.211.55.20:80 check inter 2 fall 2 rise 2
  
#重启配置文件

#测试 :  这里server实际上该是https的,这里只是简单测试,可用过http 访问
[root@Client ~]# for i in {1..10}; do curl -k https://10.211.55.100; done
This is 10.211.55.20 RS2
This is 10.211.55.10 RS1
This is 10.211.55.20 RS2
This is 10.211.55.10 RS1
This is 10.211.55.20 RS2
This is 10.211.55.10 RS1
This is 10.211.55.20 RS2
This is 10.211.55.10 RS1
This is 10.211.55.20 RS2
This is 10.211.55.10 RS1

在这里插入图片描述

开启全站加密,即将80的内容强制重定向为HTTPS的:

#在集群中加入
redirect scheme https if ! { ssl_fc }

在这里插入图片描述

(五).HTTP自定义的错误页面
#创建一个放自定义haproxy错误页面的目录

[root@Haproxy ~]# ll /etc/haproxy/errorpage/
-rw-r--r-- 1 root root 189  8月 10 22:14 503.http

#根据默认模版页面修改
[root@Haproxy ~]# rpm -ql haproxy | grep http
/usr/share/doc/haproxy/design-thoughts/http2.txt
/usr/share/doc/haproxy/design-thoughts/http_load_time.url
/usr/share/doc/haproxy/internals/http-cookies.txt
/usr/share/doc/haproxy/internals/http-docs.txt
/usr/share/doc/haproxy/internals/http-parsing.txt
/usr/share/doc/haproxy/option-http_proxy.cfg
/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

#将模版复制到目录下 、 自定义编辑html内的内容
[root@Haproxy ~]# cp /usr/share/haproxy/503.http  /etc/haproxy/errorpage/

#在haproxy中添加一条错误页面指定
...
 61     timeout http-keep-alive 10s
 62     timeout check           10s
 63     maxconn                 3000
 64
 65     errorfile 503 /etc/haproxy/errorpage/503.http
 66 #---------------------------------------------------------------------
 67 # main frontend which proxys to the backends
 68 #---------------------------------------------------------------------
...

#重启服务器
[root@Haproxy ~]#  systemctl restart haproxy.service

在这里插入图片描述

#测试

#默认503页面
[root@Client ~]# curl  10.211.55.100
<html><body><h1>503 Service Unavailable</h1>
No server is available to handle this request.
</body></html>
#自定义后:
[root@Client ~]# curl  10.211.55.100
<html><body><h1>先休息会吧!</h1>
抱歉,服务器旅游去咯!
</body></html>

**遇到的问题:**错误文件的条目写在defaults下 ,然后自定义并不是任意,可以根据模版来重新自定义(无格式书则提示找不到可分析的header)

xxx/haproxy/errorpage/503.http': unable to parse headers (error offset: 1)
(六).HAProxy四层负载(MySQL):

针对与TCP应用到访问场景(Redis、MySQL、RabbitMQ、Mencache等)

#RS1和RS2上安装mariadb 、 启动
[root@RS1 ~]# dnf install mariadb-server -y
[root@RS1 ~]# systemctl enable --now mariadb

#修改mariadb配置文件以便区分 添加图上蓝色的行即可
[root@RS1 ~]# vim /etc/my.cnf.d/mariadb-server.cnf


#修改mariadb-server.cfg后需要重启数据库使Server—ID生效

在这里插入图片描述

创建test用户并添加密码和远程登录

[root@RS1 ~]# mysql
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 3
Server version: 10.5.22-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> CREATE USER 'test'@'%' IDENTIFIED BY 'test';
Query OK, 0 rows affected (0.012 sec)

MariaDB [(none)]> GRANT ALL PRIVILEGES ON *.* TO 'test'@'%' WITH GRANT OPTION;
Query OK, 0 rows affected (0.001 sec)

MariaDB [(none)]> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.002 sec)

#在隔壁RS2测试一下: 看到ID是RS1的 测试👌
[root@RS2 ~]# mysql -utest -p -h 10.211.55.10
Enter password:
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 4
Server version: 10.5.22-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> SELECT  @@server_id;
+-------------+
| @@server_id |
+-------------+
|           1 |
+-------------+
1 row in set (0.002 sec)


#RS1
[root@RS1 ~]# mysql -utest -p -h 10.211.55.20
Enter password:
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 4
Server version: 10.5.22-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> SELECT @@SERVER_ID;
+-------------+
| @@SERVER_ID |
+-------------+
|           2 |
+-------------+
1 row in set (0.001 sec)

添加HAProxy配置文件:

[root@Haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen dbserver
  bind *:3306
  mode tcp
  balance static-rr
  server db1 10.211.55.10:3306 check inter 2 fall 2 rise 2
  server db2 10.211.55.20:3306 check inter 2 fall 2 rise 2
  
  #重启HAProxy服务器
  [root@Haproxy ~]# systemctl restart haproxy.service
  
  #为方便测试,客户端也搞个Mariadb
  [root@Client ~]# yum install mariadb-server -y
  [root@Client ~]# systemctl start mariadb.service
  


#测试为1、2、1、2..轮询
[root@Client ~]# mysql -u test -ptest -h 10.211.55.20
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 4
Server version: 10.5.22-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> SELECT @@server_id;
+-------------+
| @@server_id |
+-------------+
|           2 |
+-------------+
1 row in set (0.001 sec)

MariaDB [(none)]> Ctrl-C -- exit!
Aborted
[root@Client ~]# mysql -u test -ptest -h 10.211.55.100
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 13
Server version: 10.5.22-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> SELECT @@server_id;
+-------------+
| @@server_id |
+-------------+
|           1 |
+-------------+
1 row in set (0.002 sec)

MariaDB [(none)]> quit
Bye
[root@Client ~]# mysql -u test -ptest -h 10.211.55.100
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 5
Server version: 10.5.22-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> SELECT @@server_id;
+-------------+
| @@server_id |
+-------------+
|           2 |
+-------------+
1 row in set (0.002 sec)

MariaDB [(none)]> exit;
Bye
[root@Client ~]# mysql -u test -ptest -h 10.211.55.100
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 14
Server version: 10.5.22-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> SELECT @@server_id;
+-------------+
| @@server_id |
+-------------+
|           1 |
+-------------+
1 row in set (0.004 sec)

MariaDB [(none)]> exit;
Bye
[root@Client ~]# mysql -u test -ptest -h 10.211.55.100
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 6
Server version: 10.5.22-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> SELECT @@server_id;
+-------------+
| @@server_id |
+-------------+
|           2 |
+-------------+
1 row in set (0.006 sec)

MariaDB [(none)]>
(七).开启haproxy的stat报告
#在集群配置后添加一个stats

listen stats      #集群
mode http         
bind *:9999       #端口号可以自定义
stats enable      #开启状态页面
stats refresh 1   #自动刷新时间为1s,不写则需要手动刷新
stats uri /status #管理的地址 , 即在端口号后面跟这里的值进入到状态报告界面
stats auth admin:admin        #设置认证的账户和密码


还需要注意的是not checked的情况 ,其实是在server后面需要添加服务器检查:check inter 1  

认证登陆后即可看到不同集群不同server的详细状态信息
认证登陆后即可看到不同集群不同server的详细状态信息

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值