haproxy实验

负载均衡简单环境的搭建

主机名IP角色
客户端(cip)192.168.75.100测试机
haproxy192.168.75.30调度器
rs1192.168.75.10服务器
rs2192.168.75.20服务器


 客户端配置:

#关闭防火墙
systemctl disable --now firewalld

rs1、rs2配置

#关闭防火墙
systemctl disable --now firewalld

#安装nginx服务
yum install nginx -y

#更改默认发布页面方便测试
[root@RS1 ~]# cat /usr/share/nginx/html/index.html
RS1 192.168.75.10
[root@RS2 ~]# cat /usr/share/nginx/html/index.html
RS1 192.168.75.20

haproxy配置

#关闭防火墙
systemctl disable --now firewalld

#安装haproxy
yum install haproxy -y

#在配置文件中写入策略

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

# custom web cluster
#--------------------------------------------------------------------
frontend webcluster
        bind    *:80
        mode    http
        balance roundrobin
        use_backend webserver

backend webserver
        server web1 192.168.75.10:80
        server web2 192.168.75.20:80

测试

[root@cip ~]# for hap in {1..10}
> do
> curl 192.168.75.30
> done
RS1 192.168.75.10
RS2 192.168.75.20
RS1 192.168.75.10
RS2 192.168.75.20
RS1 192.168.75.10
RS2 192.168.75.20
RS1 192.168.75.10
RS2 192.168.75.20
RS1 192.168.75.10
RS2 192.168.75.20

 

haproxy基于cookie的会话保持

 

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

注:不支持tcp mode 使用http mode

配置选项

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的请求都发送到同一台后端服务器

配置如下: 

vim /etc/haproxy/haproxy.cfg

listen webserver
        bind    *:80
        mode    http
        balance roundrobin
        cookie webcookie insert nocache indirect
        #balance hdr(User-Agent)
        hash-type consistent
        server web1 192.168.75.10:80 cookie w1 weight 1 check inter 3s fall 3 rise 5
        server web2 192.168.75.20:80 cookie w2 weight 1 check inter 3s fall 3 rise 5

验证cookie信息

 在浏览器中输入vip即可

命令验证

C:\Users\86178>curl -i 192.168.75.30
HTTP/1.1 200 OK
server: nginx/1.20.1
date: Fri, 18 Jul 2025 09:11:38 GMT
content-type: text/html
content-length: 18
last-modified: Thu, 17 Jul 2025 08:02:12 GMT
etag: "6878ae04-12"
accept-ranges: bytes
set-cookie: webcookie=w2; path=/
cache-control: private

RS2 192.168.75.20

C:\Users\86178>curl -i 192.168.75.30
HTTP/1.1 200 OK
server: nginx/1.20.1
date: Fri, 18 Jul 2025 09:12:22 GMT
content-type: text/html
content-length: 18
last-modified: Thu, 17 Jul 2025 08:02:53 GMT
etag: "6878ae2d-12"
accept-ranges: bytes
set-cookie: webcookie=w1; path=/
cache-control: private

RS1 192.168.75.10

#访问时指定cookie
C:\Users\86178>curl -b webcookie=w1 192.168.75.30
RS1 192.168.75.10

C:\Users\86178>curl -b webcookie=w2 192.168.75.30
RS2 192.168.75.20


