网络高并发负载均衡(一)

LVS的NAT模型推导

Posted by 石福鹏 on 2021-03-09
Estimated Reading Time 12 Minutes
Words 3.4k In Total
Viewed Times

先演示的是一个应用层协议:

把www.baidu.com主页的HTML代码拿下来(不能使用浏览器,也没有wget、cron等)

1
2
3
4
5
6
7
8
cd /proc/$$/fd
exec 8<> /dev/tcp/www.baidu.com/80 //与百度创建了一个通信
echo -e 'GET /HTTP/1.0\n' >& 8
cat <& 8


第一步:建立链接
第二步:传输数据(http协议:规范标准)

一、传输控制层

Socket : 两个Java应用程序可通过一个双向的网络通讯连接实现数据交换,这个双向链路的一端成为一个Socket

先得有tcp建立连接通信,在通信的基础上,才会有用应用层上的协议来传输协议规范的东西,什么是Http,就是规范和约定

image-20210310142731191

浏览器发生之前,先创建一个Socket,然后调用传输控制层,告诉它,我想跟百度去传输数据,你帮我建立连接

在传输控制层就牵扯到了传输协议。

TCP协议、UDP协议

面向连接:发一个,确认一个,这也就是可靠的原因

TCP. (可靠的,效率低)面向连接的可靠的协议(不是两头怼跟网线就连上了,是面向连接的)

是专门设计用于在不可靠的因特网上提供 可靠的 、端对端的字节流通信的协议。他是一种面对连接的协议,TCP连接是字节流而非报文流

UDP(不可靠的,发出去对方收不收到,不关注、效率高)

游戏间的数据传输属于UDP

UDP向应用程序提供了一种发送封装的原始IP数据报的方法、并且发送时无需建立连接。是一种不可靠的连接

面向连接,就又牵扯到了三次握手,四次分手

a、三次握手:

发送想握手服务端回复确认收到 ,(此时客户端两次已经确定了自己的output和input),但是站在服务端的角度,收到了通知,也回复了收到了,但是客户端没有给服务端回复我也确认收到了,这是不行的,所以,这里客户端还需要给服务端也回复说我收到了

三次握手只是在建立链接,只有三次握手成功之后,才会发送数据

b、四次分手:为什么要分手?

建立连接时所需的寻址信息为远程计算机的IP地址和端口号(端口号是为了区分同一台机器上不同的应用程序)

端口号又分为TCP端口、UDP端口,每台机器有65536个TCP端口,65536个UDP端口

Socket中的资源是有限的,这里的资源即端口号

1、客户端发送一个我要个你断开的一个数据包

2、服务端回复说我收到了

3、服务端告知客户端我也想断开连接

4、客户端回复说,我也收到了

此时,内存资源销毁释放

注意:上面的图,并不是说在传输层上来回传输,其实每一次握手,每一次挥手都是从传输控制层到网络层、链路层、物理层。。。。。来回传输的

“三次握手->数据传输->四次分手” 这个称谓一个最小的粒度,不可被分割

1
netstat -a

image-20210304151202963

socket就是一个个的ip+port

image-20210304152145120


二、网络层 (路由判定)

传输的数据包要怎么发出去

基础知识:

image-20210304172305438

IPADDR:IP地址,标识网络中的每一个节点的地址

NETMASK: 掩码

IP地址叫做点分字节,点隔开的是一个字节,每个字节8个二进制位,8个二进制位从全0到全1,表示的10进制数的范围即0~255

拿着IP和掩码会发生二进制的按位与运算,可以得出网络号

比如上面的例子:拿着上面的掩码和ip地址做& 运算,255即8个1,所以当255和172(或其他数)做与运算,结果肯定是172或者其他数;

0(二进制全是0)与其他数做与运算,结果肯定是0;所以与运算后结果为:172.16.196.0;172.16.196.0即为网络号,ip最后一位200即主机位

a、网关是什么?

每一层都有一张表,在网络层也有一张表,叫做路由表

