高并发负载均衡:网络协议原理

想要分流实现高并发处理,需要转发到A、B、C服务器上,如何转发,需要了解网络协议原理!转发分七层协议、四层协议、二层协议,这里我们猜到了二层协议最快的事情,所消耗的资源是最小的。那么怎么去实现呢?所以,需要去了解网络协议。网络协议七层。

流程图

image-20210428143834325

模拟网络请求

进入本机文件

1
cd /proc/$$/fd

image-20210428143957786

会有一些文件,0–>输入,1–>输出,2–>报错

我们和百度建立socket连接,要知道,必须由链接才能访问

1
exec 8<> /dev/tcp/www.baidu.com/80

image-20210428144411043

关闭socket连接

1
exec 8<& -

开始通过协议请求,任何的请求必须要有协议,什么是协议,是规范

1
echo -e 'GET / HTTP/1.0\n' >& 8

有request就有response,我们查看response

1
cat 0<& 8

image-20210428145746702

下面的东西就不展示了,就是html,上面是就是应用层http协议。

解释网络层

应用层:主要指浏览器或者tomcat容器,就是用户层。tomcat把表示层和会话层都放在了应用层。

表示层:用户层

会话层:用户层,可记录用户信息,比如session

传输控制层:分为两个协议:tcp、udp协议,其中tcp协议是一个安全的协议,面向连接的,可靠的协议,udp反之不可靠。tcp经典三次握手、四次挥手。

  • 三次握手:A客户端向B客户端发送一个握手包,B客户端给A客户端回复确认包,A客户端收到确认包后给B客户端回个收到包。然后开始传输数据
  • 四次挥手:A客户端给B客户端发个分手包,B客户端回个收到包,B客户端同样发个分手包,A客户端收到回个收到包,开始断开连接。

上面使用一些包的名词,是我自己定义的,反正就是包。上面总结就是,三次握手之后,才能传输数据,想要断开连接,必须四次分手,这个是最小粒度,不可被分割。

网络层:上面发送握手包,也是要往下走,经历网络层,要知道请求到哪个网络啊?经过路由,就是到需要请求到哪个网络,网络层就是干这个事情的。那么需要普及点知识

  • ip地址:就是标识网路节点的id号或者坐标
  • 掩码:255.255.255.0。和ip地址【与】作用,辟如:和192.168.188.100做与运算,就是192.168.188.0,然后在去路由表做匹配,看哪个能匹配上。下面匹配到192.168.188.0那么匹配上的网关的0.0.0.0,就是局域网的意思。这个就是下一跳地址。具体看下面。

image-20210428160327179

  • 下一跳机制:没办法直接设置需要路由的ip地址,因为太多,所以,需要下一跳机制,把非局域网的ip,转发到网关。然后开始走链路层

链路层:下一跳转发到ip后,链路层会包装一层,把链接的ip Mac地址拿出来包装三层。就Mac地址点对点的跳跃。

  • 第一层:源端口号->目标端口号
  • 第二层:源ip->目标ip
  • 第三层:源mac地址->目标mac地址

那么mac地址如何获取,首先,遵循的是arp协议,我们网关的mac地址是已知的,需要知道,通过广播假如说广播到路由,确定目标ip是路由器ip,那么就可以获取到mac地址,这样其实就学习到了mac地址,记录下来,下次就直接发送。

假如,通过mac地址跳到路由器,通过路由器的路由表来进行匹配。如果

物理层:顾名思义

挖槽,上面概念属实空泛,太绕人了,我们做个试验

arp协议

ARP协议是什么

我们并不知道我们想要跳转的ip地址的mac地址是什么,于是,我们会先封装数据,广播给各个网口,目标ip收到我们发的包的时候,同时会回一个包,我们就知道目标地址的mac地址。

举例:

试验环境,两台服务器

name ip
node01 192.168.188.180
node02 192.168.188.181

