软件负载均衡一般通过两种方式来实现:基于操作系统的软负载实现和基于第三方应用的软负载实现。LVS就是基于Linux操作系统实现的一种软负载,HAProxy就是开源的并且基于第三应用实现的软负载。
HAProxy相比LVS的使用要简单很多,功能方面也很丰富。当 前,HAProxy支持两种主要的代理模式:"tcp"也即4层(大多用于邮件服务器、内部协议通信服务器等),和7层(HTTP)。在4层模式 下,HAProxy仅在客户端和服务器之间转发双向流量。7层模式下,HAProxy会分析协议,并且能通过允许、拒绝、交换、增加、修改或者删除请求 (request)或者回应(response)里指定内容来控制协议,这种操作要基于特定规则。
LVS、Nginx、HAProxy 是目前使用最广泛的三种软件负载均衡软件。
一般对负载均衡的使用是随着网站规模的提升根据不同的阶段来使用不同的技术。具体的应用需求还得具体分析,如果是中小型的 Web 应用,比如日 PV 小于1000万,用 Nginx 就完全可以了;如果机器不少,可以用 DNS 轮询,LVS 所耗费的机器还是比较多的;大型网站或重要的服务,且服务器比较多时,可以考虑用 LVS。
目前关于网站架构一般比较合理流行的架构方案:Web 前端采用 Nginx/HAProxy+Keepalived 作负载均衡器;后端采用 MySQL数据库一主多从和读写分离,采用 LVS+Keepalived 的架构。
LVS 的体系结构
LVS 架设的服务器集群系统有三个部分组成:
(1) 最前端的负载均衡层,用 Load Balancer 表示
(2) 中间的服务器集群层,用 Server Array 表示
(3) 最底端的数据共享存储层,用 Shared Storage 表示
LVS 的优点
LVS 的缺点
Nginx 的架构设计是采用模块化的、基于事件驱动、异步、单线程且非阻塞。
Nginx 大量使用多路复用和事件通知,Nginx 启动以后,会在系统中以 daemon 的方式在后台运行,其中包括一个 master 进程,n(n>=1) 个 worker 进程。所有的进程都是单线程(即只有一个主线程)的,且进程间通信主要使用共享内存的方式。
其中,master 进程用于接收来自外界的信号,并给 worker 进程发送信号,同时监控 worker 进程的工作状态。worker 进程则是外部请求真正的处理者,每个 worker 请求相互独立且平等的竞争来自客户端的请求。请求只能在一个 worker 进程中被处理,且一个 worker 进程只有一个主线程,所以同时只能处理一个请求。。
Nginx 的优点
HAProxy 支持两种代理模式 TCP(四层)和HTTP(七层),也是支持虚拟主机的。
HAProxy 的优点能够补充 Nginx 的一些缺点,比如支持 Session 的保持,Cookie 的引导;同时支持通过获取指定的 url 来检测后端服务器的状态。
HAProxy 跟 LVS 类似,本身就只是一款负载均衡软件;单纯从效率上来讲 HAProxy 会比 Nginx 有更出色的负载均衡速度,在并发处理上也是优于 Nginx 的。
HAProxy 支持 TCP 协议的负载均衡转发,可以对 MySQL 读进行负载均衡,对后端的 MySQL 节点进行检测和负载均衡,大家可以用 LVS+Keepalived 对 MySQL 主从做负载均衡。
HAProxy 负载均衡策略非常多:Round-robin(轮循)、Weight-round-robin(带权轮循)、source(原地址保持)、RI(请求URL)、rdp-cookie(根据cookie)。
HAPorxy缺点:
(1)不支持POP/SMTP协议
(2) 不支持SPDY协议
(3) 不支持HTTP cache功能。现在不少开源的lb项目,都或多或少具备HTTP cache功能。
(4)重载配置的功能需要重启进程,虽然也是soft restart,但没有Nginx的reaload更为平滑和友好。
(5)多进程模式支持不够好
yum install -y haproxy #安装haproxy
##性能调优相关参数:
maxconn <number>: //设定单haproxy进程的最大并发连接数;
maxconnrate <number>: //设定单haproxy进程每秒接受的连接数;
maxsslconn <number>: //设定单haproxy进程的ssl连接最大并发连接数;
maxsslrate <number>: //单haproxy进程的ssl连接的创建速率上限;
spread-checks <0..50, in percent>
tune.rcvbuf.client <number> //接收客户端请求的缓冲大小
tune.rcvbuf.server <number> //接收服务端响应的缓冲大小
tune.sndbuf.client <number> //向客户端发送响应的缓冲大小
tune.sndbuf.server <number> //向服务端发送请求的缓冲大小
tune.ssl.cachesize <number> //ssl会话的缓存大小
tune.ssl.lifetime <timeout> //ssl会话缓存的有效时长
##配置参数:
bind:
作用:设定监听的地址和端口;
语法:bind [<address>]:<port_range> [, ...]
使用位置:frontend,listen
mode { tcp|http|health }
作用:定义haproxy的工作模型:
tcp:基于layer4实现代理,可代理大多数基于tcp的应用层协议,例如ssh,mysql,pgsql等;
http:客户端的http请求会被深度解析;
health:工作为健康状态检查响应模式,当请求到达时仅回应“OK”即断开连接;
开启统计页面,相关信息:
maxconn <conns>:最大并发连接数,默认为2000,使用位置:frontend、default、listen
stats enable:作用:启用内建的统计页,在缺少其它必要的参数时,会使用默认配置;
默认配置:
- stats uri : /haproxy?stats
- stats realm : "HAProxy Statistics"
- stats auth : no authentication
- stats scope : no restriction
说明:
stats uri <prefix>:自定义stats页面的uri;
stats realm <realm>:启用统计信息并设置身份认证域。
stats auth <user>:<passwd>:定义认证使用的账号和密码;
stats hide-version:隐藏版本信息
stats refresh <delay>:自动刷新相关页面的时间间隔;
stats admin { if | unless } <cond>:条件满足时启用stats内建的管理功能接口;不建议启用,有安全隐患
##ACL匹配的如下所示:
1、ACL derivatives :
path : exact string match(字符窜精确匹配)
path_beg : prefix match(前缀匹配)
path_dir : subdir match(子目录匹配)
path_dom : domain match(域匹配)
path_end : suffix match(后缀匹配)
path_len : length match(长度匹配)
path_reg : regex match(正则匹配)
path_sub : substring match(子串匹配)
例如:
acl test_path path -i /test.txt ##匹配具体路径
acl test_path_beg path_beg -i /test. #匹配前缀包含
acl test_path_end path_end -i .html ##匹配.html结尾
2、可以基于字符串做检测:
req.hdr([<name>[,<occ>]]) : string
对请求报文中的内容做检查
This extracts the last occurrence of header <name> in an HTTP request.
ACL derivatives :
hdr([<name>[,<occ>]]) : exact string match
hdr_beg([<name>[,<occ>]]) : prefix match
hdr_dir([<name>[,<occ>]]) : subdir match
hdr_dom([<name>[,<occ>]]) : domain match
hdr_end([<name>[,<occ>]]) : suffix match
hdr_len([<name>[,<occ>]]) : length match
hdr_reg([<name>[,<occ>]]) : regex match
hdr_sub([<name>[,<occ>]]) : substring match
res.hdr([<name>[,<occ>]]) : string
对响应报文中的内容做检测
ACL derivatives :
shdr([<name>[,<occ>]]) : exact string match
shdr_beg([<name>[,<occ>]]) : prefix match
shdr_dir([<name>[,<occ>]]) : subdir match
shdr_dom([<name>[,<occ>]]) : domain match
shdr_end([<name>[,<occ>]]) : suffix match
shdr_len([<name>[,<occ>]]) : length match
shdr_reg([<name>[,<occ>]]) : regex match
shdr_sub([<name>[,<occ>]]) : substring match
[root@localhost ~]# cat /etc/haproxy/haproxy.cfg
# this config needs haproxy-1.1.28 or haproxy-1.2.1
#global 为全局配置
global
log /dev/log local0 info #配置日志记录,local0为日志设备,默认存放到系统日志
log /dev/log local0 notice #日志级别为 info、notice
#log loghost local0 info
maxconn 4096 #最大连接数
#chroot /usr/share/haproxy #注释掉,不让服务器从自己的目录获取,而从节点服务器
uid 99
gid 99
daemon
#debug
#quiet
#defaults 为默认配置
defaults
log global #定义日志为global中的日志
mode http #模式为http
option httplog #采用http格式记录日志
option dontlognull
retries 3 #检查节点服务器失败三次后,判定节点不可用
#redispatch
maxconn 2000 #最大连接数
contimeout 5000 #连接超时时间
clitimeout 50000 #客户端超时时间
srvtimeout 50000 #服务器超时时间
#listen 应用组件配置
listen webcluster 0.0.0.0:80 #当有访问80端口的请求则进行
# option httpchk GET /index.html #获取web服务器池中服务器的index.html文件
balance roundrobin #定义采用轮询算法
server web1 192.168.158.40:80 check inter 2000 fall 3 #定义在线节点服务器
server web2 192.168.158.50:80 check inter 2000 fall 3
yum -y install keepalived
[root@localhost ~]# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {
1582366329@qq.com #发生故障时,接受信息的email地址
}
notification_email_from doublexi@189.cn
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id LVS_DEVEL
}
vrrp_script chk_haproxy { #自定义的监控脚本
script "/etc/keepalived/check_haproxy.sh"
interval 2
weight 2
}
vrrp_instance VI_1 {
state MASTER #从服务器设为BACKUP
interface ens33 #监听接口
virtual_router_id 51
priority 100 #优先级,backup机器上的优先级要小与这个值
advert_int 1 #检查间隔
authentication {
auth_type PASS
auth_pass 1111
}
track_script { #自定义的监控脚本
chk_haproxy
}
virtual_ipaddress { #VIP地址,可以设多个
192.168.158.100
}
}
[root@localhost ~]# cat /etc/keepalived/ch
check_haproxy.sh chk_haproxy.sh
[root@localhost ~]# cat /etc/keepalived/check_haproxy.sh
#!/bin/bash
h=`ps -C haproxy --no-header |wc -l`
if [ $h -eq 0 ];then
systemctl stop keepalived
fi
haproxy如果停止,则关闭keepalived服务
[root@master ~]# systemctl restart haproxy
[root@master ~]# systemctl restart keepalived.service
停止master的haproxy服务
VIP地址已经漂移到备服务器上
基于主备的双主互相监控的高可用模式
[root@master ~]# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived
vrrp_script check_haproxy {
script "/etc/keepalived/check_haproxy.sh"
interval 2
weight 2
}
global_defs {
notification_email {
acassen@firewall.loc
}
router_id LVS_DEVEL
}
vrrp_instance VI_1 {
state MASTER
interface ens33
virtual_router_id 50
nopreempt
priority 150
advert_int 1
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
192.168.158.100
}
track_script {
check_haproxy
}
}
vrrp_instance VI_2 {
state BACKUP
interface ens33
virtual_router_id 51
nopreempt
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
192.168.158.200
}
track_script {
check_haproxy
}
}
备keepalive配置文件
[root@backup ~]# cat /etc/keepalived/keepalived.conf
i! Configuration File for keepalived
vrrp_script check_haproxy {
script "/etc/keepalived/check_haproxy.sh"
interval 2
weight 2
}
global_defs {
notification_email {
acassen@firewall.loc
}
router_id LVS_DEVEL
}
vrrp_instance VI_1 {
state BACKUP
interface ens33
virtual_router_id 50
nopreempt
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
192.168.158.100
}
track_script {
check_haproxy
}
}
vrrp_instance VI_2 {
state MASTER
interface ens33
virtual_router_id 51
nopreempt
priority 150
advert_int 1
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
192.168.158.200
}
track_script {
check_haproxy
}
}
总结:
1、配置haproxy负载均衡代理后端web服务器
2、配置keepalive配置文件master有backup优先级,指定自定义监控的脚本
3、编写监控脚本