1
2
3
4
5
6
7
8
[root@hadoop01 ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 172.16.197.1 0.0.0.0 UG 100 0 0 ens33
172.16.197.0 0.0.0.0 255.255.255.0 U 100 0 0 ens33
[root@hadoop01 ~]#


路由表是动态生成的,也可以手动修改

上面的路由表其实就是由网卡接口的配置文件生成的,比如第一行,其实就是拿IP地址和子网掩码做与运算生成的

网络层是下一跳(下一个跳跃点)机制 :通过路由表做路由判定(按位与)

如果现在ping百度

image-20210305173457866

这里把百度域名转化成了一个地址,这个地址是104.193.88.77,拿着这个地址与上面的路由表的每一个条目上做一次按位与运算,就可以找到下一跳

1
2
3
4
5
6
7
8
9
10
	104.193.88.77
& 255.255.255.0
------------------
104.193.88.0 跟目标Destination匹配不上

104.193.88.77
& 0.0.0.0
--------------
0.0.0.0 跟目标Destination匹配上了,从而从这条记录即可知道下一条的地址172.16.197.1 ,即默认网关

数据包想出这个局域网,需要先走这个网关,即将数据包先发到路由器,由路由器再去通过自己的路由表中的网关继续找下一跳

同一局域网之间的通信不需要下一条(通过交换机就可以转发数据包了),网与网之间才需要路由器做下一条做转发的操作,所以Genmask为0.0.0.0

所以当看到Genmask为0.0.0.0,我们就知道当前设备在这个局域网中有一个具体的IP,,如果看到了Genmask不为0.0.0.0了,那么这么目标网络一定不是直连的

1
在路由器上配置静态或动态路由之前,路由器只知道与自己直连的网络。这些网络是在配置静态或动态路由之前唯一显示在路由表中的网络。直连网络对于路由决定起着重要作用。如果路由器没有直连网络,也就不会有静态和动态路由的存在。如果路由器接口未启用 IP 地址和子网掩码,路由器就不能从该接口将数据包发送出去,正如在以太网接口未配置 IP 地址和子网掩码的情况下,PC 也不能将 IP 数据包从该接口发送出去

那数据包怎么发给百度呢?这就是下一层要做的事情了


三、链路层

链路层的通信地址,网卡地址(MAC地址)

链路层的表:

1
2
3
4
[root@hadoop01 ~]# arp -a
gateway (172.16.197.1) at 3e:22:fb:15:65:64 [ether] on ens33
[root@hadoop01 ~]#

什么叫arp:DNS解析域名和IP地址的映射,arp会解释ip和网卡硬件地址的映射表

从上面表发现,根据下一跳地址172.16.197.1可以看出网卡地址(MAC)地址3e:22:fb:15:65:64;

链路层结束后会封一个数据包,里面会有三个地址,最外层是链路层的MAC地址(即下一跳点给谁), 再往里层是这个包里面的目标地址最终给谁,最里层是最终的目标的端口号,这三个地址确定了,从主机出去最终给哪个设备;

image-20210306193215186

结论:

TCP/IP协议:基于下一跳机制

IP是端点间(定义的是最终的两个端的)

MAC地址是节点间的

a、如何获知对方的MAC地址?

A和B通信,A是什么时候获取到B所在网络的那块网卡的MAC地址的?

网络层封装源IP和目标IP;数据链路层封装源MAC地址,同时想要封装目的MAC地址但是无法通过目的IP获取目的MAC,此时ARP上场

ARP的工作机制会产生ARP请求去解析目的地MAC地址,此时第一波目的MAC是全F(表示所有mac地址),数据包到达本网段的所有设备,拆去封装后,需要用响应的目的ip解析ARP数据包,此时目的IP对不上的直接丢弃ARP请求包,目的IP正确的返回一个响应,并把自己的mac地址发过去,有了目的MAC地址后,将目的MAC和源MAC一起封装到数据包中,开始进行数据传输


负载均衡

一般来说,想解决高并发的话,核心思想就是,一个吼不住,那就多个,比如一个tomcat扛不住,那就变成3个,如果客户端30个并发,那么每个分配10个,但是通信不是靠域名通信的,通信是靠IP通信的,那么比如说请求的是百度,那么百度的Ip地址要配给前面三天服务器的谁呢?

同一网络当中,IP地址不能重复出现

那么该怎么解决呢?

如果中间有一个设备,可以快速(足够快)把所有的请求分发给后面的三台设备,就可以解决高并发

Tomcat 并发少,因为它是一个应用层的,处于通讯层次中最末端的层次,并且都需要建立三次握手等流程

如果有一个设备,当收到请求后,直接转发,不走四层 、不走七层,不走握手

注意:这里不要当成反向代理,反向代理是客户端跟反向代理握手了,然后反向代理把数据再转给目标

所以我们得出结论,如果想解决高并发,想解决负载均衡的话,就通信这个层次而言,客户端的程序数据包发来之后,如果有一个设备(负载均衡服务器),但是这个设备不能和客户端做一个握手链接,而是客户端直接和服务器做握手链接,相当于负载均衡服务器知道了三层路由器这个层次(即下图中的第三列),还没到四层,但是因为要获取IP端口号决定如何做转发,所以是到传输控制层,但又仅限于获取IP和端口号,所以勉强四层

image-20210308221828869

下面两张图即为推导出的负载均衡拓扑图:

image-20210308223146578

image-20210308224508817

客户端永远只认负载均衡服务器的IP;

假如通过VIp负载均衡分发给RIP,RIP会处理发过来的数据包嘛?不会,因为数据包中有客户端的IP,负载均衡服务器的VIP,唯独没有RIP,所以这个数据包就会被丢弃掉

例子:家里是如何上网的

image-20210308230112788

假如家里的两台设备分别是192.168.1.8、192.168.1.6,端口号都是12121,单独看一台设备,192.168.1.8:12121,将数据包发送给路由器,这个时候路由器将IP替换成公网IP即6.6.6.6:11212,然后请求到百度,百度返回数据到路由器,路由器再转回局域网Ip,这样看似是没有问题的

但是如果两台设备同时访问百度,那么到路由器的时候,ip+端口号都被替换成6.6.6.6:12121,发送数据包给百度,百度返回之后,到路由器,路由器怎么识别要把两个数据包分别对应给谁呢,所以其实再两个客户端访问百度的时候,请求数据包到路由器的时候,路由器会分配给每个请求一个端口号,比如说:客户端1位123,服务端位321,替换后即6.6.6.6:123、6.6.6.6:321,那么这样请求响应都是OK了

其中,路由器这里修改的IP修改的是源IP,即S-NAT(source)

再回到上面负载均衡,那CIP的数据包怎么到达RIP且被处理呢?根据上面的例子,我们得到启发,我们需要将CIP转化成RIP,即目标地址转换(D_NAT),同理,RIP响应之后,数据会直接扔到CIP(RIP->CIP)嘛?肯定不会,因为对于CIP来说,携带数据包是从CIP到VIP的,他不认识RIP,所以数据包再返回到负载均衡服务器的时候,需要做一次反地址转换,即VIP转化成CIP。

最终:

image-20210309164303228

这里需要注意的一点是,由于NAT模式是有Real-server接收到数据包后,再将数据返回到负载均衡服务器,再返回给客户端,这就要求Real-server服务器的网管需要指向到负载均衡的服务器

缺点:

从客户端到服务端,再从服务端回到客户端,中间经过负载均衡服务器,它是有瓶颈的:

即非对称

发出去东西很少,但是返回来的很多,但是来去都要经过负载均衡服务器,所以负载均衡服务器的带宽成为瓶颈,消耗算力(计算机的计算能力)


附:七层的负载均衡

七层的负载均衡(响应肯定是走负载均衡服务器的)

image-20210311140927864


如果您喜欢此博客或发现它对您有用,则欢迎对此发表评论。 也欢迎您共享此博客,以便更多人可以参与。 如果博客中使用的图像侵犯了您的版权,请与作者联系以将其删除。 谢谢 !