node01想要跳转到node02,需要mac地址,不知道node02的mac地址怎么办。封装一个包:

  • 源mac地址->node01@mac
  • 源ip node01
  • 目标mac地址 FFFFFFF
  • 目标ip node02

交换机,拿到这个包,发现目标mac地址是FFFFFFF,就会在各个网口进行一次广播,有的机器可以看到不是自己的就丢弃,假如一个路由看到目标ip是自己了,自己拿到这个包,会在封装一个包:

  • 源mac地址->node02@mac
  • 源ip node02
  • 目标mac地址 ->node01@mac
  • 目标ip node01

没错,反过来了,因为我们要给回一个包啊。这里有个细节是,node02会包的时候,因为交换机会在node01发送包的时候,把node01的mac地址记录下来,那么当node02回包的时候,交换机直接就拿到node01的mac地址,直接跳转到node01。同样的,node01收到node02的mac地址,也会把node02的mac地址记录下来,这个就是arp协议。

实例测试

试验环境,两台服务器

name ip
node01 192.168.188.180
node02 192.168.188.181

我们在node01新建个虚拟网卡ip

1
ifconfig ens33:1 192.168.88.100/24

我们用node02去ping 192.168.88.100时候能ping通吗?

image-20210428171325760

肯定ping不通,为什么呢?根据上面需要的知识,我们查看node02的路由表

image-20210428170931395

发现他只能是走192,.168.188.2这个网关出去,而192.168.188.2这个网关没有192.168.88.100信息,肯定会跑丢,那么我们需要新建个路由,把192.168.88.100路由到192.168.188.180这个服务器上

1
route add -host 192.168.88.100 gw 192.168.188.180

image-20210428171411239

然后ping下自然是能ping通的

image-20210428171543761

浅显的看是根据路由转发,深点看就是

  • 通过ip匹配路由,找到网关
  • 链路层:根据网关找到mac地址
  • 链路层:根据mac地址跳具体的ip,点对点的关系
  • 跳到具体的ip,继续通过路由匹配ip,还没匹配到具体的ip,那么继续网关转发,继续mac跳

总结发送

上面一切都ok后,我们源mac地址 ip 目标mac地址 ip都知道了,就可以发送包了,只需要封装一个包:

  • 源mac地址->目标mac地址
  • 源ip->目标ip
  • 源端口号->目标端口号

上面就是全部网络的环节

LVS的DR,TUN,NAT模型推导

这里就是负载均衡服务器的模型推到,通过我们的网络知识。通过上面的网络知识,我们可以推导出来,我们在网络层动手,收到一个数据包,看到目标端口是,要转发的端口,就可以把ip任意替换成要负载的ip就可以,然后在发出去。

image-20210428232636243

试验环境,两台服务器

name ip 作用
client01 192.168.188.11 客户端ip 01
client02 192.168.188.12 客户端ip 02
node01 192.168.188.180 负载均衡服务器
node02 192.168.188.181 具体的、需要转发的服务1
node02 192.168.188.182 具体的、需要转发的服务2
route 192.168.188.2 路由器
route-r 6.6.6.6 路由器外网通信的ip

NAT网络模型推导R-NAT

第一步:

我们假设client01上网,访问百度,这里假设百度ip是8.8.8.8,那么client01,扔给路由器,但是我们不知道路由器的mac地址啊,要进行一次arp,发送arp数据包

  • 源mac地址->client01@mac
  • 源ip:端口 client01
  • 目标mac地址 FFFFFFF
  • 目标ip:端口 route

第二步:

交换机经过广播,路由器看到是自己的目标ip包,然后直接回一个包

  • 源mac地址->route@mac
  • 源ip:端口 route
  • 目标mac地址 client01@mac
  • 目标ip:端口 client01

第三步:

client01拿到路由器的mac后,直接发送数据包到路由器,链路层通过mac地址直接跳到路由器

  • 源mac地址->client01@mac
  • 源ip:端口 client01
  • 目标mac地址 route@mac
  • 目标ip:端口 8.8.8.8

