深入浅出Web应用负载均衡
原始模式
假设我们有一个java开发的系统A,我们将其部署在一台服务器上,在初期用户量不大的情况下,单机跑着没有任何问题,当用户量越来越大,系统出现大量的并发直接将系统搞挂掉的情况。这个时候我们可能会将服务器的配置升级,但是过一段时间用户量更大了,最后大量的并发还是把系统搞挂了。我们除了提升服务器配置的解决方案还有没有其他的解决方案呢?答案肯定是有。一台服务器处理不过来我们是不是可以让N台服务器来处理呢?这个时候我们就要请出我们第一位大神nginx。
Nginx+Tomcat模式
介绍nginx是什么?
Nginx(“engine x”)是一款是由俄罗斯的程序设计师Igor Sysoev所开发高性能的反向代理服务器。
为什么使用nginx可以解决
从上面介绍我们可以了解到nginx是一款高性能的反向代理服务器(当然也可以作为web服务器);可能有人不清楚反向代理服务器是啥意思,我们通过下面一张图来解释一下:
从上图我们可以看出nginx服务器对于客户端而言就像是原始服务器,并且客户端不需要做特殊设置。客户端向反向代理服务器(nginx)发送普通请求,接着反向代理服务器(nginx)将判断向何处转交请求,并将获得的内容返回给客户端。
那有反向代理,是不是就有正向代理呢?答案肯定是有的比如翻墙软件。
搭建Nginx+Tomcat
环境准备
-
Nginx服务器:192.168.56.107
-
应用服务器:192.168.56.108/109
tomcat安装
-
下载tomcat(默认机器已经安装了jdk)
cd /usr/local/ # 由于Apache官网网站下载比较慢,这边使用阿里云镜像来下载 wget https://mirrors.aliyun.com/apache/tomcat/tomcat-9/v9.0.35/bin/apache-tomcat-9.0.35.tar.gz #解压 tar -xvf apache-tomcat-9.0.35.tar.gz rm -rf apache-tomcat-9.0.35.tar.gz #进入安装目录并启动 cd /usr/local/apache-tomcat-9.0.35 ./startup.sh #查看是否正常启动 ps -ef | grep tomcat #修改index.jsp,便于区分访问到那一台服务器,实际环境两台的内容绝对要一致 cd /usr/local/apache-tomcat-9.0.35/webapps/ROOT vi index.jsp
-
验证安装是否成功,访问http://192.168.56.108:8080/
- 同样的方法安装109服务器,http://192.168.56.109:8080/结果如下:
安装nginx(使用yum安装)
-
新增nginx官网的yum安装源
rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
-
安装nginx
yum install -y nginx
-
启动Nginx并设置开机自动运行
systemctl start nginx.service systemctl enable nginx.service
-
安装完成成,在测试之前需要确认是否开着防火墙,如果开着防火墙则关闭防火墙或者开放80端口
-
方式一:关闭防火墙
#1、先检查防火墙是否开着 systemctl status firewalld.service #2、如果开着则先 停掉防火墙 systemctl stop firewalld.service #3、将防火墙服务禁止掉 systemctl disable firewalld.service
-
方式二:开放端口
firewall-cmd --zone=public --add-port=80/tcp --permanent firewall-cmd --reload
-
-
配置nginx
cd /etc/nginx/conf.d #将原来默认文件重命名一下 mv default.conf test.conf #修改配置文件的内容,将没用的内容删除掉,只保留一下内容 server { listen 80; server_name localhost; location / { proxy_pass http://tomcatserver; } } #从以上配置文件我们可以看到我们代理的服务器使用了tomcatserver,所以我们要nginx.conf配置文件中配置对应的upstream,我们这边使用一个配置文件来专门放upstream cd /etc/nginx/ vi upstream.conf #在配置文件添加一下内容 upstream tomcatserver { server 192.168.56.108:8080; server 192.168.56.109:8080; } #将upstream.conf配置文件引入到nginx.conf vi nginx.conf #引入upstream.conf http { #此处省去了默认的配置 #引入upstream.conf include /etc/nginx/upstream.conf; include /etc/nginx/conf.d/*.conf; } #重新加载配置文件 nginx -t nginx -s reload
-
验证是否成功,访问http://192.168.56.107/,访问结果如下:
因为nginx默认的负载策略是随机,所以可能要多刷新几次才会切换到另外一台应用服务器。目前为止我们已经通过nginx作为负载均衡服务器实现了应用的集群部署。但是假如说我们的并发量还是不断的在增长,这样单机的nginx也会到达瓶颈的时候(好像是支持5W并发,本人没有校验)。如果真的出现这么高的并发数我们有没有别的方案来解决nginx瓶颈的问题呢?答案肯定是有,这个时候我们清楚第二位大神LVS,下面我们就来看看LVS如何解决。
LVS+Nginx+Tomcat模式
介绍LVS是什么?
LVS是Linux Virtual Server的简写,意即Linux虚拟服务器,是一个虚拟的服务器集群系统。本项目在1998年5月由章文嵩博士成立,是中国国内最早出现的自由软件项目之一。在linux内存2.6中,它已经成为内核的一部分。
LVS工作在网络层,有非常高的性能,同时其廉价,可以将性能一般服务器组合在一起形成一个超级服务器群。它稳定可靠,即使在集群中某个节点无法正常工作,也不影响整体效果。当应用服务器性能撑不住的时候只要横向增加应用服务器部署即可,扩展性也非常好。
疑问:LVS干的事情不是跟nginx一样吗?如果说LVS性能好的话,那直接使用LVS就好了,干嘛要用nginx呢?我先看下nginx和LVS对比
LVS VS Nginx
LVS优缺点
优点
- 高性能:工作方式简单并且工作在网络层,不参与客户端三次握手过程,只负责数据包转发,所以工作效率上可以想象的高。
- 高稳定:LVS几乎不会出现故障,除非机器本身的内存或者CPU出现故障。
- 配置可选性少,所以不需要有人经常去修改配置,大大减少了人为出错的几率。
缺点
- 配置可选性少:什么鬼,上面不是说这是优点吗?很多时候在特定的情况下优点就可能成为缺点。为什么这么说呢,正因为LVS配置可选性少,所以配置的可选择性相比nginx就少非常多
- 不对结果负责:正是LVS工作原理他只负责数据包的转发,但是不会对响应结果负责。
nginx优缺点
优点
- 工作在应用层,所以针对HTTP请求有丰富的分发策略,比如针对域名、静态资源等。相比之下LVS这方面是不具备的。
- Nginx对网络依赖性比较小,理论上能ping通就就能进行负载功能,相反LVS对网络稳定性依赖比较大,同时LVS整个工作过程中需要用到虚拟IP,作为相应的运维人员就必须有更高的要求;
- 高性能:nginx具有非常高的性能和稳定性,只是相对于LVS会差上一些。
总结
从上面的对比我们可以得出最核心的结论:LVS相对于比Nginx具备更高的性能,但是配置方面没有nginx来的灵活。所以我们为什么不能利用量二者的长处一起来解决我们的问题呢?对没错,我们利用LVS的高性能、高稳定性让其第一层处理来自客户的高并发,然后转发到nginx,再利用nginx灵活的分发策略分发到应用服务器。下图为改进版的系统部署结构图。
细心的同学可能会问,不对啊,为什么client到LVS以及到Nginx怎么是单箭头的?因为当我们采用DR模式的时候,响应式是直接由nginx层直接响应给client端的。
LVS+Nginx+Tomcat环境搭建(DR模式)
环境准备
- Nginx服务器:192.168.56.106/107
- 应用服务器:192.168.56.108/109
- LVS服务器:192.168.56.105
- 虚拟IP:192.168.56.200
Nginx与tomcat我们上面已经安装过了,这边就不多做说明。
LVS环境安装与配置
-
LVS服务器安装
ipvsadm
因为linux本身自带LVS模块,所以我们不需要安装。不过我们需要安装一个管理工具
ipvsadm
yum install ipvsadm #使用查看我们是否安装成功,也可以该命令查看当前的当前连接情况 ipvsadm -Ln
-
LVS服务器配置虚拟ip
192.168.56.200
ifconfig enp0s8:1 192.168.56.200/24
-
LVS服务器配置LVS
# 为ipvs虚拟服务器添加一个虚拟服务 ipvsadm -A -t 192.168.56.200:80 -s rr # 为虚拟服务添加一个real server(RS) -g为使用网关(即直接路由),此模式是默认模式;-w 设置每个节点的权重 ipvsadm -a -t 192.168.56.200:80 -r 192.168.56.106 -g -w 1 ipvsadm -a -t 192.168.56.200:80 -r 192.168.56.107 -g -w 1
-
使用
ipvsadm -Ln
查看下当前连接情况:[root@localhost ~]# ipvsadm -ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.56.200:80 rr -> 192.168.56.106:80 Route 1 0 0 -> 192.168.56.107:80 Route 1 0 0
nginx服务器(192.168.56.106/107)配置
-
配置虚拟ip
cd /etc/sysconfig/network-scripts cp ifcfg-lo ifcfg-lo:1 vi ifcfg-lo:1
将ifcfg-lo:1改成:
DEVICE=lo IPADDR=192.168.56.200 NETMASK=255.255.255.255 NETWORK=127.0.0.0 # If you're having problems with gated making 127.0.0.0/8 a martian, # you can change this to something else (255.255.255.255, for example) BROADCAST=127.255.255.255 ONBOOT=yes NAME=loopback
重启网络服务:
service network restart
-
修改Linux内核参数
net.ipv4.conf.all.arp_ignore = 1 net.ipv4.conf.default.arp_ignore = 1 net.ipv4.conf.lo.arp_ignore = 1 net.ipv4.conf.all.arp_announce = 2 net.ipv4.conf.default.arp_announce = 2 net.ipv4.conf.lo.arp_announce = 2
-
重新刷新sysctl.conf,
sysctl -p
,这个时候我们可以看到如下结果:sysctl -p net.ipv4.conf.all.arp_ignore = 1 net.ipv4.conf.default.arp_ignore = 1 net.ipv4.conf.lo.arp_ignore = 1 net.ipv4.conf.all.arp_announce = 2 net.ipv4.conf.default.arp_announce = 2 net.ipv4.conf.lo.arp_announce = 2
验证
- 访问http://192.168.56.200/
-
使用命令行验证
-
疯狂刷新http://192.168.56.200/页面,验证客户端的连接都发送到哪里?
我们在LVS服务器上执行
netstat -natp | grep 192.168.56.200
命令,这个时候我们可以看到没有一个客户端请求连接在这台机器,这个也证明了LVS不会跟客户端进行握手。 -
我们再去nginx的服务器上看下客户端连接情况
106服务器:
107服务器:
-
我们再去LVS服务器上查看LVS的偷窥记录
上图我们可以看出LVS实际上偷偷的记录所有经过的他的请求
总结
目前我们已经完成了LVS+Nginx(2台)+tomcat(2台)环境搭建,是不是很爽O(∩_∩)O哈哈~。
这个时候可能有同学会问,如果单机的LVS宕机了怎么办?确实有这样的可能,不管LVS再稳定或者服务器多么的稳定,真的哪天这台服务器抽风了岂不是整个系统不可用了。这个时候要请出我们的第三位大神keepalived
-
LVS的高可用
keepalived是什么?
Keepalived的作用是检测服务器的状态,如果有一台web服务器宕机,或工作出现故障,Keepalived将检测到,并将有故障的服务器从系统中剔除,同时使用其他服务器代替该服务器的工作,当服务器工作正常后Keepalived自动将服务器加入到服务器群中,这些工作全部自动完成,不需要人工干涉,需要人工做的只是修复故障的服务器。
从以上描述看,这正不是我们想要的东西吗,我们可以部署两个LVS,当一台挂掉的情况下,另外一台接盘,是不是很完美。
keepalived+LVS环境搭建
环境准备
- Nginx服务器:192.168.56.106/107
- 应用服务器:192.168.56.108/109
- LVS服务器:192.168.56.104/105
- 虚拟IP:192.168.56.200
Nginx、LVS、tomcat我们上面已经安装过了,这边就不多做说明。
LVS配置修改
-
104服务器安装LVS,与上文安装方式一样,不过不需要配置虚拟IP
-
105服务器将200的虚拟ip down掉
ifconfig enp0s8:1 down
因为keepalived+LVS本身就支持虚拟IP,所以我们不需要额外新增虚拟ip
安装keepalived
-
安装keepalived(使用yum安装)
yum install -y curl gcc openssl-devel libnl3-devel net-snmp-devel yum install -y keepalived
-
启动keepalived并设置成开启启动
#启动keepalived systemctl start keepalived #加入开机启动keepalived systemctl enable keepalived #重新启动keepalived systemctl restart keepalived #查看keepalived状态 systemctl status keepalived
-
配置keepalived
#到keepalived安装目录并修改配置文件 cd /etc/keepalived #找到 keepalived.conf配置文件并修改配置文件,将配置修改成如下:
keepalived.conf
! Configuration File for keepalived global_defs { #指定router_id的名字 router_id LVS_104 } vrrp_instance VI_1 { #指定当前节点为MASTER还BACKUP state MASTER #指定网卡的名称,大家根据自己的网卡名称来设置 interface enp0s8 # 指定虚拟路由ID名称 virtual_router_id 104 # 指定当前节点的优先级 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111 } # 配置虚拟IP virtual_ipaddress { 192.168.56.200 } } #配置虚拟IP与真实IP的转发规则 virtual_server 192.168.56.200 80 { #健康检查时间,单位:秒 delay_loop 6 #配置负载均衡算法,默认是轮询 lb_algo rr #配置LVS的模式 NAT/TUN/DR lb_kind DR #设置持久化时间,默认50秒 persistence_timeout 50 #默认的协议 protocol TCP #配置真实服务器的地址IP real_server 192.168.56.107 80 { #设置每台机器的权重配比 weight 1 #设置健康检查 TCP_CHECK { #连接端口 80 connect_port 80 #设置检查的超时时间 connect_timeout 2 #重试的次数 5次 nb_get_retry 5 #间隔时间 3S delay_before_retry 3 } } real_server 192.168.56.106 80 { #设置每台机器的权重配比 weight 1 #设置健康检查 TCP_CHECK { #连接端口 80 connect_port 80 #设置检查的超时时间 connect_timeout 2 #重试的次数 5次 nb_get_retry 5 #间隔时间 3S delay_before_retry 3 } } }
验证
-
验证56.104服务器是不是master,我们通过
ip addr
来查看当前200的虚拟是否在这台机器上我们再看下105服务器:
-
主备切换:我们把104服务器的keepalived停掉(
systemctl stop keepalived
),看看系统是否可以正常访问,再使用ip addr查看虚拟ip情况- 首先页面没有任何问题
-
其次我们看下200虚拟ip在哪台服务器,从下图我们可以看出虚拟ip已经漂移到105服务器了
我们已经完成了所有的验证,这样的结构下我们不管是LVS还是Nginx以及tomcat都可以实现高可用,也可以实现灵活的横向扩展
思考
我们思考一个问题:104和105互为主备,那是不是意味着104不挂的情况下105服务器就浪费在那边了呢?好像是这么一回事,那有没有办法让104和105两台机器都利用起来呢?答案是肯定是有的,那就是让104和105互为主备,不过这样需要两个虚拟ip,我们可以通过DNS轮询来实现当客户访问我们网站的时候分到不同的虚拟IP上。由于个人电脑没有这样的环境,这边就不给大家演示了。
好了,到目前为止我们已经完成了从tomcat单机到keepalived+LVS+Nginx+tomcat高可用部署方案介绍了,欢迎大家拍砖。