负载均衡及其架构原理
写在前面:
架构是一个比较宏观的概念,是控制、管理代码层面实现这一面更好地工作的过程。接下来请先看看几个版本的架构示意图。
单机Tomcat
如上图所示,理论上单个Tomcat并发容量是200~300左右,经过优化后的最多500。虽然单机Tomcat开发部署简单,但出点故障就不行了,例如出现单点故障后应用服务就不可以访问了。
多Tomcat、DNS轮询架构
如上图所示,提供备用11.4 IP,当IP请求来的时候进行IP轮询,第一个请求走12.3,第二个请求走11.4,下一个请求又走12.3依次轮询。这样不仅解决了单点故障的问题,容量也提升了。但还是存在一些缺点,例如:
- 多个Tomcat应用暴露到外网,造成安全隐患,入口不集中。
- 如果其中一个Tomcat挂了,请求的的IP刚好进到坏的Tomcat,还是不可以访问,会导致用户流失。
负载均衡架构
此架构图我们在浏览器和Tomcat之间加了请求分发工具和负载均衡设备。将请求入口集中在nignx下管理,用nignx的反向代理/负载均衡的典型算法,随机将请求分发到不同的Tomcat。外网仅暴露一个接口,而Tomcat没有暴露到外网,上面的所遇到的问题也得到了比较好的解决。但这样的架构离完美无缺还差的很远,因为请求分发、负载均衡的设备只设置了一台,只要存在单台,那么单点故障也会存在。而且这是一个重要节点,负责一切请求,一旦出故障,所有服务不可用。所以就衍生了下一个架构.
负载均衡架构2
双机热备,解决了负载均衡的单机BUG问题。但是对外同一时刻只有一个在服务,一个负责请求,另外一个随时待命,每隔一段时间做一次心跳检测负载均衡是否都存活。假如其中一个挂了,就要把虚拟IP改到另外一个负载均衡设备(Nginx),这样就可以继续提供服务了,体现了高可用性。
这样的架构算是还比较满意,但有存在的缺点:
- 一台工作一台待命,如果其中一挂了另外一台才开始工作,利用低且浪费资源。
- 请求分发设备有流量并发上限。
接下来我们一起来看看一套比较完善的方案
负载均衡架构3
这一套方案是基于双机热备 + DNS轮询,在DNS供应商做些手脚,户输入域名通过浏览器访问DNS服务器,得到一个虚拟IP,通过虚拟IP进入相应的双机热备份,下一个请求来了,就通过轮询,用下一个虚拟IP又进入了另外一个虚拟IP对应的双机热备份。
最后,在实际开发中这一套方案可以承受起几百万的访问量,但还是以实际压力测试和单点故障测试数据为准。单机Tomcat跑一个应用的美好时代一去不复返,但一个成熟的产品一天24小时都要不停机运行。
常见负载均衡设备优缺点及Tomcat压力测试
负载均衡实现方式
硬件方面
F5(硬件设备)实现
优点:非常快,可靠性高,并发量大
缺点:成本高,不方便,最致命的是不能将动态请求和静态请求分离
软件方面
- Linux的LVS(基于Linux系统IP层面的负载均衡)
- 优点:可靠性非常高,简单易用,并发量大
缺点:不能将动态请求和静态请求分离(很少用)
- apache http server
优点:可靠性高,可以动静请求分离
缺点:效率低
- Nginx
简介:这是一种反向代理软件,反响代理:将庞大的Tomcat服务器的IP隐藏,真正在工作的是Nginx(即服务器隐藏了,找了个代理),正向代理:即隐藏用户IP。
优点:非常快,可靠性高并发量大,更重要的是可以实现动态请求和静态请求分离
负载均衡所存在的问题:session ID会发生变化
Nginx动静分离
原理:Nginx 动静分离简单来说就是把动态跟静态请求分开,不能理解成只是单纯的把动态页面和静态页面物理分离。严格意义上说应该是动态请求跟静态请求分开,可以理解成使用Nginx 处理静态页面,Tomcat、 Resin 出来动态页面。
Tomcat压力测试
测试软件:jemeter
步骤:
1.创建一个简单的Servlet工程,打包成war并部署到Tomcat
ServletDemo类
test.jsp
2.下载jemeter
网址:https://jmeter.apache.org/dow... 解压然后bin目录下双击jmeter.bat.
3.添加线程组并填写参数
4.添加Http请求并填写参数
5.添加监听想要查看的选项
6.简单servlet项目测试结果:
图形结果图
察看结果树
聚合报告结果
7.超多条线程演示
测试过程中可以偷偷查看一下任务管理器的数据因为线程数高了有些时候会导致电脑卡顿。
最后来看一下6000条线程下的聚合报告
当线程数很高的时候,Tomcat承受不聊了(受业务影响),其中Error代表错误率,Throughput代表Tomcat的吞吐量。所以说Tomcat承受能力是有限的。
如果有兴趣你可以到的Tomcat安路径下servlet.xml修改一些配置继续测试。当然也可以通过这里进行一些相关优化。
Nginx负载均衡实战
Nginx下载解压
地址:http://nginx.org/ 找stable version版的下载,尽量不要下载最新的
准备两台tomcat
复制Tomcat并修改可以修改的端口(文件在conf的server.xml)。同时分别对应两个Tomcat的学习项目做个标记,比如第一台tomcat访问成功的界面显示“Hello,Tomcat 1 shide ”,第二台同理。这里记录一下我第二台Tomcatserver.xml的端口修改,以防时回查时忘记。
8005→8015
8080→8090
8009→8019
8443→8453
修改nginx的配置文件(nginx.conf)
在文件中添加两个东西
1.
upstream test-service{
server localhost:8080;
server localhost:8090;
}
# upstream表示上游服务器,test-service填的是服务器集群名,这里取test-service。
2.
proxy_pass http://test-service;
# 意思是只有test-service下面的tomcat才能通过我的反向代理。
启动两个Tomcat和Nginx
在浏览器输入上一篇文章的项目访问路径:http://localhost/test_war/test
首先会看到下图情况:
刷新一下结果如下图
发现每刷新一次浏览器Nginx就将请求发送到另一个Tomcat,这体现出了负载均衡的轮询算法。接下来就介绍几种常见的负载均衡算法。
常见负载均衡算法解析
1.轮询 RoundRobin
很公平的原则,即每次过来的请求都会分配到相应的tomcat,大家一次排队各入各的位置。如果没位置了又从头开始。
2.随机算法
通过过一定范围的随机数来分发请求给相应的tomcat.当请求量很大时,接近轮询。
3.源地址哈希
通过请求来源的IP计算相应的hashCode来分发给相应的Tomcat,只要IP不发生变动,请求分发的Tomcat也就固定了。
4.加权轮询
在轮询的基础上增加权重,比如,现在是tomcat1,tomcat2,此时tomcat2加权重4,那么轮询的顺序即tomcat1,tomcat2,tomcat2,tomcat2,tomcat2,tomcat2。
5.加权随机法
跟加权轮询类似一样的做法。比如,tomcat1,tomcat2,此时tomcat2增加权重为4,那么tomcat1,tomcat2,tomcat2,tomcat2,tomcat2,tomcat2,那么tomcat随机分发的时候分发的几率就增大。
6.最小连接数法
根据后端服务器当前的连接情况,动态的选取当前积压连接数最少的一台服务器来处理当前请求。
负载均衡带来的问题
Nginx负载均衡实战回顾,我们采用了轮询以及另外几种常见的负载均衡算法实现了Nginx的效果,接下来我们分别对两个Tomcat稍微改造一下。
操作:在界面上显示session ID
启动Tomcat和nginx并输入路径结果如下图,刷新界面之后会发现请求会分发到另一个tomcat上,sessionId也会发生变化,再刷回到tomcat1的时候sessionId也会发生变化。所以这就出现了sessionId不一致的问题,大部分系统是要求用户登录的,由于session的问题会导致用户登陆之后每一次请求都可能要重新登录,显然用户体验极差!!!
Session共享问题解决方案
方案一:
Tomcat)之间进行session同步
即应用服务器Tomcat之间session同步共享,但是应用服务器本身能力有限,再加session同步会带来网络开销。(具体操作百度:N个tomcat之间实现Session共享)。
方案二:
基于(轮询 和 源地址哈希)算法(适合一般)
要设置ip hash算法(修改Nginx的conf文件:ip_hash ) 请求定位到同一台应用服务器,不切换tomcat。
修改之后重启nginx访问界面,多刷新几遍看看session是否会发生变化?
很显然session没有发生变化,同个浏览器内打开新标签访问路径也是同一个session。这方案虽然解决的session问题,但是不容灾了。因为如果定位到的那台应用服务器挂了,那么用户是无法访问的。
方案三:
外置集中管理session(主流,其实就是类似单点登录)
利用NoSQL数据库、Redis 实现session外置集中管理,将用户每次登录之后的sessionId保存到NoSQL数据库或者Redis中,sessionid是可以标识一个用户的,我们可以用用户的灯登录信息(账号密码、时间戳)生成一个token并设置加密、解密,用户登录之后将token存到tomcat外面,需要用到session的时候就到外置的集中管理中取,为了请求能分发到相应用服务器,从外置集中管理中取token校验即可。这样就解决的session共享问题。
Nginx动静分离
简单理解:动态请求是要访问数据库并进行后端服务操作的,而静态资源(HTML,JavaScript,CSS,img等文件)与后台应用分开部署,提高用户访问静态代码的速度,降低对后台应用访问。
演示演示
项目改造
1.在tomcat1(我这里没有改,把8.5当作是1了)的webappstest_war下创建static文件夹并添加一张图
2.在jsp界面引用这张图片
3.启动tomcat 1并访问效果如下图
4.把静态资源文件放在nginx的html下并修改nginx.conf文件
这里要注意请求的路径必须和tomcat的下面一致
location ~ \.(gif|jpg|jpeg|png|bmp|swf)$ {
root html;
}
然后重启nginx并访问界面还会看到原来的界面。
关于双机热备
刚开始架构图那里所提到的负载均衡的双机热备的存活检测方案其实就是keepalive这个玩意,官网只提供Linux版本的,弄起来还是比较麻烦的,要想深入了解的还是百度咯。
这里贴上心跳检测原理图
主要是中间这个玩意,左右两边的主备nginx设备绑定到同一个Keepalive,Keepalive会根据上游请求的虚拟ip转发给主Nginx,定时检测主Nginx是否存活,否就立马将ip转到备用的Nginx。
理论知识总结
算法篇
1.轮询(默认)
每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。
2.weight
指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。
3.ip_hash
每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题
4.fair(第三方)
按后端服务器的响应时间来分配请求,响应时间短的优先分配。
5.按访问的url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。
四层、七层负载均衡
所谓四层就是基于ip+端口的负载均衡;
七层就是基于URL等应用层信息的负载均衡;
同理,还有基于MAC地址的二层负载均衡和基于IP地址的三层负载均衡;
换句话说,二层负载均衡会通过一个虚拟MAC地址接收请求,然后在分配到真实的MAC地址,三层负载均衡会通过一个虚拟IP地址接收请求,然后再分配到真实的IP地址,四层通过虚拟IP+端口接收请求,然后再分配到真实的服务器;
七层通过虚拟机的URL或主机名接受请求,然后再分配到真实的服务器。
优缺点 :
七层负载均衡也称为“内容交换”,也就是主要通过文中的正真有意义的应用层内容,再加上负载均衡设备设置的服务器选择方式,决定最终选择的内部服务器。
以常见的TCP为例,负载均衡设备如果要根据真正的应用层内容再选择服务器,只能先代理最终的服务器和客户端建立连接(三次握手)后,才可能接收到客户端发送的真正应用层内容的报文,然后再根据报文中的特定字段,再加上负载均衡设备设置的服务器选择方式,,决定最终选择的内部服务器,负载均衡设备在这种情况下,更类似于一个代理服务器,负载均衡和前端的客户端以及以后端的服务器会建立TCP连接,所以从这个技术原理上来看,七层负载均衡对负载均衡的设备要求更高,处理能力、精确率更加友好。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。