第四步:

路由器拿到包后,同样路由一次,因为百度是8.8.8.8,并非路由器的内网,还是走路由器的网关,就是route-r,路由器访问外网的ip,我们封装个包,这里会同样的需要拿到百度ip的mac地址

  • 源mac地址->6.6.6.6@mac
  • 源ip:端口 6.6.6.6
  • 目标mac地址 FFFFFFF
  • 目标ip:端口 8.8.8.8

第五步:

拿到百度的mac地址后直接通过链路层跳到百度服务器,封个包发送过去

  • 源mac地址->6.6.6.6@mac
  • 源ip:端口 6.6.6.6
  • 目标mac地址 8.8.8.8@mac
  • 目标ip:端口 8.8.8.8

这里有一个细节,路由器也会有一个表,记录什么呢?记录接收的包要转发出去的端口号和我要发送的包的绑定,不然我怎么知道我收到的这个包是要回给哪个ip啊。所以路由器也有一个点。

这种是Nat模式,这个Nat模式是R-Nat,不改变目标ip

NAT网络模型推导D-NAT

通过上面的流程,我们发现需要ip跳ip,那么需要目标的mac地址,所以D-NAT只需需要把目标ip变成我需要转发的ip就ok的

image-20210507141307036

下面是简单的说明

  • CIP–>VIP
  • VIP替换数据包,就是DIP–>RIP
  • RIP处理完毕后,回一个包,就是RIP–>DIP
  • VIP在回个包,VIP–>CIP

就是替换目标ip。这个是为了负载均衡

DR网络模型推导

我们不希望RIP在回包的时候,还经过VIP,所以,需要RIP配置一个

image-20210507144607545

DR模型的核心点是,在链路层的mac地址,是RIP的mac地址,直接跳到RIP,那么就算我们如何得到RIP的MAC地址呢?我们需要RIP里有一个VIP,因为目标ip是VIP,只需要在RIP设置个隐藏的ip,就是VIP,对外隐藏,对内可见。一定是对外隐藏,不然ip冲突。所以,得到一个结论,负载和RIP一直在同一局域网下。

TUN网络模型推导

隧道技术,就是要访问的ip被包装下,CIP->VIP 被DIP->RIP包装,DIP->RIP不断的跳,跳到RIP后,撕毁包装,就是真的ip CIP->VIP

image-20210507152244603

LVS的DR模型搭建

DR模型的点是什么?RIP的VIP隐藏!因为DR换的是mac地址,目标ip是不换的,我们需要直接路由到RIP

RIP上隐藏VIP

需要对外隐藏,对内可见,既然我们需要在RIP设置一个虚拟的VIP,并且不希望他被公布出来,所以,需要设置内核网络协议arp配置。

具体路径:

1
/proc/sys/net/ipv4/conf/*IF*

这里需要修改两个配置:

  • arp_ignore:定义收到arp收到的请求级别,默认为0
    • 0:只要本地配置有相应的地址,就给与响应
    • 1:仅在请求的目标(MAC)地址配置请求到达接口上的时候,才会给予响应
  • arp_announce:定义将自己地址向外通告的级别,默认为0
    • 0:将本地任何接口上任何地址向外通告
    • 1:试图仅向目标网络通告与其网络地址匹配
    • 2:仅向与本地接口上的地址匹配的网络进行通道

VIP安装lvs:

1
yum -y install ipvsadm

开始配置

node01设置VIP,是虚拟网卡

1
ifconfig ens33:1 192.168.188.100/24

image-20210507161203570

node02、node03设置arp协议配置

需要修改arp_ignore为1:

1
echo 1 >/proc/sys/net/ipv4/conf/ens33/arp_ignore

需要修改arp_announce为2

1
echo 2 >/proc/sys/net/ipv4/conf/ens33/arp_announce

因为我们想启动也是这个配置,所以需要在all目录下配置一下

1
echo 1 >/proc/sys/net/ipv4/conf/all/arp_ignore
1
echo 2 >/proc/sys/net/ipv4/conf/all/arp_announce

配置node02、node03的虚拟ip,注意需要配置到环卫接口上,就是本地接口,掩码需要是255.255.255.255。为什么要配置到lo上呢?lo是转发给自己的,我们不能转发出去,转发出去就出问题了。

1
ifconfig lo:1 192.168.188.100 netmask 255.255.255.255

image-20210507162749285

node01配置lvs

关闭禁止转发:

1
echo 1 > /proc/sys/net/ipv4/ip_forward

添加入口:

1
ipvsadm -A -t 192.168.188.100:80 -s rr

添加出口,就是RIP要负载的IP

1
ipvsadm -a -t 192.168.188.100:80 -r 192.168.188.181:80 -g -w 1

最终查看ipvsadm的表

1
ipvsadm -ln

image-20210507165442822

这样就配置完成了,访问192.168.188.100会把请求分发到 node01、node02

基于keepalived的LVS高可用搭建

解决问题

问题1:

单点故障,LVS解决了高并发分流的高速转发问题,但是有一个问题,就是VS挂了会怎么办,这个时候我们需要高可用,搭建分布模式。

问题2:

转发的RS挂了,VS是不知道的,VS是不断的转发…这里肯定会出问题

架构设计

我们需要改哪些东西:

是针对VS的设计,我们并不需要改RS,需要改两个东西

  • 设计一个主VS,N个备VS,只要主VS挂了,备VS马上顶上
  • 需要知道RS是否挂了,如果挂了,就不转发到这个RS上了

解决主备思路:

Master通告给Backup自己还活着,Backup监听Master状态,如果Backup监听到Master挂了,一堆Backup赶紧选举一个Master

解决RS存活:

VS对后端的RS进行健康检查,如果RS挂了,赶紧踢掉,如果RS活了,就加上

代码实现

试验环境,两台服务器

name ip 作用
VS1 192.168.166.11 负载均衡服务器
RS1 192.168.166.12 真是访问的IP
RS2 192.168.166.13 真是访问的IP
VS2 192.168.166.14 负载均衡服务器
VS 192.168.166.100 虚拟的ip,访问这个ip

有人写好了程序,我们直接安装到 VS1、VS2

1
yum -y install keepalived

去修改keepalived的配置

1
cd /etc/keepalived

里面会有keepalived.conf,下面介绍两个主要配置

vrrp_instance VI_1:虚拟路由冗余协议

1
2
3
4
5
6
7
8
9
10
11
12
13
14
vrrp_instance VI_1 {
state MASTER ##设置备注 备机需要改BACKUP
interface ens33 ##设置服务的网卡
virtual_router_id 51 ##Ha 的Id
priority 100 ##权重 备机需要改
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress { ##VIP,就是我们访问的IP
192.168.166.100/24 dev ens33 label ens33:1
}
}

​ virtual_server:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
virtual_server 192.168.166.100 80 { ##VIP
delay_loop 6
lb_algo rr ## 负载模式
lb_kind DR ## 转发模式,NAT DR TUN
persistence_timeout 0 ##持久化链接,我们实验环境设置0,生成环境设置合适的时间,单位为秒
protocol TCP ##转发协议

real_server 192.168.166.12 80 { ## RIP就是转发的IP
weight 1 ##权重
HTTP_GET { ## 请求方式 SSL_GET HTTP_GET SSL_GET应该是https请求
url {
path / ##监控RS是否存活,就是健康检查
status_code 200 ##定义请求200是存活
}
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}

real_server 192.168.166.13 80 { ## RIP就是转发的IP
weight 1 ##权重
HTTP_GET { ## 请求方式 SSL_GET HTTP_GET SSL_GET应该是https请求
url {
path / ##监控RS是否存活,就是健康检查
status_code 200 ##定义请求200是存活
}
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
}

修改完配置直接主备启动keepalived即可

1
systemctl start keepalived