C:\Users\86178>curl -vb webcookie=w2 192.168.75.30
*   Trying 192.168.75.30:80...
* Connected to 192.168.75.30 (192.168.75.30) port 80
* using HTTP/1.x
> GET / HTTP/1.1
> Host: 192.168.75.30
> User-Agent: curl/8.13.0
> Accept: */*
> Cookie: webcookie=w2
>
< HTTP/1.1 200 OK
< server: nginx/1.20.1
< date: Fri, 18 Jul 2025 09:14:05 GMT
< content-type: text/html
< content-length: 18
< last-modified: Thu, 17 Jul 2025 08:02:12 GMT
< etag: "6878ae04-12"
< accept-ranges: bytes
<
RS2 192.168.75.20
* Connection #0 to host 192.168.75.30 left intact

 

HAProxy状态页

通过web页面,显示当前haproxy的运行状态

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

#任意位置添加:
listen stats:
        mode http
        bind *:9090
        stats enable
        log global
        stats refresh 5
        stats uri /status
        stats auth test:123

 测试

#在浏览器中输入
192.168.75.30:9090/status

IP透传

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

四层IP透传

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

listen webserver
        bind    *:80
        mode    tcp		#由http改为tcp
        balance roundrobin
        cookie webcookie insert nocache indirect
        #balance hdr(User-Agent)
        hash-type consistent
        server web1 192.168.75.10:80 send-proxy cookie w1 weight 1 check inter 3s fall 3 rise 5
        server web2 192.168.75.20:80 send-proxy cookie w2 weight 1 check inter 3s fall 3 rise 5
        #增加send-proxy
        
systemctl restart haproxy

 

rs1和rs2相同配置:

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;	#增加proxy——protocol
        listen       [::]:80;
        server_name  _;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        error_page 404 /404.html;
        location = /404.html {

systemctl restart nginx

 

 

测试:

#在测试机上访问192.168.75.30

#在rs上查看日志
[root@rs1 ~]# tail /var/log/nginx/access.log
192.168.75.30 - - [20/Jul/2025:10:08:49 +0800] "GET / HTTP/1.1" "192.168.75.100"200 18 "-" "curl/7.76.1" "-"

 

自定义HAProxy 错误界面

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

#haproxy默认使用的错误错误页面
[root@haproxy ~]# rpm -ql  haproxy24z-2.4.27-1.el7.zenetys.x86_64 | grep -E http$
 /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


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

配置如下: 

#创建目录放入自定义错误界面文件
mkdir -p /etc/haproxy/errorpage
#复制原本的文件加以更改即可
cp /usr/share/haproxy/503.http /etc/haproxy/errorpage/503page.http

vim /etc/haproxy/errorpage/503page.http
HTTP/1.0 503 Service Unavailable
Cache-Control: no-cache
Connection: close
Content-Type: text/html;charset=UTF-8

<html><body><h1>离</h1>
散
</body></html>

 测试:将后端服务器停止后在浏览器进行测试

[root@RS1 ~]# systemctl stop nginx.service
[root@RS2 ~]# systemctl stop nginx.service

haproxy四层负载

 以mysql服务为例实现四层负载

#为rs1和rs2安装maridb服务
[root@RS1 ~]# yum install mariadb-server -y
[root@RS2 ~]# yum install mariadb-server -y

#配置文件中增加id
[root@RS1 ~]# vim /etc/my.cnf
[mysqld]
server-id=1

[root@RS2 ~]# vim /etc/my.cnf
[mysqld]
server-id=2

#重启mariadb
[root@RS1 ~]# systemctl restart mariadb.service
[root@RS2 ~]# systemctl restart mariadb.service

[root@RS1 ~]# mysql -e "grant all on *.* to test@'%' identified by 'test';" --grant all 表示给予所有权限 *.* 表示任意数据库中的任意表  '%'表示可以远程登陆 identified by 'test'表示设置密码为test。
[root@RS2 ~]# mysql -e "grant all on *.* to test@'%' identified by 'test';"

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

listen mysql_server
        bind :3306
        mode tcp
        balance roundrobin
        server my1 192.168.75.10:3306 check
        server my2 192.168.75.20:3306 check

#测试
[root@cip ~]# mysql -utest -ptest -h 192.168.75.30 -e "show variables like 'hostname'"
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| hostname      | RS1   |
+---------------+-------+
[root@cip ~]# mysql -utest -ptest -h 192.168.75.30 -e "show variables like 'hostname'"
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| hostname      | RS2   |
+---------------+-------+

[root@cip ~]# mysql -utest -ptest -h 192.168.75.30 -e "select @@server_id"
+-------------+
| @@server_id |
+-------------+
|           1 |
+-------------+
[root@cip ~]# mysql -utest -ptest -h 192.168.75.30 -e "select @@server_id"
+-------------+
| @@server_id |
+-------------+
|           2 |
+-------------+

 

注意:如果使用frontend和backend,一定在 frontend 和 backend 段中都指定mode tcp

frontend mysql_server
bind :3306
mode tcp
use_backend mysql_rs
backend mysql_rs
    mode tcp
    balance leastconn
    server mysql1 192.168.75.10:3306 check
    server mysql2 192.168.75.20:3306 check

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 }

 证书制作

#创建目录存放证书和key
 mkdir /etc/haproxy/certs/
#生成证书
openssl req  -newkey rsa:2048 -nodes  -sha256 -keyout /etc/haproxy/certs/cert.org.key -x509 -days 365 -out /etc/haproxy/certs/cert.org.crt
#查看是否生成
[root@haproxy certs]# cd /etc/haproxy/certs/
[root@haproxy certs]# ls
cert.org.crt  cert.org.key  cert.pem
#将证书和key放在同一个文件下
cat cert.org.key cert.org.crt > cert.pem
#haproxy配置
frontend webkey-80
        bind    *:80
        mode    http
        balance roundrobin
        redirect scheme https if !{ ssl_fc }
        use_backend webserver

frontend webkey-443
        bind    *:443 ssl crt /etc/haproxy/certs/cert.pem
        mode    http
        balance roundrobin
        use_backend     webserver

backend webserver
        server key1 192.168.75.10:80 check
        server key2 192.168.75.20:80 check

#重启haproxy服务
systemctl restart haproxy.service

测试:在浏览器中输入192.168.75.30 会自动添加https

#在客户机上使用命令测试
[root@cip ~]# curl -ikl http://192.168.75.30
HTTP/1.1 302 Found
content-length: 0
location: https://192.168.75.30/
cache-control: no-cache

[root@cip ~]# curl -IkL http://192.168.75.30
HTTP/1.1 302 Found
content-length: 0
location: https://192.168.75.30/
cache-control: no-cache

HTTP/1.1 200 OK
server: nginx/1.20.1
date: Sun, 20 Jul 2025 08:17:37 GMT
content-type: text/html
content-length: 18
last-modified: Thu, 17 Jul 2025 08:02:53 GMT
etag: "6878ae2d-12"
accept-ranges: bytes

 

 

可以看到访问依旧轮询了。

redirect scheme https if !{ ssl_fc }

可以分成 4 个部分理解,每个部分都对应一个固定的语法含义。

        redirect scheme https “redirect” 是 HAProxy 的动作关键字,表示“重定向”。 “scheme https” 告诉 HAProxy:把客户端请求的协议(scheme)改成 https,同时保持原来的主机名、路径和查询串不变。

HTTP/1.1 302 Found
Location: https://<原主机><原路径>?<原查询串>
  1. if 条件判断关键字,相当于“当……时”。

  2. !{ ssl_fc } 条件表达式。

    • ssl_fc 是 HAProxy 内置的布尔变量(fetch),含义是 SSL Front Connection——如果当前连接是 TLS/SSL(即 https),则返回 true;否则返回 false。

    • ! 是逻辑非,表示“取反”。 因此 !{ ssl_fc } 就是“当前连接不是 SSL 连接”,换句话说“是 http 明文连接”。

合起来: “如果当前连接不是 https,就把客户端重定向到 https。”

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值