网络并发知识第二天高并发负载均衡理论
tomcat为什么并发数少?因为慢,为什么慢?
1、首先因为tomcat是基于7层应用的,也就意味着一次请求从一端到另外一端 :
7层也就意味着,要分别走一遍下面的层,也就是说起码第四层的传输控制层起码要建立3次TCP握手,对资源的生成。 所以在通信上来说,7层是比较慢的
2、tomcat是跑在JVM中的,也就意味着一次请求从内核到用户程序,然后又要到JVM的虚拟程序中,所以tomcat更慢!
所以一般来讲,tomcat的并发数少,我们会开启多个tomcat实例,然后在前方放上一个足够快的中介者(负载均衡器),让它来再转发请求到各个tomcat上
那负载均衡器如何足够快?
直观来想,减少通信层数,层数越少,成本越小。
试想路由器只有三层,因此很快。
而负载均衡器如果是这样的:
基于4层,但严格来说是三层半,不会发生握手的过程,但需要知道端口号,而决定是否要对请求进行转发,因此需要稍微探一探四层的东西(端口号)。
nginx是基于7层的,后端负载的服务器可以是不同业务的,因为它会撕开客户端的7层包拿到url,请求指定后端服务器,官方号称5w并发量
LVS是基于4层的,需要保证后端负载的服务器是镜像的,因为在4层这个层次,只有ip和port,还看不到具体的url,无法根据url进行定向转发。 但并发量可以比nginx高许多
一般企业可能会在最前端使用LVS hold住流量,后续使用nginx hold住握手,nginx再进行转发到对应的tomcat实例
网络通信非对称:一次请求, 往往请求数据量比较小,而服务器响应内容比较大,因此运营商一般会做手脚,一个数据包的发送带宽降低,而把返回时的带宽提高,所以有时会感觉,上传速度很慢,但下载速度很快。
NAT模式
S-NAT
试想一种场景,你在家中,和你的某一个家人在同一路由器(192.168.1.1)下在上网,此时你们两个人同时都想访问百度(8.8.8.8)。
假设你的机器ip是192.168.1.8,他是192.168.1.6。
依照上图,你们的包会被转到路由器上。
而如果你缴费了宽带,运营商会给你分配一个公网ip(6.6.6.6),路由器可以顺着这个ip去跳到运营商对应的网络,然后一跳一跳,跳到目标点。
刚刚描述的在路由器的这部分,实际是存在 本地ip到公网ip的一个转换过程的。
也就是说,在包到了路由器的时候,你的包可能是这样的(假设本地都使用的12121端口):
源本地ip到目标公网ip的包,肯定无法直达,此时需要将本地ip转换成运营商分配的那个公网ip:
可以发现,不但源ip变了。连源端口也变了,这是为啥呢?
因为你试想一下,如果不变动,那么你和你的家人的本地ip,都被转换成公网ip后,成功转发包到百度,然后百度响应回来的时候,问题来了:它还分得清到底应该是给谁的响应吗?
分不清,所以需要路由器记录一个映射表,为每一个请求包在转换公网ip的时候,分配一个新的端口号,那两个包的源本地ip分别被转成公网ip就可以是这样的:
可以看到,端口分别是123,和321
然后表中对应着 端口号和原转换前本地请求包的关系,就像这样:
因此,当响应回来的时候,通过端口号就可以唯一确定,要响应的地方了。
上面的这种,将源ip进行转换的,就叫做 S-NAT ,也就是 source-NAT
D-NAT
说道D-NAT,就可以聊到我们的负载均衡器了
在此之前,我们约定几个术语:
客户端IP叫CIP
负责负载均衡的机器对外有一个虚拟IP,也就是VIP。且其内部有着分别可以与后方真实服务器进行连通的DIP。
后方真实服务器的IP叫RIP,也就是真实IP
我们尝试描述一下一次请求包的过程:
我们的包的格式为 源IP->目标IP
首先client发送一个CIP->VIP的包到负载均衡器上
负载均衡器接受到这个包,会对包进行桥接,改成CIP->RIP的包(这里的把目标地址进行变换的方式,就是D-NAT),然后根据RIP地址发往真实服务器。
真实服务器接受到包开始处理,然后返回响应包,但无法直接将响应包直接发给客户端,因为客户端自身来看,并未向真实服务器发送请求,此时却直接来了一个响应包,此包将会被丢弃。
因此退一步,真实服务器会将RIP->CIP的响应包先返给负载均衡器,然后由负载均衡器再将返回响应包改成 VIP->CIP的
也就是说:客户端的请求和响应都要经过中间的负载均衡器
因此缺点也就比较明显了:
1、请求和相应来回都要经过该负载均衡服务器,它的带宽将成为瓶颈。
2、请求和响应来回的拆包改包改ip,消耗算力。
注意点:
上面提到真实服务器会将RIP->CIP的响应包先返给负载均衡器,但字面上来看,目标IP是CIP,如何再发送到负载均衡器身上呢?
实际上,如果使用这种方式,需要把真实服务器的默认网关设置成负载均衡服务器所在ip地址,这样就可以保证真实服务器发送的响应包都可以流转到负载均衡器上面。
DR(企业常用)
通过NAT模式,我们发现有一个硬伤就是,请求和响应都要经过中间的负载均衡器,且需要进行桥接改ip的过程。
没有对比没有伤害,看看DR模型下是怎么做的:
客户端发送 CIP->VIP的包给负载均衡器,此时负载均衡器不再进行拆包改ip了, 而是直接将CIP->VIP的包发往真实服务器,但要满足这一点,我们需要考虑:
这个CIP->VIP的包如何可以发到真实服务器?
要知道,在负载均衡器中,CIP->VIP这个包,再次发送,VIP指的还是自身服务器,正常来讲,这样直接发是会原地打转的。
解决方案
可以采用mac地址欺骗的方式,回想一个节点到下一个节点的流转,真正依据的还是下一跳的mac地址,因此如果我们可以对mac地址做手脚,让它指向真实服务器的mac地址,那么即使包是CIP->VIP,还是会成功的发到真实服务器。
但是此种方式存在弊端:负载服务器和真实服务器必须保证在一个局域网内,也就是一跳的距离内,因为本次修改的mac地址只能生效于这一跳之内,到下一跳的时候,会重新根据路由表和ARP表计算下一跳。
真实服务器的响应包VIP->CIP如何直接发给客户端?
根据上述,假设成功把包发到了真实服务器中,但此时的真实服务器在处理完请求包后,把构建的响应包回发不想经过中间负载器,而是直接发送一个VIP->CIP的包,则需要在自身机器上额外多一块VIP的网卡,且这个VIP对内可见,对外不可见(不对外暴露)。
对比NAT模式
DR模式相对NAT模式,少了请求包和响应包来回在负载均衡器的拆包的负担,且在发送响应包时可以直接从真实服务器发送到客户端,成本比较低,可以大大提高整体的速度。
TUN隧道技术
上面的DR模型,虽然性能是提上去了,但是对于负载服务器和真实服务器的物理摆放位置比较苛刻,需要处于同一局域网内。
那有没有一种,性能还不错,并且物理条件也不这么苛刻的解决方案呢?
要想解决物理条件问题,应该关注的地方就是在负载服务器中,如何把CIP->VIP的包可以成功的投递给真实服务器。
我们说一说负载均衡器中之前没有被提及的IP,DIP,通过DIP一定是可以使得负载服务器连接的到真实服务器进行正常发包的,那借助这个特点,实际可以这么做:
在DIP->RIP的包中,里面再放一个CIP->VIP的包,这样当包到达真实服务器时,将包撕开,得到CIP->VIP的包,然后其他特征和DR一样,真实服务器中也有一个隐藏的VIP。这样也可以直接由真实服务器发送VIP->CIP的包给客户端了,保证了高效率。
可以看出,这种模式和DR的区别只在于发送CIP->VIP的包的策略上面。