上一篇我们介绍了四层的负载均衡器LVS, 这次我们我们介绍另外一种负载均衡器HAProxy。
一、HAProxy简介
HAProxy是一种高效、可靠、免费的高可用及负载均衡解决方案,非常适合于高负载站点的七层数据请求。因为HAProxy实现了一种事件驱动、单一进程模型,此模型支持非常大的并发连接数。客户端通过HAProxy代理服务器获得站点页面,而代理服务器收到客户请求后根据负载均衡的规则将请求数据转发给后端真实服务器。HAProxy还支持Session的保持和Cookie的引导。
同一客户端访问服务器,HAProxy保持会话的三种方案:
1、 HAProxy将客户端ip进行Hash计算并保存,由此确保相同IP访问时被转发到同一真实服务器上。( 配置:balance source)
2、 HAProxy依靠真实服务器发送给客户端的cookie信息进行会话保持。
3、 HAProxy保存真实服务器的session及服务器标识,实现会话保持功能。
二、HAProxy工作原理
HAProxy有前端(frontend)和后端(backend),前端和后端都可以有多个。也可以只有一个listen块来同时实现前端和后端。这里主要讲一下frontend和backend工作模式。 前端(frontend)区域可以根据HTTP请求的header信息来定义一些规则,然后将符合某规则的请求转发到相应后端(backend)进行处理。因此HAProxy可以实现动静分离(动静分离简单来说就是指将静态请求转发到对应的静态资源服务器,将动态请求转发到动态资源服务器),我们上篇说过的LVS 就没有此功能。
三、HAProxy详解配置文件
主程序:/usr/sbin/haproxy 配置文件:/etc/haproxy/haproxy.cfg Unit file:/usr/lib/systemd/system/haproxy.service
配置文件/etc/haproxy/haproxy.cfg主要由两部分组成:global 和 proxies 配置段。
下面我们详细说明这两个配置段都有哪些内容和其对应的含义。
进程及安全配置相关的参数 性能调整相关参数 Debug参数
#以下为默认全局配置端信息:
global
log 127.0.0.1 local2 #全局日志配置,日志将被记录在本机的local2设施中。chroot /var/lib/haproxy #chroot运行路径,增加安全性
pidfile /var/run/haproxy.pid #HAProxy的pid存放路径
maxconn 4000 #默认的最大连接数
user haproxy #运行haproxy的用户
group haproxy #运行haproxy用户所属的组
daemon #以守护进程的方式工作与后台
# turn on stats unix socket
stats socket /var/lib/haproxy/stats #基于本地的文件传输
proxies:代理配置段 包含的内容如下:
backend:后端,相当于nginx, upstream {} listen:同时拥有前端和后端,适用于一对一环境
#以下为默认的代理配置段的信息
defaults
mode http #默认的模式mode { tcp|http|health },tcp是4层,http是7层,health只会返回OK
log global #应用全局的日志配置
option httplog # 启用日志记录HTTP请求,默认haproxy日志记录是不记录HTTP请求日志
option dontlognull # 启用该项,日志中将不会记录空连接。所谓空连接就是在上游的负载均衡器或者监控系统为了探测该服务是否存活可用时,需要定期的连接或者获取某一固定的组件或页面,或者探测扫描端口是否在监听或开放等动作被称为空连接;官方文档中标注,如果该服务上游没有其他的负载均衡器的话,建议不要使用该参数,因为互联网上的恶意扫描或其他动作就不会被记录下来
option http-server-close #每次请求完毕后主动关闭http通道
option forwardfor except 127.0.0.0/8 #如果服务器上的应用程序想记录发起请求的客户端的IP地址,需要在HAProxy上配置此选项, 这样 HAProxy会把客户端的IP信息发送给服务器,在HTTP请求中添加"X-Forwarded-For"字段。启用X-Forwarded-For,在requests头部插入客户端IP发送给后端的server,使后端server获取到客户端的真实IP。
option redispatch #当使用了cookie时,haproxy将会将其请求的后端服务器的serverID插入到cookie中,以保证会话的SESSION持久性;而此时,如果后端的服务器宕掉了,但是客户端的cookie是不会刷新的,如果设置此参数,将会将客户的请求强制定向到另外一个后端server上,以保证服务的正常。
retries 3 # 定义连接后端服务器的失败重连次数,连接失败次数超过此值后将会将对应后端服务器标记为不可用
timeout http-request 10s #http请求超时时间
timeout queue 1m #一个请求在队列里的超时时间
timeout connect 10s #连接超时
timeout client 1m #客户端超时
timeout server 1m #服务器端超时
timeout http-keep-alive 10s #设置http-keep-alive的超时时间
timeout check 10s #检测超时
maxconn 3000 #每个进程可用的最大连接数
frontend main *:5000 #监听地址为5000
#定义了动静态分离
#请求URL是以/static, /images, /javascript或 /stylesheets 开头的都将请求转到backend static。也就是将请求转到静态服务器。
acl url_static path_beg -i /static /images /javascript /stylesheets
#请求URL是以.jpg, .gif, .png, .css, .js结尾的请求也都转到backend static。也就是将请求转到静态服务器。
acl url_static path_end -i .jpg .gif .png .css .js
use_backend static if url_static
#如果不满足上述动态请求条件,则会将该请求转向default_backend, 名为app.
default_backend app
#---------------------------------------------------------------------
# static backend for serving up images, stylesheets and such
#---------------------------------------------------------------------
#backend static(用于转发静态请求)具体定义如下:算法为轮询,将静态请求转到静态web服务器为127.0.0.1的4331端口。
backend static
balance roundrobin ##负载均衡算法
server static 127.0.0.1:4331 check ##定义的后端
#---------------------------------------------------------------------
# round robin balancing between the various backends
#---------------------------------------------------------------------
#backend app (用于转发动态请求)具体定义如下:算法为轮询,将动态请求转到以下四台服务器的任意一台
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 ##定义的多个后端
四、HAProxy 常用功能介绍及实验演练 HAProxy server: 192.168.1.102 Web server1: 192.168.1.105 Web server1: 192.168.1.106
1. 搭建一台HAProxy 服务器和 两台Apache服务器, 实现负载均衡。
准备工作:
1)在HAProxy server 上面安装haproxy:
yum -y install haproxy
2)在Web server1 和 Web server2 上面先安装httpd:
yum -y install httpd
3)配置网页:
Web server1 的默认网页内容为Web1. Web server2 的默认网页内容为Web2.
[root@workernode1 html]# pwd
/var/www/html
[root@workernode1 html]# cat index.html
Web1
[root@worknode2 html]# pwd
/var/www/html
[root@worknode2 html]# cat index.html
Web2
[root@worknode2 html]#
4)在Web server1 和 Web server2 上面启动httpd服务:
systemctl start httpd
5)使用curl http://localhost:80 访问页面查看访问内容分别为Web1 和 Web2:
[root@workernode1 html]# curl http://localhost:80
Web1
[root@worknode2 html]# curl http://localhost:80
Web2
下面我们开始真正的配置:
1)修改haproxy的主配置文件 vim /etc/haproxy/haproxy.cfg
[root@manager haproxy]# vim /etc/haproxy/haproxy.cfg
#修改内容如下:
frontend main *:80
default_backend webservers
backend webservers
balance roundrobin
server app1 192.168.1.105:80 check
server app2 192.168.1.106:80 check
[root@manager haproxy]
2)重启haproxy服务,查看haproxy监听的端口:
[root@manager ~]# systemctl restart haproxy
[root@manager ~]# systemctl status haproxy
● haproxy.service - HAProxy Load Balancer
Loaded: loaded (/usr/lib/systemd/system/haproxy.service; enabled; vendor preset: disabled)
Active: active (running) since Sun 2020-05-24 05:18:38 EDT; 4s ago
Process: 103437 ExecReload=/bin/kill -USR2 $MAINPID (code=exited, status=0/SUCCESS)
Main PID: 111840 (haproxy-systemd)
Tasks: 3
CGroup: /system.slice/haproxy.service
├─111840 /usr/sbin/haproxy-systemd-wrapper -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid
├─111841 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds
└─111842 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds
May 24 05:18:38 manager systemd[1]: Started HAProxy Load Balancer.
May 24 05:18:38 manager haproxy-systemd-wrapper[111840]: haproxy-systemd-wrapper: executing /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds
[root@manager ~]# netstat -antup | grep -i haproxy
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 111842/haproxy
tcp 0 0 0.0.0.0:90 0.0.0.0:* LISTEN 111842/haproxy
udp 0 0 0.0.0.0:33435 0.0.0.0:* 111841/haproxy
[root@manager ~]#
3)访问下服务器地址 如下图所示:访问HAProxy server的80端口, 在Web1 和 Web2 跳跃
也可以写一个循环来测试:
while [ TURE ]; do curl http://192.168.1.102:80; sleep 2; done
2. 配置haproxy的日志功能
#1.配置haproxy的日志功能
vim /etc/resyslog.conf
加入下面的几个参数,启用udp和tcp模块,加入haproxy.log的路径
[root@manager log]# cat /etc/rsyslog.conf | tail -n 5
$ModLoad imtcp
$InputTCPServerRun 514
local2.* /var/log/haproxy.log
[root@manager log]#
#2.重启日志服务
[root@manager log]# systemctl restart rsyslog
#3.重新载入haproxy
[root@manager log]# systemctl reload haproxy
#4.查看日志的输出
[root@manager log]# tail -f /var/log/haproxy.log
May 23 04:00:27 localhost haproxy[22496]: Proxy main started.
May 23 04:00:27 localhost haproxy[22496]: Proxy webservers started.
May 23 04:00:27 localhost haproxy[22136]: Stopping frontend main in 0 ms.
May 23 04:00:27 localhost haproxy[22136]: Stopping backend webservers in 0 ms.
May 23 04:00:27 localhost haproxy[22136]: Proxy main stopped (FE: 4 conns, BE: 0 conns).
May 23 04:00:27 localhost haproxy[22136]: Proxy webservers stopped (FE: 0 conns, BE: 4 conns).
May 23 04:05:40 localhost haproxy[22497]: 127.0.0.1:43980 [23/May/2020:04:05:40.640] main webservers/app1 0/0/2/3/5 200 263 - - ---- 1/1/0/0/0 0/0 "GET / HTTP/1.1"
May 23 04:05:41 localhost haproxy[22497]: 127.0.0.1:43988 [23/May/2020:04:05:41.398] main webservers/app2 0/0/0/3/3 200 263 - - ---- 1/1/0/1/0 0/0 "GET / HTTP/1.1"
May 23 04:05:42 localhost haproxy[22497]: 127.0.0.1:43996 [23/May/2020:04:05:42.112] main webservers/app1 0/0/0/6/6 200 263 - - ---- 1/1/0/0/0 0/0 "GET / HTTP/1.1"
日志输出结果如下图所示:
1)更改配置文件:
vim /etc/haproxy/haproxy.cfg
frontend websrv
bind *:80
default_backend webservers
2)重新载入haproxy:
systemctl reload haproxy
3)查看监听的端口:
[root@manager ~]# netstat -antup | grep -i 80
tcp 0 0 0.0.0.0:80 0.0.0.0:*
4)查看测试页
(也就是我们在简介里面说的实现会话保持的第一种方法:基于source算法,确保相同IP访问时被转发到同一真实服务器上。)
1)把balance调度算法改为source:
vim /etc/haproxy/haproxy.cfg
2)重新载入 haproxy:
3)查看测试页面:可以看到来自于同一IP的请求,始终定向至同一台:
5. uri的机制,对同一个uri的请求,始终定义至同一个server上 (配置: balance uri)
1)首先我们现在Web server1 和Web server2 上面多定义几个测试页面:
2)在haproxy server 上面修改调度算法为uri:
3)重新加载haproxy服务:
4)访问测试页:
在Firefox 浏览器访问test1.html 指向的是web2节点
我们换一个浏览器,用IE访问test1.html 也指向的是web2节点
在Firefox 浏览器访问test2.html 指向的是web1节点
我们换一个浏览器,用IE访问test2.html 也指向的是web1节点
由此可见,uri的机制,对同一个uri的请求,始终定义至同一个server上。也就是上述实现的无论从哪个客户端访问test1.html, 都指向的是web2上面的test1.html;无论从哪个客户端访问test2.html, 都指向的是web1上面的test2.html。
6. 设置session会话绑定
也就是我们在简介中提到的第二种设置会话保持的方法,HAProxy依靠真实服务器发送给客户端的cookie信息(也就是浏览器端的缓存信息中会包含服务器的node信息, 如web1 或者 是web2, 从而该浏览器下次访问时还会访问之前访问过的web服务器。)进行会话保持。
1)编辑配置文件:
vim /etc/haproxy/haproxy.cfg
2)重新加载haproxy
3)在浏览器中可以看到cookie的方式:
node=node1, 也就是web1
7. 配置服务状态查看
1)编辑配置文件:
vim /etc/haproxy/haproxy.cfg
2)重新加载haproxy
3)访问状态的链接http://192.168.1.102/haproxy?stats:出现如下图所示的页面:
可以通过该页面查看到forntend 和 backend 的信息和当前状态等。
8. 启用haproxy管理接口 1)编辑配置文件haproxy.cfg 加入下面所示的参数 stats admin if TRUE
2)重新加载haproxy
3)查看下面界面,发现多了管理功能:
功能如下:可以通过此管理功能,管理几个节点
9. 定义haproxy的动静分离 1)编辑配置文件haproxy.cfg,加入下面的代码
frontend websrvs
bind *:80
acl url_static path_beg -i /static /images /javascript /stylesheets
acl url_static path_end -i .jpg .gif .png .css .js .html
acl host_static hdr_beg(host) -i img. video. download. ftp. imgs. videos.
acl url_php path_end -i .php
use_backend static if url_static or host_static
use_backend dynamic if url_php
default_backend dynamic
backend static
balance roundrobin
server node1 192.168.20.11:80 check maxconn 30000
backend dynamic
balance roundrobin
server node2 192.168.20.12:80 check maxconn 1000
2)通过acl 访问规则来实现的:
3)修改完配置文件后重新载入配置文件
演示效果为: 访问静态页面都落到node1上
访问动态页面都落到node2上
现在我们来想一个问题, 如果后端的web 服务器挂了怎么办?
其实HAProxy支持后端web服务器状态检查,当其代理的后端服务器出现故障时,Haproxy会自动将该故障服务器摘除,当故障的服务器恢复后,Haproxy还会自动的将该服务器自动加入进来提供服务。下面我们来详细介绍该功能。
五、HAProxy后端web服务器状态检测
HAProxy有三种状态检测方式: 1).基于四层的传输端口做状态监测 2).基于指定的uri做状态监测 3).基于指定的URI的resquest请求头部内容做状态监测
通过监听端口进行健康检测。这种检测方式,haproxy只会去检查后端server的端口,并不能保证服务的真正可用。有时候服务端口和进程都是存在的,但是就是不正常提供服务,尤其是Java程序很容易出现类似的案例,这个时候如果我们使用基于端口的监听方式明显就不太合适了。
示例: 1)修改配置文件 vim /etc/haproxy/haproxy.cfg
2)加载haproxy:
3)先查看状态页面http://192.168.1.102:90/haproxy?stats,目前web1 web2 都正常:
4)测试: 将web1的nginx服务停止
5)再次查看状态页面http://192.168.1.102:90/haproxy?stats,发现web1 down 了。
6)通过访问HAProxy 的80 端口,发现一直将请求转到到web server2。
2. 基于指定的uri做状态监测
检测方式,是用GET后端server的的web页面,基本上可以代表后端服务的可用性。是模拟客户端去访问服务端,如果响应码是正常的说明服务端处于正常工作状态,从而避免了基于端口监控的弊端。
示例:
1)修改配置文件
vim /etc/haproxy/haproxy.cfg
2)加载haproxy:
3)先查看状态页面http://192.168.1.102:90/haproxy?stats,目前web1 web2 都正常:
4)测试: 将web1的nginx服务停止
5)再次查看状态页面http://192.168.1.102:90/haproxy?stats,发现web1 down 了。
3. 基于指定的URI的resquest请求头部内容做状态监测
和上面所说的"基于指定URI做状态监测"原理一样,只不过它做了一个优化操作,就是不要消息体(body)部分,只返回给haproxy响应头部(head)信息即可,从而节省了后端web服务器的网络I/O。在生产环境中我们更推荐使用这种方法。
示例:
1)修改配置文件
vim /etc/haproxy/haproxy.cfg
2)加载haproxy:
3)先查看状态页面http://192.168.1.102:90/haproxy?stats,目前web1 web2 都正常:
4)测试:
我们不停服务,只是修改index.html的名字, 让HAProxy 找不到index.html网页:
5)我们看到当前的端口还是正在监听的.
6)再次查看状态页面http://192.168.1.102:90/haproxy?stats,发现web1 和 web2都down 了。
7)我们再将网页名字改回到index.html, 再次查看状态页面:
发现web1 和 web2 显示正常:
今天我们先介绍到这里。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有