HAProxy的安装与配置

目录

一、HAProxy的概念

1.1 HAProxy简介

1.2  HAProxy的优点

二、 HAProxy的工作原理

2.1 负载均衡算法

 2.2 健康检查

2.3 会话保持

 三、 HAProxy的安装与配置

3.1 实验环境

3.2 软件安装

3.2.1 在安装之前需要关闭每个虚拟机的防火墙和selinux

3.3  HAProxy的基本信息

3.3.1 在node1.com上进行操作:

3.3.2 在node2.com上进行操作:

3.4 测试:

3.5 server配置

3.5.1 haproxy代理参数小实验

3.6 haproxy的状态界面实验:

3.6.1 在haproxy.conf中进行配置,然后重启配置

3.6.2 在浏览器上进行查看:

3.7 socat工具

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

3.7.2 常用示例:

3.7.3 针对多进程处理方法

四、haproxy的算法

4.1 静态算法

4.1.1 static-rr:基于权重的轮询调度

4.1.2 first

4.2 动态算法

4.2.1 roundrobin

4.2.2 leastconn

4.3 其他算法

4.3.1 source

4.3.2 uri

4.3.3 url_param

4.3.4 hdr

4.3.5 算法总结

4.3.6 各算法使用场景

五、高级功能及配置

5.1 基于cookie的会话保持

5.1.1 配置选项

5.1.2 配置示例

5.1.3 验证cookie信息

5.2 HAProxy状态页

5.2.1 状态页配置项

5.2.2 启用状态页

5.2.3 登录状态页

5.2.4 backend server信息

5.3 IP透传

5.3.1 四层IP透传

5.3.3 七层IP透传

5.4 ACL

5.4.1 ACL配置选项

5.4.2 多个ACL的组合调用方式

5.4.3 ACL示例-域名匹配

5.4.4 ACL示例-基于源IP或子网调度访问

5.4.5 ACL示例-基于源地址的访问控制

5.4.6 ACL示例-匹配浏览器类型

5.4.7 ACL示例-基于文件后缀名实现动静分离

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

5.5 自定义HAProxy 错误界面

5.5.1 基于自定义的错误页面文件

5.5.2 基于http重定向错误页面

5.6 HAProxy 四层负载

5.7 HAProxy https 实现

5.7.1 证书制作

5.7.2 https配置示例

5.8 子配置文件:


一、HAProxy的概念

1.1 HAProxy简介

企业版网站:https://www.haproxy.com
社区版网站:http://www.haproxy.org
github:https://github.com/haprox

         HAProxy是一款开源、高性能的负载均衡器和代理服务器,专为TCP和HTTP应用而设计。它可以将客户端的请求分发到多台后端服务器,从而提高应用的可用性和性能。HAProxy支持多种负载均衡算法和健康检查机制,是构建高可用性系统的理想选择。

1.2  HAProxy的优点

高性能:HAProxy采用事件驱动模型,能够处理大量并发连接。
灵活性强:支持多种负载均衡算法和调度策略,适应不同的应用场景。
高可用性:通过健康检查和故障转移机制,确保服务的连续性。
丰富的功能:支持SSL终止、HTTP重写、压缩等多种功能。

二、 HAProxy的工作原理

2.1 负载均衡算法

HAProxy支持多种负载均衡算法,包括:轮询调度(Round Robin):将请求依次分配给每个后端服务器。
最少连接(Least Connections):将请求分配给当前连接数最少的服务器。
源地址哈希(Source Hashing):根据客户端的IP地址分配请求,确保同一客户端的请求总是分配到同一台服务器。
加权轮询(Weighted Round Robin):根据服务器的权重分配请求,权重高的服务器分配更多的请求

 2.2 健康检查

        为了确保请求只被分配到正常工作的服务器,HAProxy提供了健康检查机制。健康检查可以定期检测后端服务器的状态,根据检测结果动态调整服务器的可用性。常见的健康检查类型包括TCP连接检查、HTTP请求检查等。

2.3 会话保持

         在某些应用场景中,需要确保同一客户端的所有请求都分配到同一台服务器上,HAProxy提供了会话保持机制来实现这一需求。会话保持可以通过源地址哈希、Cookie等方式实现。

 三、 HAProxy的安装与配置

3.1 实验环境

!!!这里为了实验简单化把客户端省略 ,也就是开启三台虚拟机!!!

主机名ip
haproxy.com192.168.10.40
node1.com192.168.10.10
node2.com192.168.10.20

3.2 软件安装

3.2.1 在安装之前需要关闭每个虚拟机的防火墙和selinux

[root@haproxy ~]# systemctl stop firewalld
[root@haproxy ~]# setenforce 0

[root@haproxy ~]# yum search haproxy                #查看系统自带的haproxy,下载简单
Updating Subscription Management repositories.
Unable to read consumer identity

This system is not registered with an entitlement server. You can use subscription-manager to register.

Last metadata expiration check: 0:17:50 ago on Thu 08 Aug 2024 05:19:22 PM CST.
========================================================== Name & Summary Matched: haproxy ===========================================================
haproxy.x86_64 : HAProxy reverse proxy for high availability environments
pcp-pmda-haproxy.x86_64 : Performance Co-Pilot (PCP) metrics for HAProxy


[root@haproxy ~]# yum install haproxy.x86_64  -y        #安装haproxy

[root@haproxy ~]# haproxy -v        #查看版本信息
HAProxy version 2.4.17-9f97155 2022/05/13 - https://haproxy.org/
Status: long-term supported branch - will stop receiving fixes around Q2 2026.
Known bugs: http://www.haproxy.org/bugs/bugs-2.4.17.html
Running on: Linux 5.14.0-162.6.1.el9_1.x86_64 #1 SMP PREEMPT_DYNAMIC Fri Sep 30 07:36:03 EDT 2022 x86_64

3.3  HAProxy的基本信息

[root@haproxy ~]# rpm -qc haproxy        #找基本信息位置
/etc/haproxy/haproxy.cfg
/etc/logrotate.d/haproxy
/etc/sysconfig/haproxy

