Web集群调度器-Haproxy
一、Web集群调度器
1.常用的Web集群调度器
目前常用的Web集群调度器分为软件和硬件
软件通常使用开源的LVS、Haproxy、Nginx
LVS性能最好,但是搭建相对复杂;Nginx的upstream模块支持群集功能,但是对群集节点健康检查功能不强,高并发性能没有Haproxy好。
硬件一般使用比较多的是F5,也有很多人使用国内的一些产品,如梭子鱼、绿盟等。
2. Haproxy应用分析
● LVS不支持正则处理,不能实现动静分离
● 对于大型网站,LVS的实施配置复杂,维护成本相对较高
● 适用于负载大的Web站点
● 运行在硬件上可支持数以万计的并发连接请求
3. Haproxy的主要特性
● 可靠性和稳定性非常好,可以与硬件级F5负载均衡设备相媲美;
● 最高可以同时维护40000-50000个并发连接,单位时间内处理的最大请求数位20000个,最大处理能力可达10Git/s;
● 支持多大8种负载均衡算法,同时也支持会话保持;
● 支持虚拟主机功能,从而实现web负载均衡更加灵活;
● 支持连接拒绝、全透明代理等独特的功能;
● 拥有强大的ACL支持,用于访问控制;
● 其独特的弹性二叉树数据结构,使数据结构得到复杂性上升到了0(1),即数据的查寻速度不会随着数据条目的增加而速度有所下降;
● 支持客户端的keepalive功能,减少客户端与Haproxy的多次三次握手导致资源浪费,让多个请求在一个tcp连接中完成;
● 支持TCP急速,零复制功能,类似于MMAP机制;
● 支持响应池(response buffering);
● 支持RDP协议
● 基于源的粘性,类似Nginx的ip_bash功能,把来自同一客户端的请求在一定时间内始终调度到上游的同一服务器;
● 更好统计数据接口,其web接口显示后端集群中各个服务器的接收、发送、拒绝、错误等数据的统计信息;
● 详细的健康状态监测,web接口中有关于对上游服务器的健康监测状态,并提供了一定的管理功能;
● 基于流量的健康评估机制;
● 基于HTTP认证;
● 基于命令行的管理接口;
● 日志分析器,可对日志进行分析。
4. 常用集群调度器的优缺点
集群调度器 | 优点 | 缺点 |
Nginx | ● 工作在网络的7层之上,可以针对http应用做一些分流的策略,比如针对域名、目录结构。Nginx正则规则比Haproxy更为强大和灵活。 ● Nginx对网络稳定性的依赖非常小,理论上能ping通就就能进行负载功能,LVS对网络稳定性依赖比较大,稳定要求相对更高。 ● Nginx安装和配置、测试比较简单、方便,有清晰的日志用于排查和管理,LVS的配置、测试就要花比较长的时间了。 ● 可以承担高负载压力且稳定,一般能支撑几万次的并发量,负载度比LVS相对小些。 ● Nginx可以通过端口检测到服务器内部的故障,比如根据服务器处理网页返回的状态码、超时等等。 ● Nginx不仅仅是一款优秀的负载均衡器/反向代理软件,它同时也是功能强大的Web应用服务器。 ● Nginx作为Web反向加速缓存越来越成熟了,速度比传统的Squid服务器更快,很多场景下都将其作为反向代理加速器。 ● Nginx作为静态网页和图片服务器,这方面的性能非常优秀,同时第三方模块也很多。 | ● Nginx仅能支持http、https和Email协议,这样就在适用范围上面小些。 ● 对后端服务器的健康检查,只支持通过端口来检测,不支持通过url来检测。 ● 不支持Session的直接保持,需要通过ip_hash和COOKIE的引导来解决。 |
LVS | ● 抗负载能力强、是工作在网络4层之上仅作分发之用,没有流量的产生。因此负载均衡软件里的性能最强的,对内存和cpu资源消耗比较低。 ● LVS工作稳定,因为其本身抗负载能力很强,自身有完整的双机热备方案。 无流量,LVS只分发请求,而流量并不从它本身出去,这点保证了均衡器IO的性能不会收到大流量的影响。 ● 应用范围较广,因为LVS工作在4层,所以它几乎可对所有应用做负载均衡,包括http、数据库等。 | ● 软件本身不支持正则表达式处理,不能做动静分离。相对来说,Nginx/Haproxy+Keepalived则具有明显的优势。 ● 如果是网站应用比较庞大的话,LVS/DR+Keepalived实施起来就比较复杂了。相对来说,Nginx/Haproxy+Keepalived就简单多了。 |
Haproxy | ● Haproxy也是支持虚拟主机的。 ● Haproxy支持8种负载均衡策略。 ● Haproxy的优点能够补充Nginx的一些缺点,比如支持Session的保持,COOKIE的引导,同时支持通过获取指定的url来检测后端服务器的状态。 ● Haproxy跟LVS类似,本身就只是一款负载均衡软件,单纯从效率上来讲Haproxy会比Nginx有更出色的负载均衡速度,在并发处理上也是优于Nginx的。 ● Haproxy支持TCP协议的负载均衡转发。 | ● 不支持POP/SMTP协议 ● 不支持SPDY协议 ● 不支持HTTP cache功能。现在不少开源的lb项目,都或多或少具备HTTP cache功能。 ● 重载配置的功能需要重启进程,虽然也是soft restart,但没有Nginx的reaload更为平滑和友好。 ● 多进程模式支持不够好 |
5. LVS、Nginx、Haproxy的区别
● LVS是基于Linux操作系统实现软负载均衡,而Haproxy和Nginx是基于第三方应用实现的软负载均衡;
● LVS是可实现4层的IP负载均衡技术,无法实现基于目录、URL的转发。而Haproxy在状态监测方面功能更丰富、强大,可支持端口、URL、脚本等多种状态监测方式;
● LVS因为工作在ISO模型的第四层,其状态监测功能单一,而Haproxy在状态监测方面功能更丰富、强大,可支持端口、URL、脚本等多种状态监测方式;
● Haproxy功能强大,但整体性能低于4层模式的LVS负载均衡
● Nginx主要用于Web服务器或缓存服务器,Nginx的upstream模块虽然也支持群集功能,但是对群集节点健康检查功能不强,性能没有Haproxy好
● LVS性能方面表现最好,其次是Haproxy
● LVS只支持4层转发,Haproxy和Nginx都能支持4层和7层的转发
● 对节点的健康检查,Haproxy、LVS都是主动检查,Haproxy检查的方式更丰富,Nginx只能被动检查,通过转发请求是否失败来判断
6. Haproxy的调度算法
Haproxy常用的调度算法 | 调度依据 |
roundrobin | 表示简单的轮询 |
static-rr | 表示根据权重轮询 |
leastconn | 表示最少连接者先处理 |
source | 表示根据请求源ip |
uri | 表示根据请求的URI,做cdn需使用 |
url_param | 表示根据请求的URL参数'balance url_param' requires an URL parameter name |
hdr(name) | 表示根据HTTP请求头来锁定每一次HTTP请求 |
rdp-COOKIE(name) | 表示根据COOKIE(name)来锁定并哈希每一次TCP请求 |
Haproxy支持多种调度算法,常用的有三种 | 轮询调度RR 最小连接数算法LC 基于来源访问调度算法SH |
(1)RR(Round Robin)
rr算法是最简单最常用的一种算法,即轮询调度
例如:
有三个节点A、B、C;
第一个用户访问会被指派到节点A;
第二个用户访问会被指派到节点B;
第三个用户访问会被指派到节点C;
第四个用户访问继续指派到节点A,轮询分配访问请求实现负载均衡效果。
(2)LC(Least Connections)
最小连接数算法,根据后端节点连接数大小动态分配前端请求。
例如:
有三个节点A、B、C,各节点的连接数分别为A:4、B:5、C:6;
第一个用户连接请求,会被指派到A上,连接数变为A:5、B:5、C:6;
第二个用户请求会继续分配到A上,连接数变为A:6、B:5、C:6;再有新的请求会分配给B,每次将新的请求指派给连接数最小的客户端;
由于实际情况下A、B、C的连接数会动态释放,很难出现一样连接数的情况;
此算法相比较rr算法有很大改进,是目前用到比较多的一种算法。
(3)SH(Source Hashing)
基于来源访问调度算法,用于一些有Session会话记录在服务器端的场景,可以基于来源的IP、COOKIE等做集群调度。
例如:
有三个节点A、B、C,第一个用户第一次访问被指派到了A,第二个用户第一次访问被指派到了B;
当第一个用户第二次访问时会被继续指派到A,第二个用户第二次访问时依旧会被指派到B,只要负载均衡调度器不重启,第一个用户访问都会被指派到A,第二个用户访问都会被指派到B,实现集群的调度;
此调度算法好处是实现会话保持,但某些IP访问量非常大时会引起负载不均衡,部分节点访问量超大,影响业务使用。
二、使用Haproxy搭建Web集群
1. 服务器及IP配置
Haproxy服务器:192.168.10.5
Nginx服务器1:192.168.10.3
Nginx服务器2:192.168.10.4
客户端:192.168.10.1
https://www.haproxy.org/#haproxy-2.1.3.tar.gz
2. Haproxy服务器部署
1.关闭防火墙,将安装Haproxy所需软件包传到/opt目录下
[root@haproxy ~]# systemctl stop firewalld
[root@haproxy ~]# setenforce 0
setenforce: SELinux is disabled
[root@haproxy ~]# cd /opt
[root@haproxy opt]# rz -E
rz waiting to receive.
[root@haproxy opt]# ls
haproxy-1.5.19.tar.gz rh
2.编译安装Haproxy
[root@haproxy opt]# yum install -y pcre-devel bzip2-devel openssl-devel libnl3-devel systemd-devel gcc gcc-c++ make
[root@haproxy opt]# tar zxvf haproxy-1.5.19.tar.gz
[root@haproxy opt]# cd haproxy-1.5.19/
[root@haproxy haproxy-1.5.19]# uname -r
3.10.0-693.el7.x86_64
[root@haproxy haproxy-1.5.19]# make TARGET=linux-glibc \
USE_OPENSSL=1 \
USE_SYSTEMD=1 \
USE_PCRE=1 \
USE_ZLIB=1
[root@haproxy haproxy-1.5.19]# make install
3.Haproxy服务器配置
[root@haproxy haproxy-1.5.19]# mkdir /etc/haproxy
[root@haproxy haproxy-1.5.19]# cp examples/haproxy.cfg /etc/haproxy/
[root@haproxy haproxy-1.5.19]# cd /etc/haproxy
[root@haproxy haproxy]# vim haproxy.cfg
# this config needs haproxy-1.1.28 or haproxy-1.2.1
global
##全局配置,主要用于定义全局参数,属于进程级的配置,通常和操作系统配置有关
##4-5行修改,定义haproxy日志输出设置和日志级别,local0为日志设备,默认存放到系统日志
log /dev/log local0 info
log /dev/log local0 notice
#log loghost local0 info
maxconn 4096
##最大连接数,需考虑ulimit -n限制,推荐使用10240
#chroot /usr/share/haproxy
uid 99
##用户UID
gid 99
##用户GID
daemon
##守护进程模式
nbproc 2
##添加,设置并发进程数,建议与当前服务器CPU核数相等或为其2倍
#debug
#quiet
defaults
##配置默认参数,这些参数可以被用到Listen,frontend,backend组件
log global
##引入global定义的日志格式
mode http
##模式为http(7层代理http,4层代理tcp)
option httplog
##日志类别为http日志格式
option dontlognull
##不记录健康检查日志信息
retries 3
##检查节点服务器失败次数,连续达到三次失败,则认为节点不可用
redispatch
##当服务器负载很高时,自动结束当前队列处理比较久的连接
maxconn 2000
##最大连接数,"defaults"中的值不能超过"global"段中的定义
#contimeout 5000
##设置连接超时时间,默认单位是毫秒
#clitimeout 50000
##设置客户端超时时间,默认单位是毫秒
#srvtimeout 50000
##设置服务器超时时间,默认单位是毫秒
timeout http-request 10s
##默认http请求超时时间
timeout queue 1m
##默认队列超时时间
timeout connect 10s
##默认连接超时时间,新版本中替代contimeout,该参数向后兼容
timeout client 1m
##默认客户端超时时间,新版本中替代clitimeout,该参数向后兼容
timeout server 1m
##默认服务器超时时间,新版本中替代srvtimeout,该参数向后兼容
timeout http-keep-alive 10s
##默认持续连接超时时间
timeout check 10s
##设置心跳检查超时时间
##删除下面所有listen项,并添加以下内容
listen webcluster 0.0.0.0:80
##haproxy实例状态监控部分配置,定义一个名为webcluster的应用
option httpchk GET /test.html
##检查服务器的test.html文件
balance roundrobin
##负载均衡调度算法使用轮询算法roundrobin
##最小连接数算法:leastconn;来源访问调度算法:source;类似于nginx的ip_bash
server inst1 192.168.122.100:80 check inter 2000 fall 3
##定义在线节点server1
##check inter 2000表示启用对此后端服务器执行健康检查,设置健康状态检查的时间间隔,单位为毫秒
##fall 3表示连续三次检查不到心跳频率则认为该节点失效
##若节点配置后带有"backup"表示该节点只是个备份节点,仅在所有在线节点都失效时该节点才启用。不携带"backup",表示为主节点,和其它在线节点共同提供服务
server inst2 192.168.122.101:80 check inter 2000 fall 3
##定义在线节点server2
global
maxconn 4096
ulimit-n 16384
log 127.0.0.1 local0
uid 200
gid 200
chroot /var/empty
nbproc 2
daemon
defaults
mode http
retries 3
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
frontend www
bind *:80
bind-process 2
mode http
option httplog
option forwardfor
option httpclose
log global
default_backend serverpool
backend serverpool
mode http
option redispatch
option abortonclose
balance static-rr
COOKIE SERVERID
option httpchk GET /index.html
server ser01 192.168.80.20:80 COOKIE 1 weight 1 check inter 2000 rise 2 fall 3
server ser02 192.168.80.80:80 COOKIE 2 weight 1 check inter 2000 rise 2 fall 3
listen admin_stats
bind 0.0.0.0:9188
mode http
log 127.0.0.1 local0 err
stats refresh 30s
stats uri /status
stats realm welcom login\ Haproxy
stats auth admin:admin123
stats hide-version
stats admin if TRUE
4.添加haproxy系统服务
[root@haproxy haproxy]# cp /opt/haproxy-1.5.19/examples/haproxy.init /etc/init.d/haproxy
[root@haproxy haproxy]# cd /etc/init.d
[root@haproxy init.d]# chmod +x haproxy
[root@haproxy init.d]# chkconfig --add haproxy
[root@haproxy init.d]# ln -s /usr/local/sbin/haproxy /usr/sbin/haproxy
vim /usr/lib/systemd/system/haproxy.service
[Unit]
Description=HAProxy Load Balancer
After=syslog.target network.target
[Service]
ExecStartPre=/usr/local/sbin/haproxy -f /etc/haproxy/haproxy.cfg -c -q
ExecStart=/usr/local/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid
ExecReload=/bin/kill -USR2 $MAINPID
[Install]
WantedBy=multi-user.target
3. 配置nginx服务器
1.yum安装nginx
nginx_server1(192.168.10.3)
[root@nginx_server1 ~]# systemctl stop firewalld
[root@nginx_server1 ~]# setenforce 0
[root@nginx_server1 ~]# cd /etc/yum.repos.d/
[root@nginx_server1 yum.repos.d]# vim nginx.repo
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=0
enabled=1
[root@nginx_server1 yum.repos.d]# yum install -y nginx
[root@nginx_server1 yum.repos.d]# nginx -v
nginx version: nginx/1.20.1
nginx_server2(192.168.10.4)
[root@nginx_server2 ~]# systemctl stop firewalld
[root@nginx_server2 ~]# setenforce 0
[root@nginx_server2 ~]# cd /etc/yum.repos.d/
[root@nginx_server2 yum.repos.d]# vim nginx.repo
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=0
enbaled=1
[root@nginx_server2 yum.repos.d]# yum install -y nginx
[root@nginx_server2 yum.repos.d]# nginx -v
nginx version: nginx/1.20.1
2.配置健康检查文件以及首页文件
nginx_server1(192.168.10.3)
[root@nginx_server1 yum.repos.d]# cd /usr/share/nginx/html/
[root@nginx_server1 html]# ls
50x.html index.html
[root@nginx_server1 html]# echo "this is test1 health-check" > test.html
[root@nginx_server1 html]# echo "this is test1 web" > index.html
[root@nginx_server1 html]# systemctl start nginx
[root@nginx_server1 html]# netstat -natp | grep :80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 11937/nginx: master
nginx_server2(192.168.10.4)
[root@nginx_server2 yum.repos.d]# cd /usr/share/nginx/html/
[root@nginx_server2 html]# ls
50x.html index.html
[root@nginx_server2 html]# echo "this is test2 health-check" > test.html
[root@nginx_server2 html]# echo "this is test2 web" > index.html
[root@nginx_server2 html]# systemctl start nginx
[root@nginx_server2 html]# netstat -natp | grep :80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 11122/nginx: master
3.Haproxy服务器启动haproxy服务
[root@haproxy haproxy]# service haproxy start
Starting haproxy (via systemctl): [ 确定 ]
haproxy -c -f /etc/haproxy/haproxy.cfg //检查配置文件
systemctl daemon-reload
service haproxy start
netstat -anpt |grep haproxy
4.客户端访问测试
(1)客户端访问http://192.168.10.5/index.html
(2)客户端访问http://192.168.10.5/test.html
(3)查看统计页面http://192.168.10.5:9188/status
将192.168.10.3的nginx停掉,测试高可用
再将192.168.10.3的nginx启动,不断刷新界面
第一次刷新
第二次刷新
第一次刷新
第二次刷新
这样,网页就能在10.3和10.4来回跳动
三、日志定义优化
1. 定义日志文件
默认haproxy的日志是输出到系统syslog中,查看起来不是非常方便,为了更好的管理haproxy的日志,我们在生产环境中一般单独定义出来。需要将haproxy的info及notice日志分别记录到不同的日志文件中。
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
# this config needs haproxy-1.1.28 or haproxy-1.2.1
global
log /dev/log local0 info
log /dev/log local0 notice
[root@haproxy ~]# service haproxy restart
Restarting haproxy (via systemctl): [ 确定 ]
2. rsyslog配置
需要修改rsyslog配置,为了便于管理。将haproxy相关的配置独立定义到haproxy.conf,并放到/etc/rsyslog.d/下,rsyslog启动时会自动加载此目录下的所有配置文件
[root@haproxy ~]# vim /etc/rsyslog.d/haproxy.conf
if ($programname == 'haproxy' and $syslogseverity-text == 'info')
then -/var/log/haproxy/haproxy-info.log
&~
if ($programname == 'haproxy' and $syslogseverity-text == 'notice')
then -/var/log/haproxy/haproxy-notice.log
&~
这部分配置是将haproxy的info日志记录到/var/log/haproxy/haproxy-info.log下,将notice日志记录到/var/log/haproxy/haproxy-notice.log下。"&~"表示当日志信息写入到日志文件后,rsyslog停止处理这个信息
[root@haproxy ~]# mkdir /var/log/haproxy
[root@haproxy ~]# systemctl restart rsyslog
[root@haproxy ~]# tail -f /var/log/haproxy/haproxy-info.log
[root@haproxy ~]# service haproxy restart
客户端浏览器访问http://192.168.122.10
[root@haproxy ~]# tail -f /var/log/haproxy/haproxy-info.log
Aug 25 03:42:13 haproxy haproxy: /etc/rc.d/init.d/haproxy: 第 26 行:[: =: 期待一元表达式
Aug 25 03:42:13 haproxy haproxy: Shutting down haproxy: [ 确定 ]
Aug 25 03:42:13 haproxy haproxy: /etc/rc.d/init.d/haproxy: 第 26 行:[: =: 期待一元表达式
Aug 25 03:42:13 haproxy haproxy: Starting haproxy: [WARNING] 236/034213 (6151) : parsing [/etc/haproxy/haproxy.cfg:22]: keyword 'redispatch' is deprecated in favor of 'option redispatch', and will not be supported by future versions.
Aug 25 03:42:13 haproxy haproxy: [ 确定 ]
Aug 25 03:47:30 haproxy haproxy[6152]: 192.168.122.222:63528 [25/Aug/2021:03:47:30.274] webcluster webcluster/inst1 0/0/0/1/1 304 179 - - ---- 2/2/0/1/0 0/0 "GET / HTTP/1.1"
Aug 25 03:47:30 haproxy haproxy[6152]: 192.168.122.222:63528 [25/Aug/2021:03:47:30.275] webcluster webcluster/inst2 173/0/1/0/174 304 179 - - ---- 2/2/0/1/0 0/0 "GET / HTTP/1.1"
Aug 25 03:47:30 haproxy haproxy[6152]: 192.168.122.222:63528 [25/Aug/2021:03:47:30.449] webcluster webcluster/inst1 165/0/1/0/166 304 179 - - ---- 2/2/0/1/0 0/0 "GET / HTTP/1.1"
Aug 25 03:47:30 haproxy haproxy[6152]: 192.168.122.222:63528 [25/Aug/2021:03:47:30.616] webcluster webcluster/inst2 158/0/0/0/158 304 179 - - ---- 2/2/0/1/0 0/0 "GET / HTTP/1.1"
原文链接:https://www.cnblogs.com/wang-a/p/15975219.html