[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg         #红色的是在文件添加的内容

#---------------------------------------------------------------------
# Example configuration for a possible web application.  See the
# full configuration options online.
#
#   https://www.haproxy.org/download/1.8/doc/configuration.txt
#
#---------------------------------------------------------------------

#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
    # to have these messages end up in /var/log/haproxy.log you will
    # need to:
    #
    # 1) configure syslog to accept network log events.  This is done
    #    by adding the '-r' option to the SYSLOGD_OPTIONS in
    #    /etc/sysconfig/syslog
    #
    # 2) configure local2 events to go to the /var/log/haproxy.log
    #   file. A line like the following can be added to
    #   /etc/sysconfig/syslog
    #
    #    local2.*                       /var/log/haproxy.log
    #
    log         127.0.0.1 local2                                #定义全局的syslog服务器;日志服务器需要开启UDP协议,最多可以定义两个

    chroot      /var/lib/haproxy                                #锁定运行目录
    pidfile     /var/run/haproxy.pid                        #指定pid文件路径
    maxconn     4000                                              #最大并发连接数
    user        haproxy                                                # 用户
    group       haproxy                                                #用户组
    daemon                                                                #以守护进程运行

    # turn on stats unix socket
    stats socket /var/lib/haproxy/stats

    # utilize system-wide crypto-policies
    ssl-default-bind-ciphers PROFILE=SYSTEM
    ssl-default-server-ciphers PROFILE=SYSTEM
    nbproc 2                #启用多进程
    cpu-map 1 0             #进程和cpu核心绑定防止cpu抖动从而减少系统资源消耗
    cpu-map 2 1                #2 表示第二个进程,1 表示第二个cpu核心

    #nbthread 2       #启用多线程

#---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block
#---------------------------------------------------------------------
defaults
    mode                    http                                        # HAProxy实例使用的连接协议
    log                     global                                          #指定日志地址和记录日志条目的

syslog/rsyslog日志设备               #此处的 global表示使用 global配置段中设定的log值。

                                   
    option                  httplog                                     #日志记录选项,httplog表示记录与 HTTP

会话相关的各种属性值          #包括 HTTP请求、会话状态、连接数、源地 址以及连接时间等

                                  
    option                  dontlognull                        #dontlognull表示不记录空会话连接日志
    option http-server-close                  #等待客户端完整HTTP请求的时间,此处为等待10s。

    option forwardfor       except 127.0.0.0/8                #透传客户端真实IP至web服务器
    option                  redispatch                     #当server Id对应的服务器挂掉后,强制定向到其他健康的服务器,重新派发

    retries                 3                                #连接后端服务器失败次数
    timeout http-request    10s                  #等待客户端请求完全被接收和处理的最长时间

    timeout queue           1m                    #设置删除连接和客户端收到503或服务不可用等提示信息前的等待时间

          
    timeout connect         10s                        #设置等待服务器连接成功的时间
    timeout client          1m                    #设置允许客户端处于非活动状态,即既不发送数据也不接收数据的时间

  
    timeout server          1m                     #设置服务器超时时间,即允许服务器处于既不接收也不发送数据的非活动时间

    timeout http-keep-alive 10s        #session 会话保持超时时间,此时间内会转发到相同的后端服务器
    timeout check           10s            #指定后端服务器健康检查的超时时间    
    maxconn                 3000

#---------------------------------------------------------------------
# main frontend which proxys to the backends
#--------------------------------------------------------------------

 frontend webcluster        #前端,相当于nginx中的server {}
    bind *:80                           #指定HAProxy的监听地址,可以是IPV4或IPV6,可以同时监听多个IP或端口,可同时用于listen字段中
    mode http                        #指定负载协议类型,和对应的frontend必须一致
    use_backend webcluster-host                

backend webcluster-host        #后端,相当于nginx中的upstream {}
    balance roundrobin
    server web1 192.168.10.10:80 check inter 3s fall 3 rise 5
    server web2 192.168.10.20:80 check inter 3s fall 3 rise 5

#上面也可以简写

listen webserver_80        #同时拥有前端和后端配置,配置简单,生产推荐使用
    bind *:80
    mode http
    option forwardfor        #配置选项
注意:option后面加 httpchk,smtpchk,mysql-check,pgsql-check,ssl-hello-chk方法,可用于实现更 多应用层检测功能。
    server web1 192.168.0.10:80 check inter 3s fall 3 rise 5        #定义后端real server,必须指定IP和端口
    server web2 192.168.0.20:80 check inter 3s fall 3 rise 5


frontend main
    bind *:5000
    acl url_static       path_beg       -i /static /images /javascript /stylesheets
    acl url_static       path_end       -i .jpg .gif .png .css .js

    use_backend static          if url_static
    default_backend             app

#---------------------------------------------------------------------
# static backend for serving up images, stylesheets and such
#---------------------------------------------------------------------
backend static
    balance     roundrobin
    server      static 127.0.0.1:4331 check

#---------------------------------------------------------------------
# round robin balancing between the various backends
#---------------------------------------------------------------------
backend app
    balance     roundrobin
    server  app1 127.0.0.1:5001 check
    server  app2 127.0.0.1:5002 check
    server  app3 127.0.0.1:5003 check
    server  app4 127.0.0.1:5004 check

[root@haproxy ~]# pstree -p | grep haproxy        #查看多进程信息
           |-haproxy(2152)-+-haproxy(2154)
           |               `-haproxy(2155)

[root@haproxy ~]# systemctl restart haproxy.service 
[root@haproxy ~]# 
 

3.3.1 在node1.com上进行操作:

[root@node1 ~]# yum install nginx -y        #下载nginx

[root@node1 ~]# systemctl enable --now nginx        #设置启动和开机自启nginx服务

[root@node1 ~]# echo server1 - 192.168.10.10 > /usr/share/nginx/html/index.html
[root@node2 ~]# systemctl restart nginx.service 

3.3.2 在node2.com上进行操作:

[root@node2 ~]# yum install nginx -y
[root@node2 ~]# systemctl enable --now nginx

[root@node2 ~]# echo server2 - 192.168.10.20 > /usr/share/nginx/html/index.html
[root@node2 ~]# systemctl restart nginx.service 

3.4 测试:

[root@haproxy ~]# for i in {1..10}
> do 
> curl 192.168.10.140
> done

a5b259aac92c4c5a9bbdf5927dffb98e.png

3.5 server配置

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

3.5.1 haproxy代理参数小实验

3.5.1.1 backup    

将后端服务器标记为备份状态,只在所有非备份主机down机时提供服务,类似Sorry Server

3.5.1.1.1 首先,需要关闭node1的httpd服务和node2的nginx.service服务

[root@node1 html]# systemctl disable httpd
[root@node1 html]# systemctl stop httpd


[root@node2 ~]# systemctl disable nginx.service 
Removed "/etc/systemd/system/multi-user.target.wants/nginx.service".
[root@node2 ~]# systemctl stop nginx.service

3.5.1.1.2 然后为了方便在haproxy主上下载httpd,下载好后需要打开配置进行端口更改,因为80端口被占用着,然后打开httpd服务。写一个内容到 /var/www/html/index.html,进行访问一下。

[root@haproxy html]# yum install httpd -y

[root@haproxy html]# vim /etc/httpd/conf/httpd.conf

#Listen 12.34.56.78:80
Listen 8080        #把80端口改为8080端口,防止端口占用

[root@haproxy html]# systemctl start httpd.service 

[root@haproxy html]# echo sorry 下班了!!> /var/www/html/index.html

一种是在浏览器访问,一个是在主机访问

ca0dc8e4544e416da6f7948cbe96819b.png

0a08d2bc60f047e3b825b4b8375df5e7.png

3.5.1.1.3 然后在haproxy.conf中进行配置,重启配置

frontend webcluster
    bind *:80
    mode http
    use_backend webcluster-host

backend webcluster-host
    balance roundrobin
    server web1 192.168.10.10:80 check inter 2 fall 3 rise 5 weight 2
    server web2 192.168.10.20:80 check inter 2 fall 3 rise 5 weight 1
    server web_sorry 192.168.10.140:8080 backup

[root@haproxy html]# systemctl restart haproxy.service 

[root@haproxy html]#

3.5.1.1.4 最后进行测试:

[root@haproxy html]# curl 192.168.10.140
sorry 下班了!!
[root@haproxy html]# curl 192.168.10.140
sorry 下班了!!

3.5.1.2 disabled

将后端服务器标记为不可用状态,即维护状态,除了持久模式 .将不再接受连接,状态为深黄色,优雅下线,不再接受新用户的请求

3.5.1.2.1 首先开启node2主机的nginx.service服务,然后进行测试。

[root@node2 ~]# systemctl restart nginx.service 
[root@haproxy html]# curl 192.168.10.140
server2 - 192.168.10.20
[root@haproxy html]# 

3.5.1.2.2 然后打开haproxy.conf中进行配置,重启配置

frontend webcluster
    bind *:80
    mode http
    use_backend webcluster-host

backend webcluster-host
    balance roundrobin
    server web1 192.168.10.10:80 check inter 2 fall 3 rise 5 weight 2
    server web2 192.168.10.20:80 check inter 2 fall 3 rise 5 weight 1 disabled
    server web_sorry 192.168.10.140:8080 backup

[root@haproxy html]# systemctl restart haproxy.service 

[root@haproxy html]#

3.5.1.2.3 最后进行测试:

[root@haproxy html]# curl 192.168.10.140
sorry 下班了!!

3.5.1.3 redirect prefix http://www.baidu.com/

将请求临时(302)重定向至其它URL,只适用于http模式

3.5.1.3.1 打开haproxy.conf中进行配置,然后重启配置

frontend webcluster
    bind *:80
    mode http
    use_backend webcluster-host

backend webcluster-host
    balance roundrobin
    redirect prefix http://www.baidu.com/

[root@haproxy html]# systemctl restart haproxy.service 
[root@haproxy html]# 

3.5.1.3.2 最后在浏览器上进行测试:

输入完地址后点击‘enter’回车键就进入到百度页面。

b1ef6ffc19b54ae4bf6b6f9d14c06545.png

f9d4f72bd4d948b48afaddca669b9783.png

3.6 haproxy的状态界面实验:

3.6.1 在haproxy.conf中进行配置,然后重启配置

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

listen stats
    mode http
    bind *:7777
    stats enable
    stats refresh 3
    stats uri /status
    stats auth root:root

[root@haproxy html]# systemctl restart haproxy.service 
[root@haproxy html]# 

3.6.2 在浏览器上进行查看:

首先输入地址,然后输入用户名和密码,这样就进入页面了 。

a83617e8aeab43b7bf0598fa55b3d06f.png

bd8605280cc24231beb0987582e8a2ff.png

3.7 socat工具

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

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

#下载socat工具

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

#修改配置文件

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

stats socket /var/lib/haproxy/stats mode 600 level admin

#查看帮助

[root@haproxy ~]# socat -h

[root@haproxy ~]# echo "help" | socat stdio /var/lib/haproxy/stats

3.7.2 常用示例:

#查看haproxy状态

[root@haproxy ~]# echo "show info" | socat stdio /var/lib/haproxy/stats
Name: HAProxy
Version: 2.4.17-9f97155
Release_date: 2022/05/13
Nbthread: 1
Nbproc: 1
Process_num: 1
Pid: 3070
Uptime: 0d 0h17m49s
Uptime_sec: 1069
Memmax_MB: 0
PoolAlloc_MB: 0
PoolUsed_MB: 0
 

#查看集群状态

[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
3 webcluster-host 1 web1 192.168.10.10 2 0 2 2 1133 6 0 7 7 0 0 0 - 80 - 0 0 - - 0
3 webcluster-host 2 web2 192.168.10.20 2 0 1 1 1133 6 0 7 7 0 0 0 - 80 - 0 0 - - 0
6 static 1 static 127.0.0.1 0 0 1 1 1133 8 2 0 6 0 0 0 - 4331 - 0 0 - - 0
7 app 1 app1 127.0.0.1 0 0 1 1 1133 8 2 0 6 0 0 0 - 5001 - 0 0 - - 0
7 app 2 app2 127.0.0.1 0 0 1 1 1132 8 2 0 6 0 0 0 - 5002 - 0 0 - - 0
7 app 3 app3 127.0.0.1 0 0 1 1 1132 8 2 0 6 0 0 0 - 5003 - 0 0 - - 0
7 app 4 app4 127.0.0.1 0 0 1 1 1132 8 2 0 6 0 0 0 - 5004 - 0 0 - - 0
 

#查看集群权重

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

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

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

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

#设置完成后查询权重:

3056f92bae2547bc905d589b1f44fa8c.png

#下线后端服务器

[root@haproxy ~]# echo "disable server webcluster-host/web1" | socat stdio /var/lib/haproxy/stats


#上线后端服务器

[root@haproxy ~]# echo "enable server webcluster-host/web1" | socat stdio /var/lib/haproxy/stats

3.7.3 针对多进程处理方法

如果开启多进程那么我们在对进程的sock文件进行操作时其对进程的操作时随机的
如果需要指定操作进程那么需要用多soct文件方式来完成

[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg 
    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

[root@haproxy ~]# systemctl restart haproxy.service 
[root@haproxy ~]# 

这样每个进程就会有单独的sock文件来进行单独管理

[root@haproxy ~]# ll /var/lib/haproxy/
total 0
srw------- 1 root root 0 Aug 11 18:48 stats
srw------- 1 root root 0 Aug 11 19:20 stats1
srw------- 1 root root 0 Aug 11 19:20 stats2

四、haproxy的算法

HAProxy通过固定参数 balance 指明对后端服务器的调度算法
balance参数可以配置在listen或backend选项中。
HAProxy的调度算法分为静态和动态调度算法
有些算法可以根据参数在静态和动态算法中相互转换。

4.1 静态算法

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

4.1.1 static-rr:基于权重的轮询调度

  • 不支持运行时利用socat进行权重的动态调整(只支持0和1,不支持其它值)
  • 不支持端服务器慢启动
  • 其后端主机数量没有限制,相当于LVS中的 wrr
慢启动是指在服务器刚刚启动上不会把他所应该承担的访问压力全部给它,而是先给一部分,当没问题后在给一部分

4.1.1.1 示例:

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

frontend webcluster
    bind *:80
    mode http
    use_backend webcluster-host

backend webcluster-host
    balance static-rr
    server web1 192.168.10.10:80 check inter 2 fall 3 rise 5 
    server web2 192.168.10.20:80 check inter 2 fall 3 rise 5 
[root@haproxy ~]# systemctl restart haproxy.service 
[root@haproxy ~]# 

[root@haproxy ~]# for i in {1..10}; do  curl 192.168.10.140; done #10次测试结果
node1 192.168.10.10
node1 192.168.10.10
server2 - 192.168.10.20
server2 - 192.168.10.20
node1 192.168.10.10
node1 192.168.10.10
server2 - 192.168.10.20
server2 - 192.168.10.20
node1 192.168.10.10
node1 192.168.10.10

4.1.2 first

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

4.1.2.1 示例:

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

frontend webcluster
    bind *:80
    mode http
    use_backend webcluster-host

backend webcluster-host
    balance first
    server web1 192.168.10.10:80 check inter 2 fall 3 rise 5
    server web2 192.168.10.20:80 check inter 2 fall 3 rise 5

[root@haproxy ~]# systemctl restart haproxy.service 
[root@haproxy ~]# 

#在两台主机上分别执行此循环,可以观察是否102被调度到
[root@node1 html]# while true;do curl 192.168.10.140 ; sleep 0.1;done
[root@node2 ~]# while true;do curl 192.168.10.140 ; sleep 0.1;done

4.2 动态算法

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

4.2.1 roundrobin

1. 基于权重的轮询动态调度算法,
2. 支持权重的运行时调整,不同于lvs中的rr轮训模式,
3. HAProxy中的roundrobin支持慢启动(新加的服务器会逐渐增加转发数),
4. 其每个后端backend中最多支持4095个real server,
5. 支持对real server权重动态调整,
6. roundrobin为默认调度算法,此算法使用广泛

4.2.1.1 示例:

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

frontend webcluster
    bind *:80
    mode http
    use_backend webcluster-host

backend webcluster-host
    balance roundrobin
    server web1 192.168.10.10:80 check inter 2 fall 3 rise 5
    server web2 192.168.10.20:80 check inter 2 fall 3 rise 5

[root@haproxy ~]# systemctl restart haproxy.service 
[root@haproxy ~]# 

#动态调整权重

[root@haproxy ~]# echo "set weight webcluster-host/web2 2" | socat stdio /var/lib/haproxy/stats1

[root@haproxy ~]# for i in {1..10}; do  curl 192.168.10.140; done
server2 - 192.168.10.20
server2 - 192.168.10.20
node1 192.168.10.10
node1 192.168.10.10
server2 - 192.168.10.20
server2 - 192.168.10.20
node1 192.168.10.10
server2 - 192.168.10.20
server2 - 192.168.10.20
node1 192.168.10.10

4.2.2 leastconn

  • leastconn加权的最少连接的动态
  • 支持权重的运行时调整和慢启动,即:根据当前连接最少的后端服务器而非权重进行优先调度(新客户端连接)
  • 比较适合长连接的场景使用,比如:MySQL等场景。

4.2.2.1 示例:

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

frontend webcluster
    bind *:80
    mode http
    use_backend webcluster-host

backend webcluster-host
    balance leastconn
    server web1 192.168.10.10:80 check inter 2 fall 3 rise 5
    server web2 192.168.10.20:80 check inter 2 fall 3 rise 5

[root@haproxy ~]# systemctl restart haproxy.service 
[root@haproxy ~]# 

[root@haproxy ~]# for i in {1..10}; do  curl 192.168.10.140; done
node1 192.168.10.10
node1 192.168.10.10
server2 - 192.168.10.20
server2 - 192.168.10.20
node1 192.168.10.10
node1 192.168.10.10
server2 - 192.168.10.20
server2 - 192.168.10.20
node1 192.168.10.10
node1 192.168.10.10

4.3 其他算法

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

4.3.1 source

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

4.3.1.1 示例:

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

frontend webcluster
    bind *:80
    mode http
    use_backend webcluster-host

backend webcluster-host
    balance source
    server web1 192.168.10.10:80 check inter 2 fall 3 rise 5
    server web2 192.168.10.20:80 check inter 2 fall 3 rise 5

[root@haproxy ~]# systemctl restart haproxy.service 
[root@haproxy ~]# 
[root@haproxy ~]# for i in {1..10}; do  curl 192.168.10.140; done
node1 192.168.10.10
node1 192.168.10.10
node1 192.168.10.10
node1 192.168.10.10
node1 192.168.10.10
node1 192.168.10.10
node1 192.168.10.10
node1 192.168.10.10
node1 192.168.10.10
node1 192.168.10.10

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

4.3.1.2 map-base 取模法

map-based:取模法,对source地址进行hash计算,再基于服务器总权重的取模,最终结果决定将此请求转发至对应的后端服务器。
此方法是静态的,即不支持在线调整权重,不支持慢启动,可实现对后端服务器均衡调度
缺点是当服务器的总权重发生变化时,即有服务器上线或下线,都会因总权重发生变化而导致调度结果整体改变
hash-type 指定的默值为此算法
所谓取模运算,就是计算两个数相除之后的余数,10%7=3, 7%4=3
map-based算法:基于权重取模,hash(source_ip)%所有后端服务器相加的总权重
比如当源hash值时1111,1112,1113,三台服务器a b c的权重均为1,
即abc的调度标签分别会被设定为 0 1 2(1111%3=1,1112%3=2,1113%3=0)
1111 ----- > nodeb
1112 ------> nodec
1113 ------> nodea
如果a下线后,权重数量发生变化
1111%2=1,1112%2=0,1113%2=1
1112和1113被调度到的主机都发生变化,这样会导致会话丢失

4.3.1.3 取模法配置示例:

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

frontend webcluster
    bind *:80
    mode http
    use_backend webcluster-host

backend webcluster-host
    balance source
    server web1 192.168.10.10:80 check inter 2 fall 3 rise 5
    server web2 192.168.10.20:80 check inter 2 fall 3 rise 5

[root@haproxy ~]# systemctl restart haproxy.service 
[root@haproxy ~]# 

#不支持动态调整权重值

[root@haproxy ~]# echo "set weight webcluster-host/web2 2" | socat stdio /var/lib/haproxy/stats1
Backend is using a static LB algorithm and only accepts weights '0%' and '100%'.
#只能动态上线和下线

[root@haproxy ~]# echo "set weight webcluster-host/web2 0" | socat stdio /var/lib/haproxy/stats1

[root@haproxy ~]# echo "get weight webcluster-host/web2" | socat stdio /var/lib/haproxy/stats1
0 (initial 1)

4.3.1.4 一致性hash

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

4.3.1.4.1 算法:

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

8125643794ad4278ae67aa1d2fe62d16.png

4.3.1.4.2 hash环偏斜问题

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

4.3.1.4.3 hash对象

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

5d7e3e95e388478b9ad33a93c4c4f7ef.png

4.3.1.4.4 一致性hash示意图

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

fc395cacdc3f4765affeccffc15b4527.png

4.3.1.4.5 一致性hash配置示例

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

frontend webcluster
    bind *:80
    mode http
    use_backend webcluster-host

backend webcluster-host
    balance source
    hash-type consistent
    server web1 192.168.10.10:80 check inter 2 fall 3 rise 5
    server web2 192.168.10.20:80 check inter 2 fall 3 rise 5
[root@haproxy ~]# systemctl restart haproxy.service 
[root@haproxy ~]# 

4.3.2 uri

基于对用户请求的URI的左半部分或整个uri做hash,再将hash结果对总权重进行取模后
根据最终结果将请求转发到后端指定服务器
适用于后端是缓存服务器场景
默认是静态算法,也可以通过hash-type指定map-based和consistent,来定义使用取模法还是一致性hash
注意:此算法基于应用层,所以只支持 mode http ,不支持 mode tcp
<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>
左半部分:/<path>;<params>
整个uri:/<path>;<params>?<query>#<frag>

50895e1f08fc42b7b8561ac1def88261.png

4.3.2.1 uri 取模法配置示例

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

frontend webcluster
    bind *:80
    mode http
    use_backend webcluster-host

backend webcluster-host
    balance uri
    server web1 192.168.10.10:80 check inter 2 fall 3 rise 5
    server web2 192.168.10.20:80 check inter 2 fall 3 rise 5
    #server web_sorry 192.168.10.140:8080 backup
[root@haproxy ~]# systemctl restart haproxy.service 
[root@haproxy ~]# 

4.3.2.2 uri 一致性hash配置示例

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

frontend webcluster
    bind *:80
    mode http
    use_backend webcluster-host

backend webcluster-host
    balance uri

    hash-type consistent
    server web1 192.168.10.10:80 check inter 2 fall 3 rise 5
    server web2 192.168.10.20:80 check inter 2 fall 3 rise 5
    #server web_sorry 192.168.10.140:8080 backup
[root@haproxy ~]# systemctl restart haproxy.service 
[root@haproxy ~]# 

4.3.2.3 访问测试

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

[root@node1 html]# echo 192.168.10.10 - index1.html > /var/www/html/index1.html
[root@node1 html]# echo 192.168.10.10 - index2.html > /var/www/html/index2.html
[root@node1 html]# echo 192.168.10.10 - index3.html > /var/www/html/index3.html
[root@node2 html]# echo 192.168.10.20 - index1.html > /usr/share/nginx/html/index1.html

[root@node2 html]# echo 192.168.10.20 - index2.html > /usr/share/nginx/html/index2.html

[root@node2 html]# echo 192.168.10.20 - index3.html > /usr/share/nginx/html/index3.html

#测试访问

[root@haproxy ~]# curl 192.168.10.140/index.html
server2 - 192.168.10.20
[root@haproxy ~]# curl 192.168.10.140/index1.html
192.168.10.10 - index1.html
[root@haproxy ~]# curl 192.168.10.140/index2.html
192.168.10.20 - index2.html
[root@haproxy ~]# curl 192.168.10.140/index3.html
192.168.10.10 - index3.html

4.3.3 url_param

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

4.3.3.1 url_param取模法配置示例

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

frontend webcluster
    bind *:80
    mode http
    use_backend webcluster-host

backend webcluster-host
    balance url_param name,userid
    server web1 192.168.10.10:80 check inter 2 fall 3 rise 5
    server web2 192.168.10.20:80 check inter 2 fall 3 rise 5

[root@haproxy ~]# systemctl restart haproxy.service 
[root@haproxy ~]# 

4.3.3.2 url_param一致性hash配置示例

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

frontend webcluster
    bind *:80
    mode http
    use_backend webcluster-host

backend webcluster-host
    balance url_param name,userid

    hash-type consistent
    server web1 192.168.10.10:80 check inter 2 fall 3 rise 5
    server web2 192.168.10.20:80 check inter 2 fall 3 rise 5

[root@haproxy ~]# systemctl restart haproxy.service 
[root@haproxy ~]# 

4.3.3.3 测试访问

[root@haproxy ~]# curl 192.168.10.140/index2.html?name=lee
192.168.10.20 - index2.html
[root@haproxy ~]# curl 192.168.10.140/index2.html?name=le
192.168.10.10 - index2.html
[root@haproxy ~]# curl 192.168.10.140/index2.html?name=xixi
192.168.10.20 - index2.html
[root@haproxy ~]# curl 192.168.10.140/index2.html?name=haha
192.168.10.10 - index2.html

4.3.4 hdr

  • 针对用户每个http头部(header)请求中的指定信息做hash,
  • 此处由 name 指定的http首部将会被取出并做hash计算,
  • 然后由服务器总权重取模以后派发至某挑出的服务器,如果无有效值,则会使用默认的轮询调度。

4.3.4.1 hdr取模法配置示例

[root@haproxy ~]# systemctl restart haproxy.service 

frontend webcluster
    bind *:80
    mode http
    use_backend webcluster-host

backend webcluster-host
    balance hdr(User-Agent)
    server web1 192.168.10.10:80 check inter 2 fall 3 rise 5
    server web2 192.168.10.20:80 check inter 2 fall 3 rise 5

[root@haproxy ~]# systemctl restart haproxy.service 
[root@haproxy ~]# 

4.3.4.2 一致性hash配置示例

[root@haproxy ~]# systemctl restart haproxy.service 

frontend webcluster
    bind *:80
    mode http
    use_backend webcluster-host

backend webcluster-host
    balance hdr(User-Agent)

    hash-type consistent
    server web1 192.168.10.10:80 check inter 2 fall 3 rise 5
    server web2 192.168.10.20:80 check inter 2 fall 3 rise 5

[root@haproxy ~]# systemctl restart haproxy.service 
[root@haproxy ~]# 

4.3.4.3 测试访问

[root@haproxy ~]# curl -v 192.168.10.140
[root@haproxy ~]# curl -vA 'sougou' 192.168.10.140

[root@haproxy ~]# curl -A 'sougou' 192.168.10.140
server2 - 192.168.10.20
[root@haproxy ~]# curl -A 'xixi' 192.168.10.140
server2 - 192.168.10.20
[root@haproxy ~]# curl -A '456' 192.168.10.140
node1 192.168.10.10
[root@haproxy ~]# 

4.3.5 算法总结

#静态
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

4.3.6 各算法使用场景

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

五、高级功能及配置

介绍HAProxy高级配置及实用案例

5.1 基于cookie的会话保持

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

5.1.1 配置选项

cookie name [ rewrite | insert | prefix ][ indirect ] [ nocache ][ postonly ] [
preserve ][ httponly ] [ secure ][ domain ]* [ maxidle <idle> ][ maxlife ]
name: #cookie 的 key名称,用于实现持久连接
insert: #插入新的cookie,默认不插入cookie
indirect: #如果客户端已经有cookie,则不会再发送cookie信息
nocache:         #当client和hapoxy之间有缓存服务器(如:CDN)时,不允许中间缓存器缓存cookie,
                        #因为这会导致很多经过同一个CDN的请求都发送到同一台后端服务器

5.1.2 配置示例

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

frontend webcluster
    bind *:80
    mode http
    use_backend webcluster-host

backend webcluster-host
    balance roundrobin
    cookie xixi insert nocache indirect
    server web1 192.168.10.10:80 cookie lee check inter 2 fall 3 rise 5
    server web2 192.168.10.20:80 cookie lee2 check inter 2 fall 3 rise 5

[root@haproxy ~]# systemctl restart haproxy.service 
[root@haproxy ~]# 

5.1.3 验证cookie信息

2c7c9c4ac028462fa2a7f9fab6199087.png通过命令行验证:

[root@haproxy ~]# curl -i 192.168.10.140
HTTP/1.1 200 OK
server: nginx/1.20.1
date: Sun, 11 Aug 2024 13:01:45 GMT
content-type: text/html
content-length: 24
last-modified: Wed, 07 Aug 2024 08:01:38 GMT
etag: "66b329e2-18"
accept-ranges: bytes
set-cookie: xixi=lee2; path=/
cache-control: private

server2 - 192.168.10.20


[root@haproxy ~]# curl -i 192.168.10.140
HTTP/1.1 200 OK
date: Sun, 11 Aug 2024 13:01:48 GMT
server: Apache/2.4.53 (Red Hat Enterprise Linux)
last-modified: Sat, 10 Aug 2024 03:53:37 GMT
etag: "14-61f4c346337a9"
accept-ranges: bytes
content-length: 20
content-type: text/html; charset=UTF-8
set-cookie: xixi=lee; path=/
cache-control: private

node1 192.168.10.10


#curl访问时指定cookie

[root@haproxy ~]# curl -b xixi=lee 192.168.10.140
node1 192.168.10.10
[root@haproxy ~]# curl -b xixi=lee2 192.168.10.140
server2 - 192.168.10.20
 

[root@haproxy ~]# curl -vb xixi=lee2 192.168.10.140
*   Trying 192.168.10.140:80...
* Connected to 192.168.10.140 (192.168.10.140) port 80 (#0)
> GET / HTTP/1.1
> Host: 192.168.10.140
> User-Agent: curl/7.76.1
> Accept: */*
> Cookie: xixi=lee2

* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< server: nginx/1.20.1
< date: Sun, 11 Aug 2024 13:05:14 GMT
< content-type: text/html
< content-length: 24
< last-modified: Wed, 07 Aug 2024 08:01:38 GMT
< etag: "66b329e2-18"
< accept-ranges: bytes

server2 - 192.168.10.20
* Connection #0 to host 192.168.10.140 left intact


[root@haproxy ~]# curl -vb xixi=lee 192.168.10.140
*   Trying 192.168.10.140:80...
* Connected to 192.168.10.140 (192.168.10.140) port 80 (#0)
> GET / HTTP/1.1
> Host: 192.168.10.140
> User-Agent: curl/7.76.1
> Accept: */*
> Cookie: xixi=lee

* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< date: Sun, 11 Aug 2024 13:05:19 GMT
< server: Apache/2.4.53 (Red Hat Enterprise Linux)
< last-modified: Sat, 10 Aug 2024 03:53:37 GMT
< etag: "14-61f4c346337a9"
< accept-ranges: bytes
< content-length: 20
< content-type: text/html; charset=UTF-8

node1 192.168.10.10
* Connection #0 to host 192.168.10.140 left intact

5.2 HAProxy状态页

通过web界面,显示当前HAProxy的运行状态

5.2.1 状态页配置项

stats enable         #基于默认的参数启用stats page
stats hide-version         #将状态页中haproxy版本隐藏
stats refresh <delay>         #设定自动刷新时间间隔,默认不自动刷新
stats uri <prefix>         #自定义stats page uri,默认值:/haproxy?stats
stats auth <user>:<passwd>         #认证时的账号和密码,可定义多个用户,每行指定一个用户
                                                #默认:no authentication
stats admin { if | unless } <cond>         #启用stats page中的管理功能

5.2.2 启用状态页

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

listen stats
    mode http
    bind *:7777
    stats enable
    stats refresh 3
    stats uri /status                        #自定义stats page uri
    stats auth root:root                   #认证,此行可以出现多次      

[root@haproxy html]# systemctl restart haproxy.service 
[root@haproxy html]# 

测试:

浏览器访问: 192.168.10.140:7777/status

5.2.3 登录状态页

bd8605280cc24231beb0987582e8a2ff.png

#pid为当前pid号,process为当前进程号,nbproc和nbthread为一共多少进程和每个进程多少个线程
pid = 27134 (process #1, nbproc = 1, nbthread = 1)
#启动了多长时间
uptime = 0d 0h00m04s
#系统资源限制:内存/最大打开文件数/
system limits: memmax = unlimited; ulimit-n = 200029
#最大socket连接数/单进程最大连接数/最大管道数maxpipes
maxsock = 200029; maxconn = 100000; maxpipes = 0
#当前连接数/当前管道数/当前连接速率
current conns = 2; current pipes = 0/0; conn rate = 2/sec; bit rate = 0.000 kbps
#运行的任务/当前空闲率
Running tasks: 1/14; idle = 100 %
active UP: #在线服务器
backup UP: #标记为backup的服务器
active UP, going down: #监测未通过正在进入down过程
backup UP, going down: #备份服务器正在进入down过程
active DOWN, going up: #down的服务器正在进入up过程
backup DOWN, going up: #备份服务器正在进入up过程
active or backup DOWN: #在线的服务器或者是backup的服务器已经转换成了down状态
not checked: #标记为不监测的服务器
#active或者backup服务器人为下线的
active or backup DOWN for maintenance (MAINT)
#active或者backup被人为软下线(人为将weight改成0)
active or backup SOFT STOPPED for maintenance

5.2.4 backend server信息

session rate(每秒的连接会话信息):
Errors(错误统计信息):
cur:每秒的当前会话数量 :
Req:错误请求量
max:每秒新的最大会话数量
conn:错误链接量
limit:每秒新的会话限制量
Resp:错误响应量
sessions(会话信息):
Warnings(警告统计信息):
cur:当前会话量
Retr:重新尝试次数
max:最大会话量
Redis:再次发送次数
limit: 限制会话量
Total:总共会话量
Server(real server信息):
LBTot:选中一台服务器所用的总时间
Status:后端机的状态,包括UP和DOWN
Last:和服务器的持续连接时间
LastChk:持续检查后端服务器的时间
Wght:权重
Bytes(流量统计):
Act:活动链接数量
In:网络的字节输入总量
Bck:备份的服务器数量
Out:网络的字节输出总量
Chk:心跳检测时间
Dwn:后端服务器连接后都是DOWN的数量
Denied(拒绝统计信息):
Dwntme:总的downtime时间
Req:拒绝请求量
Thrtle:server 状态
Resp:拒绝回复量
####

5.3 IP透传

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

5.3.1 四层IP透传

#未开启透传的四层代理

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

frontend webcluster
    bind *:80
    mode tcp
    use_backend webcluster-host

backend webcluster-host
    balance roundrobin
    server web1 192.168.10.10:80 check  inter 2 fall 3 rise 5
    server web2 192.168.10.20:80 check  inter 2 fall 3 rise 5
[root@haproxy ~]# systemctl restart haproxy.service 
[root@haproxy ~]# 


#正常的nginx配置

[root@node2 html]# 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;
#在访问haproxy后查看nginx日志

[root@node2 html]# tail -n3 /var/log/nginx/access.log
192.168.10.140 - - [11/Aug/2024:21:26:21 +0800] "GET / HTTP/1.1" 200 24 "-" "curl/7.76.1" "-"
192.168.10.140 - - [11/Aug/2024:21:26:23 +0800] "GET / HTTP/1.1" 200 24 "-" "curl/7.76.1" "-"
192.168.10.140 - - [11/Aug/2024:21:26:24 +0800] "GET / HTTP/1.1" 200 24 "-" "curl/7.76.1" "-"
在此日志中是无法看到真实访问源地址的

5.3.2 开启四层透传

#nginx 配置:在访问日志中通过变量$proxy_protocol_addr 记录透传过来的客户端IP

[root@node2 html]# 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 {
        listen       80 proxy_protocol;
        listen       [::]:80;
        server_name  _;
        root         /usr/share/nginx/html;

[root@node2 html]# systemctl restart nginx.service 

#修改haproxy

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

frontend webcluster
    bind *:80
    mode tcp
    use_backend webcluster-host

backend webcluster-host
    balance roundrobin
    server web1 192.168.10.10:80 check  inter 2 fall 3 rise 5
    server web2 192.168.10.20:80 send-proxy check  inter 2 fall 3 rise 5
[root@haproxy ~]# systemctl restart haproxy.service 
[root@haproxy ~]# 

#访问后查看日志内容
[root@node2 html]# tail -n3 /var/log/nginx/access.log
192.168.10.140 - - [11/Aug/2024:21:34:22 +0800] "GET / HTTP/1.1"  "192.168.10.140"200 24 "-" "curl/7.76.1" "192.168.10.140"
192.168.10.140 - - [11/Aug/2024:21:34:23 +0800] "GET / HTTP/1.1"  "192.168.10.140"200 24 "-" "curl/7.76.1" "192.168.10.140"
192.168.10.140 - - [11/Aug/2024:21:34:24 +0800] "GET / HTTP/1.1"  "192.168.10.140"200 24 "-" "curl/7.76.1" "192.168.10.140"

5.3.3 七层IP透传

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

5.3.3.1 HAProxy配置

在由haproxy发往后端主机的请求报文中添加“X-Forwarded-For"首部,其值为前端客户端的地址;用于向后端主发送真实的客户端IP
option forwardfor [ except <network> ] [ header <name> ] [ if-none ]
[ except <network> ]:请求报请来自此处指定的网络时不予添加此首部,如haproxy自身所在网络
[ header <name> ]: 使用自定义的首部名称,而非“X-Forwarded-For",示例:X-client
[ if-none ] 如果没有首部才添加首部,如果有使用默认值

示例:

#修改haproxy

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

frontend webcluster
    bind *:80
    mode http
    use_backend webcluster-host

backend webcluster-host
    balance roundrobin
    server web1 192.168.10.10:80 check  inter 2 fall 3 rise 5
    server web2 192.168.10.20:80 send-proxy check  inter 2 fall 3 rise 5

[root@haproxy ~]# systemctl restart haproxy.service 
[root@haproxy ~]# 
 

5.3.3.2 web服务器日志格式配置

配置web服务器,记录负载均衡透传的客户端IP地址

#apache 配置:
[root@node1 html]# vim /etc/httpd/conf/httpd.conf
 LogFormat "%{X-Forwarded-For}i %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
[root@node1 html]# systemctl restart httpd.service 
[root@node1 html]# 

#nginx 日志格式:
$proxy_add_x_forwarded_for: 包括客户端IP和中间经过的所有代理的IP
$http_x_forwarded_For: 只有客户端IP
log_format main '"$proxy_add_x_forwarded_for" - $remote_user [$time_local]
"$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" $http_x_forwarded_For';
#查看日志如下:
[root@node1 html]# tail -n1 /etc/httpd/logs/access_log 
192.168.10.140 192.168.10.140 - - [11/Aug/2024:21:43:27 +0800] "GET / HTTP/1.1" 200 20 "-" "curl/7.76.1"
[root@node2 html]# tail -n1 /var/log/nginx/access.log
192.168.10.140 - - [11/Aug/2024:21:43:26 +0800] "GET / HTTP/1.1"  "192.168.10.140"200 24 "-" "curl/7.76.1" "192.168.10.140"

5.4 ACL

访问控制列表ACL,Access Control Lists)
是一种基于包过滤的访问控制技术
它可以根据设定的条件对经过服务器传输的数据包进行过滤(条件匹配)即对接收到的报文进行匹配和过滤,基于请求报文头部中的源地址、源端口、目标地址、目标端口、请求方法、URL、文件后缀等信息内容进行匹配并执行进一步操作,比如允许其通过或丢弃。
#示例
 frontend test_acl
        bind *:80
        mode http
        #acl bad_browers hdr_beg(User-Agent) -i curl
        #http-request deny if bad_browers
        #acl test hdr_dom(host) -i www.timinglee.org
        #acl test hdr_end(host) -i .org
        #acl test base_sub -m sub org
        #acl test path_sub -m sub /a
        #acl test path_end -m sub /a
        #acl test path_reg -i ^/t
        acl test url_sub -m sub lee
        acl test path_dir -m sub a
        use_backend test_web if test
        default_backend default_webserver
 backend default_webserver
        mode http
        server web1 172.25.254.20:80 check inter 3 fall 3 rise 5
 backend test_web
        mode http
        server web2 172.25.254.30:80 check inter 3 fall 3 rise 5

5.4.1 ACL配置选项

#用acl来定义或声明一个acl
acl <aclname> <criterion> [flags] [operator] [<value>]
acl 名称 匹配规范 匹配模式 具体操作符 操作对象类型

5.4.1.1 ACL-Name 名称

acl test path_end -m sub /a
#ACL名称,可以使用大字母A-Z、小写字母a-z、数字0-9、冒号:、点.、中横线和下划线,并且严格区分大
小写,比如:my_acl和My_Acl就是两个完全不同的acl5.8.1.2 ACL-criterion

5.4.1.2 ACL-criterion 匹配规范

定义ACL匹配规范,即:判断条件

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也会匹配
#示例:
hdr(<string>) 用于测试请求头部首部指定内容
hdr_dom(host) 请求的host名称,如 www.timinglee.org
hdr_beg(host) 请求的host开头,如 www. img. video. download. ftp.
hdr_end(host) 请求的host结尾,如 .com .net .cn
#示例:
acl bad_agent hdr_sub(User-Agent) -i curl wget
http-request deny if bad_agent
#有些功能是类似的,比如以下几个都是匹配用户请求报文中host的开头是不是www
acl short_form hdr_beg(host) www.
acl alternate1 hdr_beg(host) -m beg www.
acl alternate2 hdr_dom(host) -m beg www.
acl alternate3 hdr(host) -m beg www.
base : string
#返回第一个主机头和请求的路径部分的连接,该请求从主机名开始,并在问号之前结束,对虚拟主机有用
<scheme>://<user>:<password>@#<host>:<port>/<path>;<params>#?<query>#<frag>
base : exact string match
base_beg : prefix match
base_dir : subdir match
base_dom : domain match
base_end : suffix match
base_len : length match
base_reg : regex match
base_sub : substring match
path : string
#提取请求的URL路径,该路径从第一个斜杠开始,并在问号之前结束(无主机部分)
<scheme>://<user>:<password>@<host>:<port>#/<path>;<params>#?<query>#<frag>
path : exact string match
path_beg : prefix match #请求的URL开头,如/static、/images、/img、/css
path_end : suffix match #请求的URL中资源的结尾,如 .gif .png .css .js .jpg .jpeg
path_dom : domain match
path_dir : subdir match
path_len : length match
path_reg : regex match
path_sub : substring match
#示例:
path_beg -i /haproxy-status/
path_end .jpg .jpeg .png .gif
path_reg ^/images.*\.jpeg$
path_sub image
path_dir jpegs
path_dom timinglee
url : string
#提取请求中的整个URL。
url :exact string match
url_beg : prefix match
url_dir : subdir match
url_dom : domain match
url_end : suffix match
url_len : length match
url_reg : regex match
url_sub : substring match
dst #目标IP
dst_port #目标PORT
src #源IP
src_port #源PORT
#示例:
acl invalid_src src 10.0.0.7 192.168.1.0/24
acl invalid_src src 172.16.0.0/24
acl invalid_port src_port 0:1023
status : integer #返回在响应报文中的状态码
#七层协议
acl valid_method method GET HEAD
http-request deny if ! valid_method

5.4.1.3 ACL-flags 匹配模式

ACL匹配模式

-i 不区分大小写
-m 使用指定的正则表达式匹配方法
-n 不做DNS解析
-u 禁止acl重名,否则多个同名ACL匹配或关系

5.4.1.4 ACL-operator 具体操作符

ACL 操作符

整数比较:eq、ge、gt、le、lt
字符比较:
- exact match (-m str) :字符串必须完全匹配模式
- substring match (-m sub) :在提取的字符串中查找模式,如果其中任何一个被发现,ACL将匹配
- prefix match (-m beg) :在提取的字符串首部中查找模式,如果其中任何一个被发现,ACL将匹配
- suffix match (-m end) :将模式与提取字符串的尾部进行比较,如果其中任何一个匹配,则ACL进行
匹配
- subdir match (-m dir) :查看提取出来的用斜线分隔(“/")的字符串,如其中任一个匹配,则ACL
进行匹配
- domain match (-m dom) :查找提取的用点(“.")分隔字符串,如果其中任何一个匹配,则ACL进行
匹配

5.4.1.5 ACL-value 操作对象

value的类型
The ACL engine can match these types against patterns of the following types :
- Boolean #布尔值
- integer or integer range #整数或整数范围,比如用于匹配端口范围
- IP address / network #IP地址或IP范围, 192.168.0.1 ,192.168.0.1/24
- string--> www.timinglee.org
exact #精确比较
substring #子串
suffix #后缀比较
prefix #前缀比较
subdir #路径, /wp-includes/js/jquery/jquery.js
domain #域名,www.timinglee.org
- regular expression #正则表达式
- hex block #16进制

5.4.2 多个ACL的组合调用方式

多个ACL的逻辑处理
与:隐式(默认)使用
或:使用“or" 或 “||"表示
否定:使用 "!" 表示
多个ACL调用方式:
#示例:
if valid_src valid_port #与关系,ACL中A和B都要满足为true,默认为与
if invalid_src || invalid_port #或,ACL中A或者B满足一个为true
if ! invalid_src #非,取反,不满足ACL才为true

5.4.3 ACL示例-域名匹配

backend webcluster-host
    bind *:80
    mode http
    acl test hdr_dom(host) -i www.xixi.com

   ############################################

    use_backend webcluster-host if test
    default_backend default-host

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

backend default-host
    mode http
    server web2 192.168.10.20:80 check inter 2 fall 2 rise 5
[root@haproxy ~]# systemctl restart haproxy.service 
[root@haproxy ~]# 

测试结果:

#在本地所在主机中做地址解析

路径:C:\Windows\System32\drivers\etc\hosts

192.168.10.140 www.xixi.com

#测试结果

[D:\~]$ curl www.xixi.com
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:--100    20  100    20    0     0   2331      0 --:--:-- --:--:-- --:--:--  4000
node1 192.168.10.10

[D:\~]$ curl 192.168.10.140
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:--100    24  100    24    0     0  10582      0 --:--:-- --:--:-- --:--:-- 12000
server2 - 192.168.10.20

5.4.4 ACL示例-基于源IP或子网调度访问

将指定的源地址调度至指定的web服务器组。
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg 

frontend webcluster
    bind *:80
    mode http
    acl ctrl_ip src 192.168.10.1 192.168.10.10 172.25.0.0/24

   ############################################
    use_backend webcluster-host if ctrl_ip
    default_backend default-host

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

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

[root@haproxy ~]# systemctl restart haproxy.service 
[root@haproxy ~]# 
测试结果
[root@haproxy ~]# curl 192.168.10.140
server2 - 192.168.10.20
[root@haproxy ~]# curl 192.168.10.140
server2 - 192.168.10.20

5.4.5 ACL示例-基于源地址的访问控制

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

[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg 
frontend webcluster
    bind *:80
    mode http
    acl test hdr_dom(host) -i www.xixi.com
    acl ctrl_ip src 192.168.10.1 192.168.10.10 172.25.0.0/24

   ############################################
    http-request deny if test  
    default_backend default-host

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

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

[root@haproxy ~]# systemctl restart haproxy.service 
[root@haproxy ~]# 

测试:

[D:\~]$ curl www.xixi.com
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:--100    93  100    93    0     0   7513      0 --:--:-- --:--:-- --:--:-- 10333
<html><body><h1>403 Forbidden</h1>
                                  Request forbidden by administrative rules.
             </body></html>

[D:\~]$ curl 192.168.10.140
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:--100    24  100    24    0     0   9489      0 --:--:-- --:--:-- --:--:-- 12000
server2 - 192.168.10.20

5.4.6 ACL示例-匹配浏览器类型

匹配客户端浏览器,将不同类型的浏览器调动至不同的服务器组、
范例: 拒绝curl和wget的访问
示例:

[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg 
frontend webcluster
    bind *:80
    mode http
    acl badweb hdr_sub(User-Agent) -i curl wget  

   ############################################   
    http-request deny if badweb
    default_backend default-host

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

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

[root@haproxy ~]# systemctl restart haproxy.service 
[root@haproxy ~]# 

测试:

[root@haproxy ~]# curl 192.168.10.140
<html><body><h1>403 Forbidden</h1>
Request forbidden by administrative rules.
</body></html>

[root@haproxy ~]# wget 192.168.10.140/index.html
--2024-08-11 22:54:30--  http://192.168.10.140/index.html
Connecting to 192.168.10.140:80... connected.
HTTP request sent, awaiting response... 403 Forbidden
2024-08-11 22:54:30 ERROR 403: Forbidden.

5.4.7 ACL示例-基于文件后缀名实现动静分离

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

frontend webcluster
    bind *:80
    mode http
    acl badweb hdr_sub(User-Agent) -i curl wget
    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.10.10:80 check inter 2 fall 2 rise 5

backend default-host
    mode http
    server web2 192.168.10.20:80 check inter 2 fall 2 rise 5
[root@haproxy ~]# systemctl restart haproxy.service 
[root@haproxy ~]# 

[root@node1 html]# vim /var/www/html/index.php 
<?php
    phpinfo();
?>
 

测试:

1cbca9ebcef04f33ac56818183ee11d8.png

bdbd01a9e04244c5bfcae175ce8d18e0.png

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

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

frontend webcluster
    bind *:80
    mode http
   acl test path_sub -m sub lee

   ############################################

    use_backend webcluster-host if test
    #use_backend webcluster-host if ! test        #不是以test为名
    #use_backend webcluster-host if test domain    #必须两个条件都满足    
    #use_backend webcluster-host if test ||  domain   #满足其中一个条件
    default_backend default-host

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

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

[root@haproxy ~]# systemctl restart haproxy.service 
[root@haproxy ~]# 

#创建相关文件
[root@node1 ~]# mkdir -p /var/www/html/lee/

[root@node1 ~]# echo xixi 192.168.10.10 /var/www/html/lee/index.html

[root@node2 ~]# mkdir -p /usr/share/nginx/html/lee/
[root@node2 ~]# echo haha 192.168.10.20 > /usr/share/nginx/html/lee/index.html

[root@node2 static]# mkdir -p /usr/share/nginx/html/static/

[root@node2 static]# echo static 192.168.10.20 //usr/share/nginx/html/static/index.html

测试

[root@haproxy ~]# curl 192.168.10.140/lee/
xixi 192.168.10.10
[root@haproxy ~]# curl 192.168.10.140/static/
static 192.168.10.20

5.5 自定义HAProxy 错误界面

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

[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

5.5.1 基于自定义的错误页面文件

#自定义错误页
errorfile <code> <file>
<code> #HTTP status code.支持200, 400, 403, 405, 408, 425, 429, 500, 502,503,504
<file> #包含完整HTTP响应头的错误页文件的绝对路径。 建议后缀".http",以和一般的html文件相区分
#示例:
errorfile 503 /haproxy/errorpages/503page.http

示例:

首先可以先把node1的httpd服务和node2的nginx.service服务停掉

[root@node1 ~]# systemctl stop httpd

[root@node2 static]# systemctl stop nginx.service

[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                 100000
    errorfile 503 /etc/haproxy/errorpage/503.http
[root@haproxy errorpage]# systemctl restart haproxy.service 
[root@haproxy errorpage]# 
[root@haproxy ~]# mkdir -p /etc/haproxy/errorpage/

[root@haproxy errorpage]# cp /usr/share/haproxy/503.http /etc/haproxy/errorpage/

[root@haproxy ~]# cd /etc/haproxy/errorpage/
[root@haproxy errorpage]# vim 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>
!!!!那就访问<a href="http://www.baidu.com">www.baidu.com</a>,你所想要的答案都能搜到!!!!
</body></html>

测试:

在浏览器上测试去访问192.168.10.140

3d78149c31774c299b0d8695861906ed.png

5.5.2 基于http重定向错误页面

#错误页面重定向
errorloc <code> <url>
#相当于errorloc302 <code> <url>,利用302重定向至指URL
#示例:
errorloc 503 https://www.baidu.com
范例:
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg 
  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                 100000
    #errorfile 503 /etc/haproxy/errorpage/503.http
    errorloc 503 https://www.baidu.com
[root@haproxy ~]# systemctl restart haproxy.service 
[root@haproxy ~]# 

测试:

访问浏览器192.168.10.140 自动跳转到百度

18c230c8bb8646bdb38d27ea6c6a61c4.png

b01cf2f05d5849aaab2ff51d3732bbce.png

5.6 HAProxy 四层负载

针对除HTTP以外的TCP协议应用服务访问的应用场景
MySQL
Redis
Memcache
RabbitMQ
四层负载示例
注意:如果使用frontend和backend,一定在 frontend 和 backend 段中都指定mode tcp
listen mysql-port
bind 10.0.0.7:6379
mode tcp
balance leastconn
server server1 10.0.0.17:3306 check
server server2 10.0.0.27:3306 check backup
范例:对 MySQL 服务实现四层负载
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg 
listen dbserver
    bind *:3306
    mode tcp
    balance static-rr
    server db1 192.168.10.10:3306 check inter 2 fall 2 rise 5
    server db2 192.168.10.20:3306 check inter 2 fall 2 rise 5

#在后端服务器安装和配置mariadb服务
[root@node1 ~]# yum install mariadb-server -y
[root@node2 static]# yum install mariadb-server -y
[root@haproxy ~]# yum install mariadb -y  #安装一个客户端

 
[root@node1 ~]# vim /etc/my.cnf.d/mariadb-server.cnf 
[mysqld]
server-id=1
[root@node2 static]# vim /etc/my.cnf.d/mariadb-server.cnf 
[mysqld]
server-id=2
 
[root@node1 ~]# systemctl restart mariadb.service
[root@node2 static]# systemctl restart mariadb.service
 
[root@node1 ~]#  mysql -e "grant all on *.* to lee@'%' identified by 'lee';"
[root@node2 static]# mysql -e "grant all on *.* to lee@'%' identified by 'lee';"
#测试

[root@haproxy ~]# mysql -ulee -plee -h 192.168.10.140
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 3
Server version: 10.5.16-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.001 sec)

[root@haproxy ~]# mysql -ulee -plee -h 192.168.10.140
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 3
Server version: 10.5.16-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)

5.7 HAProxy https 实现

haproxy可以实现https的证书安全,从用户到haproxy为https,从haproxy到后端服务器用http通信
但基于性能考虑,生产中证书都是在后端服务器比如nginx上实现
#配置HAProxy支持https协议,支持ssl会话;
bind *:443 ssl crt /PATH/TO/SOME_PEM_FILE
#指令 crt 后证书文件为PEM格式,需要同时包含证书和所有私钥
cat demo.key demo.crt > demo.pem
#把80端口的请求重向定443
bind *:80
redirect scheme https if !{ ssl_fc }

5.7.1 证书制作

首先要开启node1的httpd服务和node2的nginx.service服务

[root@node1 ~]# systemctl restart httpd
[root@node1 ~]# 
[root@node2 static]# systemctl start nginx.service 
[root@node2 static]# 
 

[root@haproxy ~]# mkdir /etc/haproxy/certs/

[root@haproxy ~]# openssl req -newkey rsa:2048 -nodes -sha256 -keyout /etc/haproxy/certs/timinglee.org.key -x509 -days 365 -out /etc/haproxy/certs/timinglee.org.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]:CN
State or Province Name (full name) []:Shannxi
Locality Name (eg, city) [Default City]:Xi'an 
Organization Name (eg, company) [Default Company Ltd]:timinglee
Organizational Unit Name (eg, section) []:webserver
Common Name (eg, your name or your server's hostname) []:www.timinglee.org  
Email Address []:admin@timinglee.org
[root@haproxy ~]# 
 

[root@haproxy ~]# ls /etc/haproxy/certs/
timinglee.org.crt  timinglee.org.key

# 指令 crt 后证书文件为PEM格式,需要同时包含证书和所有私钥

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

5.7.2 https配置示例

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

frontend webcluster
    bind *:80
    mode http
    redirect scheme https if !{ ssl_fc }        #全站加密
 

listen web-https
    bind *:443 ssl crt /etc/haproxy/certs/timinglee.pem
    mode http
    balance roundrobin
    server web1 192.168.10.10:80 check inter 2 fall 2 rise 5      

    server web2 192.168.10.20:80 check inter 2 fall 2 rise 5
[root@haproxy ~]# systemctl restart haproxy.service 
[root@haproxy ~]# 

手动访问测试:

84d7df02345d41f6ab3ff92b907bd907.png

自动跳转到https测试:

ee5b6ec08dc7493e848a820b03ea0572.png

f1bc6ecdfbc64d20aa5a455139c64b6a.png

5.8 子配置文件:

好处:使文件更易于阅读

[root@haproxy ~]# vim /lib/systemd/system/haproxy.service 

[Unit]
Description=HAProxy Load Balancer
After=network-online.target
Wants=network-online.target

[Service]
EnvironmentFile=-/etc/sysconfig/haproxy
Environment="CONFIG=/etc/haproxy/haproxy.cfg" "PIDFILE=/run/haproxy.pid" "CFGDIR=/etc/haproxy/conf.d"
ExecStartPre=/usr/sbin/haproxy -f $CONFIG -f $CFGDIR -c -q $OPTIONS
ExecStart=/usr/sbin/haproxy -Ws -f $CONFIG -f $CFGDIR -p $PIDFILE $OPTIONS
ExecReload=/usr/sbin/haproxy -f $CONFIG -f $CFGDIR -c -q $OPTIONS
ExecReload=/bin/kill -USR2 $MAINPID
KillMode=mixed
SuccessExitStatus=143
Type=notify

[Install]
WantedBy=multi-user.target


[root@haproxy ~]# cd /etc/haproxy/conf.d
[root@haproxy conf.d]# 

[root@haproxy conf.d]# vim web.cfg
listen stats
    mode http
    bind *:7777
    stats enable
    stats refresh 3
    stats uri /status
    stats auth root:root
 

[root@haproxy conf.d]# vim /etc/haproxy/haproxy.cfg
#listen stats
    #mode http
    #bind *:7777
    #stats enable
    #stats refresh 3
    #stats uri /status
    #stats auth root:root

[root@haproxy conf.d]# systemctl restart haproxy.service 
Warning: The unit file, source configuration file or drop-ins of haproxy.service changed on disk. Run 'systemctl daemon-reload' to reload units.
[root@haproxy conf.d]# systemctl daemon-reload   #打开 /lib/systemd/system/haproxy.service 文件需要执行systemctl daemon-reload
[root@haproxy conf.d]# systemctl restart haproxy.service 

[root@haproxy conf.d]# 

测试:

d5425cdd05a44b37bc86e42a64846014.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值