阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

LVS(Linux Virtual Server) 入门详解

148次阅读
没有评论

共计 15200 个字符,预计需要花费 38 分钟才能阅读完成。

前言:

当第一次接触 LVS,得知是国内的大佬弄出来的东东,还被加入了内核,简直佩服的不要不要的。不过,由于其功能比较简单,配置复杂,其实正真被使用的到不是很多。也许一提到软件的负载均衡,肯定先想到的是 Nginx 或者 haproxy。当然,对于理解 LVS 的一些概念,各种类型,已经调度方式,对于以后学习应用层的负载均衡技术是有很大帮助的。今天,我们就先来说说 LVS 的一些概念性的东西。

正文:

首先,我们先以宏观的角度来说说 LVS 集群的各个类型,多目标 DNAT 的 LVS-nat,直接路由的 LVS-dr,此为默认类型,还有基于隧道的 LVS-tun。其实基本的类型就以上三种,不过还有一个后面出来的东东 LVS-fullnat。我们一个一个的来说~ 在讲具体 LVS 类型之前,我们先提几个术语,方便后面的描述,能用到的我会尽量在图中标记出来。整个服务器集群,由一堆提供服务的服务器和调度器组成,服务器是来提供服务器的,调度器使用来决定,当一个客户请求尽量,选择哪个服务器响应的东东。我们把这个调度器称为 Virtual Server(VS),Director(调度器),Dispatcher(分发器),Balancer(负载均衡器),把后面的服务器称为 Real Server(RS),客户端向调度器发送请求时,客户端的 IP 即 Client IP 简称为 CIP,接收客户端请求的 IP 为 Virtual Server IP(VIP), 连接后端服务器的为 Director IP(DIP),服务器端为 Real Server IP(RIP)

LVS-nat

LVS(Linux Virtual Server) 入门详解

咳咳,图有点丑,将就着看把~nat 做为网络中很基本的协议,估计是没人不懂把。不懂的道友求请自行学习下~ 不难!LVS-nat 是多目标的 DNAT,通过将请求报文中的目标地址和目标端口修改为挑选出来的 RS 的 RIP 和 PORT 实现转发。简单来说就是,用户客户端发送的请求都由 VIP 接收,然后 VS 根据调度策略选择某一个 RIP。从客户端到调度器的数据包的源 IP 是 CIP,目的 IP 是 VIP, 然后 DNAT 把其目的地址从 VIP 转换为 RIP,所有数据包从 DIP 发送到 RIP 是,其源 IP 为 CIP,目的 IP 为 RIP。这样客户端的请求就到达了调度器选择的某一个 RS 上,然后此 RS 根据请求,向 CIP 发送一个响应,如果 RIP 直接响应 CIP,不经过调度器,客户端收到一个源 IP 不是 VIP 的数据包,肯定莫名奇妙呀,明明我请求的是 VIP,怎么会返回 RIP 的数据包呢?所以,RS 响应客户端请求时,得重新把源地址为 RIP 的数据转换成 VIP。然后客户端就收到响应啦~~~

OK,我们重新来总体描述下。假如现在同时有 5 个客户端请求发给调度器,然后调度器根据调度策略,把这 5 个请求送到后面几个服务器上,送的方式就是修改目的 IP 地址为选择的 RIP。然后,各服务器的响应在经过调度器的转换发送给各个客户端。这样就实现了最基本的负载均衡啦~ 有木有很简单~

在此模式下,我们只用把 VIP 设置为公网 IP,把其他的 DIP,RIP 设置为私有地址,就可以提供服务器并满足负载均衡的需求了。而且,此模式还支持端口映射~ 因为调度器只是发送一个请求到后端服务器,所以 VS 必须是 linux,比较 LVS 是 linux 上的东东,还加到内核了,RS 就可以是任何系统了,能提供服务就好。

nat 模式有不少优势,但是劣势却是相当明显的,所有的请求,响应都必须经过调度器,可想调度器的负载有多大,当集群越来越大时,调度器就有可能称为整个集群的瓶颈。所以,我们就想,我们能不能只把请求发送给调度器选定的服务器,然后后端服务器直接响应客户端。因为,其实请求的消耗的资源,比起响应消耗的资源简直不要小太多,这样调度器即实现了调度的功能,有减少了负载,妙哉!其实,这种实现方式就是我们下面要讲到的基于直接路由的 LVS-dr 啦~ 让我们来一起看看这个有趣又复杂的东东把~

LVS-dr

虽然叫 Direct Routing, 但是跟我们熟悉的路由不太一样耶~ 来看看整个结构图把!图丑,见谅~(为了显示方便,我就不打水印了,引用要注明出处哈~ 我想是没人想看这丑图的!)

LVS(Linux Virtual Server) 入门详解

普通意义上来讲,用户从客户端到我们的调度器时,已经经过了无数个网络设备了,图上的路由器标识我们局域网的出接口所在的路由器,交换机表示 VS 和 RS 所在的局域网,专业点说就是同一个广播域。我们来开始描述下 LVS-dr 这个东东的结构哈~ 当客户端的请求经过无数个路由器,交换机到达我们的调度器时,此过程中源 IP 是客户端的 CIP,目的 IP 是调度器的 VIP, 到达调度器的内网时,请求报文的源 MAC 地址为网关的 MAC 地址,目的 MAC 地址就是 VIP 所在的 MAC 地址。(这个东东必须明晰!不然后面理解有点困难,此处默认大家有基本的网络知识!)此结构中我们的 VIP 和 DIP 其实是同一个,然后我们把请求的数据包转发给处在同一网络中的 VS 选择的一个 RS。此时的请求数据包的源 IP 依然是 CIP,目的 IP 依然是 VIP 不变,但是目的 MAC 地址变为 RIP 所在接口的 MAC 地址。(必须知道,IP 地址是逻辑上的地址,MAC 地址才是真正的通信地址,所以我们才可以通过修改 MAC 地址发送到指定的 RS)。RS 接收到数据后,假如她能根据请求进行响应,直接发给客户端。这样就响应报文就不用经过调度器。不过,前面我们提到的问题还没解决呀,我们从 RIP 发出去的数据包,肯定源 IP 是 RIP,客户端依然会觉得莫名奇妙呀!也许你会想,那我们可以给 RIP 所在的接口加一个 VIP 地址呀,让它出去的时候源 IP 是 VIP 不就行了,嗯。。想法很好,不过还是有问题,RS 和 VS 在同一个网络,同一个网络可是不能有相同地址的。不然,当某个接口发送 arp 广播,问这个网络中 VIP 的 MAC 地址是谁呀,如果有两个接口响应,不是就乱套了吗?当然,这个问题可以有两个解决办法,第一我们可以在出接口的路由器上绑定 arp,就把 VIP 绑定到 VS 的 VIP 所在的接口,然后把 RIP 也设置为 VIP。这样问题就解决了~ 当然,一般来说我们的出接口路由器都在 运营商的机房里我们很难有权利去修改,所以也有第二种方法,我们可以通过 arptables 禁止 RS 的 VIP 去响应和通告 arp。这样 RS 可以不告诉别人我有 VIP 地址了~ 完美!

再讲第三种之前,我们先整理一下,我们把 VS 和 RS 上都设置有 VIP 的 ip 地址,然后不让 RS 上的 RIP 接口响应 arp 也不向别人通告自己,这样的话,当客户端对 vip 的请求发到本地网络时,发送 arp 广播问 VIP 对应的 mac 地址是多少呀?就只有 VS 的 VIP 响应说,啊,VIP 的 MAC 地址就是我们这个 MAC 地址!然后网关就通过 MAC 地址将客户端的请求发送给 VIP 所在的接口,因为是客户端请求,最后由网关发送到 VIP 的。所以,从网关出去时源 IP 为 CIP,目的 IP 为 VIP,源 MAC 为网关接口的 MAC,目的 IP 为 VIP 所在接口的 MAC,VS 接收到请求数据包之后,根据调度策略选择一个合适的 RS,然后从 VIP 接口发出,到 RS 所在的 RIP 接口,此时,源 IP 还是 CIP,目的 IP 还是 VIP,源 MAC 是 VS 的 VIP 所在的接口 MAC,目的 MAC 是 RIP 所在接口的 MAC,然后 RS 接收到数据包后,查看一下,嗯目的 IP 是我接口的 IP,目的 MAC 是我接口的 MAC,然后继续解封装到应用层,把请求给对应的服务器程序。服务器收到程序后,再从 RS 的 VIP 发送响应数据,此时源 IP 就为送出接口的 IP 即 VIP,目的 IP 就是 CIP 啦~ 然后就实现所谓的响应报文不经过调度器啦。有没有感觉牛逼吊炸天呀!!!!!!简直不要太牛!!!!不过有个问题还是没解决,RIP 收到请求数据包后,在从此接口发出去的时候源 IP 依然是 RIP,怎样才能实现上文提到的源 IP 为 VIP 呢?LVS 在此处的设计相当精巧。在 linux 中有个思想就是,ip 是属于内核的而不是接口的。即接口 a 上 有个 IP1,接口 b 上有个 ip2,当从 a 接口收到一个数据包,问接口 a 你有没有 ip2 呀,接口 a 回复说我有 ip2,然后接口 a 收到 ip2 的数据包之后就转发给接口 b。还有一点,一个数据包从哪个接口发出去,它的源 IP 就是哪个接口的 ip,即从接口 a 发出去的数据包的源 ip 为接口 a 的 ip,但是从接口 a 发出,但转发到接口 b 发送给另外一个接口,源 ip 还是接口 a 的 ip。根据这两个常识,第三种的实现如下:RS 接收数据包的接口依然是 RIP,但是我们把 VIP 设置到 lo0 环回接口上,因为接口 a 都会把 lo0 接口上的 VIP 告诉别人,所以我们得通过设置内核参数让 ip 地址就属于接口本身,不属于接口的 ip 他不能告诉别人。第二,我们让数据包从 lo0 口发出,然后从 RIP 所在的接口发送给外部主机,这样源 IP 就是 lo0 接口所在的 VIP 啦~~~~ 有木有很精巧!!!可以根据上面的图示进行理解。

因为 LVS-dr 模式是通过修改目的 MAC 地址来把请求报文从 VS 发送到 RS 的,而且 MAC 不能跨网络,所以 LVS-dr 模式只能用在同一广播域中。如果我们向把 RS 放在各个地方的不同网络中,怎么办?这就是我们接下来要讲的类型。

高可用集群技术之 Keepalived 实现 LVS 高可用并负载均衡 Web 服务   http://www.linuxidc.com/Linux/2016-09/135111.htm

LVS 简单实现 NAT&DR 模型 http://www.linuxidc.com/Linux/2016-12/138707.htm

LVS 集群类型简介  http://www.linuxidc.com/Linux/2016-12/138709.htm

《LVS 手册》http://www.linuxidc.com/Linux/2016-03/129233.htm 

Linux 负载均衡软件 LVS  http://www.linuxidc.com/Linux/2016-11/137435.htm

使用 LVS 实现负载均衡原理及安装配置详解  http://www.linuxidc.com/Linux/2017-02/140548.htm

第一个就是 LVS 内核本身支持的类型 LVS-tun,tun 就是 tunnel 的简写即隧道。如果熟悉 vpn 的道友,肯定对隧道不陌生。不过,我们还是来仔细讲讲咯~

LVS(Linux Virtual Server) 入门详解

客户端向 VS 发出请求,源 IP 为 CIP 目的 IP 为 VIP,然后给请求数据包在封装一层,源 IP 为 DIP,目标 IP 为 RIP,然后 RS 收到数据包,先解开一看,嗯目标地址是自己,再继续解封装,因为 RS 肯定也得支持隧道,所以就知道是 CIP 发来的请求,然后就可以用 vip 发出响应从 RIP 所在的接口发出直接到达客户端。此类型特殊,用的也不多,就简单这样讲讲~ 既然是要跨网络的,所以所有的 RIP 和 VIP 以及 DIP 都得是公网地址~

第三种是 full-nat, 和 LVS-nat 模式其是差不太多。在 LVS-nat 中,后端服务器为了能发送数据包给客户端,必须得经过 VS,���以 RS 的网关得设置为 DIP,即 RS 和 VS 必须在同一网段中,也就是不能跨网络,那如果我们非要让它实现跨网络怎么办?因为 LVS-nat 只是把目的地址 VIP 转换为 RIP,以至于其不能跨网络,所以为了实现跨网络,我们就可以把请求数据包的源目 ip 地址都进行转换,这就是所谓的 full-nat 啦~

LVS(Linux Virtual Server) 入门详解

full-nat 理解起来是最简单的,客户端向 VS 发送请求,VS 接收到请求后,根据调度策略选择某一个 RS,然后把请求的源 ip 地址从 CIP 改为 DIP,目的 IP 从 VIP 改为 RIP,发送到后端服务器,后端服务器收到请求后,再向 VS 响应请求,发送到 VS,然后 VS 在通过地址转换发送到客户端,整个过程就是这么简单~~~ 所以 VS 和 RS 之间只要网络可达,无论 RS 在世界的哪个角落都能收到 VS 转发过来的请求,然后通过 VS 响应客户端。完美解决异地问题。

嗯嗯,到此呢,LVS 的类型就将完了~ 除了 dr 复杂点其他都还好把。我们从宏观的角度描述了各类的 LVS,我们很明白其实整个 LVS 负载均衡集群的核心就是那个调度器啦、而调度器的核心就是各种调度策略咯。所以,接下来我们就再讲讲各种调度方法把~ 我们可以把调度方法分为静态方法和动态方法,静态方法就是仅仅根据算法本身调度,动态方法就是根据算法及各 RS 当前的负载状态进行调度。

静态方法有如下几种:

RR,Round Robin,轮询调度,也就是无论个 RS 的性能,一个一个的进行调度。

WRR,Weighted RR,加权轮询,就是根据每个 RS 的性能不同,给每个设备不同的权值,权值大的就调度次数更多,比如有两台机器一个权值是 3,一个权值是 2,那么可以简单理解为先调用第一台机器 3 此,在调用第二台机器两次,这样一直轮询。

SH,Source Hashing,源地址哈希,假如我们提供服务的网站要保存用户的信息,比如说 session 会话之类的东东,如果用户 1 第一次访问被分配到 RS1 响应,然后把 session 之类的信息保存到了 RS1,然后用户 1 第二次访问时,被分配到了 RS2 响应,以前保存的用户相关的信息没了?!这写问题就闹大了。所以,为了解决这类问题,就出现了所谓的源地址哈希,就是如果某个请求是第一次收到,我们就对请求报文的源 ip 地址进行 hash 计算,保存到一个哈希表中,并对应这个请求的 RS 地址,当第后面收到请求时,查看哈希表找到这个请求对应的 RS,就直接传给上次访问的 RS。这样就解决了,上述问题啦~

DH,Destination Hashing,目标地址哈希

动态方法如下:

LC:least connections,最少连接:即后端服务器那个处理的请求连接数最少就选哪个 RS,公式为 OverHead=Active*250+Inactive,活动链接数乘以 250 加上非活动连接数,越小越优先选择。不过此方式的虽然考虑到了后端的负载,但是并没区别出不同性能的服务器,所以此方法还是有不足之处、

WLC,Weight LC,加权最少连接,既然要烤炉每个设备的不同性能,我们也可以给不同性能的 RS 以不同的权重值,公式为 OverHead=(Active*256+inactive)/weight,假如有三台机器,权重值分别是 5,2,1. 当第一个请求进来时,因为三台机器都没有链接,都是 0,调度器就会根据 RS 列表从上到下一次调度,但是如果放在最前面的是性能最差的机器怎么办,如果我们想从第一个请求开始就根据负载能力调度,那么就有了下面这种方法。

SED,Shortest Expection Delay,最短延迟预期,因为相对于活动连接来说,非活动链接的消耗,小的可以忽略不计,所以我们可以直接不计算非活动链接数,以此来减小计算,SED 公式如下 Overhead=(activeconns+1)*256/weight,这样权重值大的一定会被先选到。不过依然有个问题,假如有两台机器,一台权重为 1,另一台权重为 10,当地一个请求进来时,经过计算第一台为 256,第二个为 25.6,然后就把第一个请求给第二台服务器,第二请求过来,经过计算依然给第 2 台服务器,如果一次过来 9 个请求,都会全部给第二台主机,那么第一台就一直处于等待状态,就算能力再差也至少得处理一个请求把~ 所以有下面这种调度方法。

NQ,Never Queue,永不排队。假如有两台 RS,从 vs 过来两个请求,第一个给权重大的那个 RS,第二个给空闲的哪个,后面的再根据负载计算进行分配,这样就保证了即使权重小也不会一直控线啦。后面还有 LBLS,Locality-Based LC,基于本地的 LC 和 LBLCR,LBLC with copy 带复制功能的 LBLC。

更多详情见请继续阅读下一页的精彩内容:http://www.linuxidc.com/Linux/2017-03/141929p2.htm

前言:

    讲道理来说,我是不愿意弄出来一堆命令的,毕竟理论知识才是核心嘛。不过,lvs 的部署倒是坑不少,所以都把实现过程记录下来了~

正文:

    lvs-nat 的简单拓扑如下:

LVS(Linux Virtual Server) 入门详解

    因为,此模式的核心是 DNAT,所以调度器前端用来接收请求和与后端服务器通信就不在同一网段了。当请求从左端的客户端进来,调度器根据调度算法选择一台服务器,把请求的目的 IP 改成该服务器的地址,该服务器在通过调度器响应客户端。这就是大概的通信流程。具体的可以看上一篇博客,此篇我们主要来说配置。

    环境介绍:我们用 172.16.53.100 来当 VIP,192.168.157.128 为 DIP,192.168.157.129 为第一台 RS 的 RIP,192.168.157.130 为第二台 RS 的 RIP。配置的重点有如下几个:

    1. 我们的调度器因为用到了 nat 的网络地址转换,所以调度器得开核心转发

    2. 因为 RS 得通过调度器来和外部的客户端通信,所以 RS 的网关就是 DIP

    3. 因为 lvs 工作在 input 链 (不知道是什么的可以去学学 iptables 理论知识~) 上,所以为了方式 iptables 的干扰,就直接清空 iptables 了。

    4. 各个服务器之间要时间同步。

    话不多说,nat 模式还是比较简单的,所以我们直接来配置把。我们先在两个 RS 上开启 web 服务。并设置不同的主页以用来测试。两个 RS 配置基本一致,我就只写一遍咯,不同的地方会指出。

#RS
yum install httpd -y
vim /var/www/html/index.html
    192.168.157.129  #另一台设置为 192.168.157.130,方便测试的区别
systemctl start httpd
route add default gw 192.168.157.128        #一定要记得网关指向 DIP 哟。
iptables -F(或者允许 80 端口进入就可)
#VS
yum install -y ipvsadm
echo 1 > /proc/sys/net/ipv4/ip_forward          #开启转发功能
ipvsadm -A -t 172.16.53.100:80 -s rr  #新建一个集群服务,VIP 为 172.16.53.100,rr 表示轮询
ipvsadm -a -t 172.16.53.100:80 -r 192.168.157.129:80 -m 
ipvsadm -a -t 172.16.53.100:80 -r 192.168.157.130:80 -m  #增加两个个 RS - m 表示 nat 模式
iptables -F                                              #记得清空防火墙规则
curl 172.16.53.100        #测试 lvs 功能。

    提一下博主遇到的一些坑。首先 VIP 得能访问到后端的 web 服务,如果不能,可能是 80 端口没开放,web 服务没开启,一定要记得在 RS 上指定网关为 DIP,一定要记得在 VS 上开启核心转发。一定要记得情况 VS 上的防火墙规则,还有要保证测试环境的干净,比如 RS 最好只有一个网卡。博主每次做完实验都会把测试系统还原到最原始的状态。接下来我们实现稍微复杂的 lvs-dr。

    lvs-dr 模式实现的环境结构图如下:

LVS(Linux Virtual Server) 入门详解

    RS 和 VS 都在同一个网络中,DIP 的 ip 地址为 172.16.53.100,RS1 的 RIP 为 172.16.53.101,RS2 的 RIP 为 172.16.53.102. 模仿用户的测试客户机的 ip 地址为 172.16.53.103.

    dr 中要注意的是,VS 上 vip 和 dip 在同一个接口上,RS 上 RIP 在物理接口上,VIP 在 lo 上,然后为了方式 RS 上的 VIP 通告自己的 MAC 地址,或者响应 arp,我们得修改内核参数来关闭这两个功能。RS 配置基本一样,配置如下:

#RS
yum install httpd -y
vim /var/www/html/index.html
    172.16.53.101  #另一台设置为 172.16.53.102,方便测试的区别
systemctl start httpd
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
ifconfig lo:0 172.16.53.50 netmask 255.255.255.255 broadcast 172.16.53.50 up
    #在 lo 环回口上设置 vip 地址。
route add -host 172.16.53.50 dev lo:0    #指定主机路由,让以 vip 为源地址的数据包从 lo:0 发出 #VS
yum install ipvsadm -y
ifconfig eno16777736:0 172.16.53.50 netmask 255.255.255.255 broadcast 172.16.53.50 up
在 DIP 所在的接口上加一个 VIP
iptables -F  #记得清空防火墙规则
ipvsadm -A -t 172.16.53.50:80 -s rr  #新增一个集群,rr 表示调度方法为轮询
ipvsadm -a -t 172.16.53.50:80 -r 172.16.53.101 -g    # - g 表示为 lvs-dr 模式
ipvsadm -a -t 172.16.53.50:80 -r 172.16.53.102 -g
# 测试机
curl 172.16.53.50   
    ################### 注意!!!!!一定要在另外一台机器上测试!!!!这个坑我已经踩了好多次了!!!!!!!!!!!!!真的是坑!!!!!!!

    好啦,到此配置就结束了~ 有木有很简单呢~

本文永久更新链接地址:http://www.linuxidc.com/Linux/2017-03/141929.htm

前言:

当第一次接触 LVS,得知是国内的大佬弄出来的东东,还被加入了内核,简直佩服的不要不要的。不过,由于其功能比较简单,配置复杂,其实正真被使用的到不是很多。也许一提到软件的负载均衡,肯定先想到的是 Nginx 或者 haproxy。当然,对于理解 LVS 的一些概念,各种类型,已经调度方式,对于以后学习应用层的负载均衡技术是有很大帮助的。今天,我们就先来说说 LVS 的一些概念性的东西。

正文:

首先,我们先以宏观的角度来说说 LVS 集群的各个类型,多目标 DNAT 的 LVS-nat,直接路由的 LVS-dr,此为默认类型,还有基于隧道的 LVS-tun。其实基本的类型就以上三种,不过还有一个后面出来的东东 LVS-fullnat。我们一个一个的来说~ 在讲具体 LVS 类型之前,我们先提几个术语,方便后面的描述,能用到的我会尽量在图中标记出来。整个服务器集群,由一堆提供服务的服务器和调度器组成,服务器是来提供服务器的,调度器使用来决定,当一个客户请求尽量,选择哪个服务器响应的东东。我们把这个调度器称为 Virtual Server(VS),Director(调度器),Dispatcher(分发器),Balancer(负载均衡器),把后面的服务器称为 Real Server(RS),客户端向调度器发送请求时,客户端的 IP 即 Client IP 简称为 CIP,接收客户端请求的 IP 为 Virtual Server IP(VIP), 连接后端服务器的为 Director IP(DIP),服务器端为 Real Server IP(RIP)

LVS-nat

LVS(Linux Virtual Server) 入门详解

咳咳,图有点丑,将就着看把~nat 做为网络中很基本的协议,估计是没人不懂把。不懂的道友求请自行学习下~ 不难!LVS-nat 是多目标的 DNAT,通过将请求报文中的目标地址和目标端口修改为挑选出来的 RS 的 RIP 和 PORT 实现转发。简单来说就是,用户客户端发送的请求都由 VIP 接收,然后 VS 根据调度策略选择某一个 RIP。从客户端到调度器的数据包的源 IP 是 CIP,目的 IP 是 VIP, 然后 DNAT 把其目的地址从 VIP 转换为 RIP,所有数据包从 DIP 发送到 RIP 是,其源 IP 为 CIP,目的 IP 为 RIP。这样客户端的请求就到达了调度器选择的某一个 RS 上,然后此 RS 根据请求,向 CIP 发送一个响应,如果 RIP 直接响应 CIP,不经过调度器,客户端收到一个源 IP 不是 VIP 的数据包,肯定莫名奇妙呀,明明我请求的是 VIP,怎么会返回 RIP 的数据包呢?所以,RS 响应客户端请求时,得重新把源地址为 RIP 的数据转换成 VIP。然后客户端就收到响应啦~~~

OK,我们重新来总体描述下。假如现在同时有 5 个客户端请求发给调度器,然后调度器根据调度策略,把这 5 个请求送到后面几个服务器上,送的方式就是修改目的 IP 地址为选择的 RIP。然后,各服务器的响应在经过调度器的转换发送给各个客户端。这样就实现了最基本的负载均衡啦~ 有木有很简单~

在此模式下,我们只用把 VIP 设置为公网 IP,把其他的 DIP,RIP 设置为私有地址,就可以提供服务器并满足负载均衡的需求了。而且,此模式还支持端口映射~ 因为调度器只是发送一个请求到后端服务器,所以 VS 必须是 linux,比较 LVS 是 linux 上的东东,还加到内核了,RS 就可以是任何系统了,能提供服务就好。

nat 模式有不少优势,但是劣势却是相当明显的,所有的请求,响应都必须经过调度器,可想调度器的负载有多大,当集群越来越大时,调度器就有可能称为整个集群的瓶颈。所以,我们就想,我们能不能只把请求发送给调度器选定的服务器,然后后端服务器直接响应客户端。因为,其实请求的消耗的资源,比起响应消耗的资源简直不要小太多,这样调度器即实现了调度的功能,有减少了负载,妙哉!其实,这种实现方式就是我们下面要讲到的基于直接路由的 LVS-dr 啦~ 让我们来一起看看这个有趣又复杂的东东把~

LVS-dr

虽然叫 Direct Routing, 但是跟我们熟悉的路由不太一样耶~ 来看看整个结构图把!图丑,见谅~(为了显示方便,我就不打水印了,引用要注明出处哈~ 我想是没人想看这丑图的!)

LVS(Linux Virtual Server) 入门详解

普通意义上来讲,用户从客户端到我们的调度器时,已经经过了无数个网络设备了,图上的路由器标识我们局域网的出接口所在的路由器,交换机表示 VS 和 RS 所在的局域网,专业点说就是同一个广播域。我们来开始描述下 LVS-dr 这个东东的结构哈~ 当客户端的请求经过无数个路由器,交换机到达我们的调度器时,此过程中源 IP 是客户端的 CIP,目的 IP 是调度器的 VIP, 到达调度器的内网时,请求报文的源 MAC 地址为网关的 MAC 地址,目的 MAC 地址就是 VIP 所在的 MAC 地址。(这个东东必须明晰!不然后面理解有点困难,此处默认大家有基本的网络知识!)此结构中我们的 VIP 和 DIP 其实是同一个,然后我们把请求的数据包转发给处在同一网络中的 VS 选择的一个 RS。此时的请求数据包的源 IP 依然是 CIP,目的 IP 依然是 VIP 不变,但是目的 MAC 地址变为 RIP 所在接口的 MAC 地址。(必须知道,IP 地址是逻辑上的地址,MAC 地址才是真正的通信地址,所以我们才可以通过修改 MAC 地址发送到指定的 RS)。RS 接收到数据后,假如她能根据请求进行响应,直接发给客户端。这样就响应报文就不用经过调度器。不过,前面我们提到的问题还没解决呀,我们从 RIP 发出去的数据包,肯定源 IP 是 RIP,客户端依然会觉得莫名奇妙呀!也许你会想,那我们可以给 RIP 所在的接口加一个 VIP 地址呀,让它出去的时候源 IP 是 VIP 不就行了,嗯。。想法很好,不过还是有问题,RS 和 VS 在同一个网络,同一个网络可是不能有相同地址的。不然,当某个接口发送 arp 广播,问这个网络中 VIP 的 MAC 地址是谁呀,如果有两个接口响应,不是就乱套了吗?当然,这个问题可以有两个解决办法,第一我们可以在出接口的路由器上绑定 arp,就把 VIP 绑定到 VS 的 VIP 所在的接口,然后把 RIP 也设置为 VIP。这样问题就解决了~ 当然,一般来说我们的出接口路由器都在 运营商的机房里我们很难有权利去修改,所以也有第二种方法,我们可以通过 arptables 禁止 RS 的 VIP 去响应和通告 arp。这样 RS 可以不告诉别人我有 VIP 地址了~ 完美!

再讲第三种之前,我们先整理一下,我们把 VS 和 RS 上都设置有 VIP 的 ip 地址,然后不让 RS 上的 RIP 接口响应 arp 也不向别人通告自己,这样的话,当客户端对 vip 的请求发到本地网络时,发送 arp 广播问 VIP 对应的 mac 地址是多少呀?就只有 VS 的 VIP 响应说,啊,VIP 的 MAC 地址就是我们这个 MAC 地址!然后网关就通过 MAC 地址将客户端的请求发送给 VIP 所在的接口,因为是客户端请求,最后由网关发送到 VIP 的。所以,从网关出去时源 IP 为 CIP,目的 IP 为 VIP,源 MAC 为网关接口的 MAC,目的 IP 为 VIP 所在接口的 MAC,VS 接收到请求数据包之后,根据调度策略选择一个合适的 RS,然后从 VIP 接口发出,到 RS 所在的 RIP 接口,此时,源 IP 还是 CIP,目的 IP 还是 VIP,源 MAC 是 VS 的 VIP 所在的接口 MAC,目的 MAC 是 RIP 所在接口的 MAC,然后 RS 接收到数据包后,查看一下,嗯目的 IP 是我接口的 IP,目的 MAC 是我接口的 MAC,然后继续解封装到应用层,把请求给对应的服务器程序。服务器收到程序后,再从 RS 的 VIP 发送响应数据,此时源 IP 就为送出接口的 IP 即 VIP,目的 IP 就是 CIP 啦~ 然后就实现所谓的响应报文不经过调度器啦。有没有感觉牛逼吊炸天呀!!!!!!简直不要太牛!!!!不过有个问题还是没解决,RIP 收到请求数据包后,在从此接口发出去的时候源 IP 依然是 RIP,怎样才能实现上文提到的源 IP 为 VIP 呢?LVS 在此处的设计相当精巧。在 linux 中有个思想就是,ip 是属于内核的而不是接口的。即接口 a 上 有个 IP1,接口 b 上有个 ip2,当从 a 接口收到一个数据包,问接口 a 你有没有 ip2 呀,接口 a 回复说我有 ip2,然后接口 a 收到 ip2 的数据包之后就转发给接口 b。还有一点,一个数据包从哪个接口发出去,它的源 IP 就是哪个接口的 ip,即从接口 a 发出去的数据包的源 ip 为接口 a 的 ip,但是从接口 a 发出,但转发到接口 b 发送给另外一个接口,源 ip 还是接口 a 的 ip。根据这两个常识,第三种的实现如下:RS 接收数据包的接口依然是 RIP,但是我们把 VIP 设置到 lo0 环回接口上,因为接口 a 都会把 lo0 接口上的 VIP 告诉别人,所以我们得通过设置内核参数让 ip 地址就属于接口本身,不属于接口的 ip 他不能告诉别人。第二,我们让数据包从 lo0 口发出,然后从 RIP 所在的接口发送给外部主机,这样源 IP 就是 lo0 接口所在的 VIP 啦~~~~ 有木有很精巧!!!可以根据上面的图示进行理解。

因为 LVS-dr 模式是通过修改目的 MAC 地址来把请求报文从 VS 发送到 RS 的,而且 MAC 不能跨网络,所以 LVS-dr 模式只能用在同一广播域中。如果我们向把 RS 放在各个地方的不同网络中,怎么办?这就是我们接下来要讲的类型。

高可用集群技术之 Keepalived 实现 LVS 高可用并负载均衡 Web 服务   http://www.linuxidc.com/Linux/2016-09/135111.htm

LVS 简单实现 NAT&DR 模型 http://www.linuxidc.com/Linux/2016-12/138707.htm

LVS 集群类型简介  http://www.linuxidc.com/Linux/2016-12/138709.htm

《LVS 手册》http://www.linuxidc.com/Linux/2016-03/129233.htm 

Linux 负载均衡软件 LVS  http://www.linuxidc.com/Linux/2016-11/137435.htm

使用 LVS 实现负载均衡原理及安装配置详解  http://www.linuxidc.com/Linux/2017-02/140548.htm

第一个就是 LVS 内核本身支持的类型 LVS-tun,tun 就是 tunnel 的简写即隧道。如果熟悉 vpn 的道友,肯定对隧道不陌生。不过,我们还是来仔细讲讲咯~

LVS(Linux Virtual Server) 入门详解

客户端向 VS 发出请求,源 IP 为 CIP 目的 IP 为 VIP,然后给请求数据包在封装一层,源 IP 为 DIP,目标 IP 为 RIP,然后 RS 收到数据包,先解开一看,嗯目标地址是自己,再继续解封装,因为 RS 肯定也得支持隧道,所以就知道是 CIP 发来的请求,然后就可以用 vip 发出响应从 RIP 所在的接口发出直接到达客户端。此类型特殊,用的也不多,就简单这样讲讲~ 既然是要跨网络的,所以所有的 RIP 和 VIP 以及 DIP 都得是公网地址~

第三种是 full-nat, 和 LVS-nat 模式其是差不太多。在 LVS-nat 中,后端服务器为了能发送数据包给客户端,必须得经过 VS,���以 RS 的网关得设置为 DIP,即 RS 和 VS 必须在同一网段中,也就是不能跨网络,那如果我们非要让它实现跨网络怎么办?因为 LVS-nat 只是把目的地址 VIP 转换为 RIP,以至于其不能跨网络,所以为了实现跨网络,我们就可以把请求数据包的源目 ip 地址都进行转换,这就是所谓的 full-nat 啦~

LVS(Linux Virtual Server) 入门详解

full-nat 理解起来是最简单的,客户端向 VS 发送请求,VS 接收到请求后,根据调度策略选择某一个 RS,然后把请求的源 ip 地址从 CIP 改为 DIP,目的 IP 从 VIP 改为 RIP,发送到后端服务器,后端服务器收到请求后,再向 VS 响应请求,发送到 VS,然后 VS 在通过地址转换发送到客户端,整个过程就是这么简单~~~ 所以 VS 和 RS 之间只要网络可达,无论 RS 在世界的哪个角落都能收到 VS 转发过来的请求,然后通过 VS 响应客户端。完美解决异地问题。

嗯嗯,到此呢,LVS 的类型就将完了~ 除了 dr 复杂点其他都还好把。我们从宏观的角度描述了各类的 LVS,我们很明白其实整个 LVS 负载均衡集群的核心就是那个调度器啦、而调度器的核心就是各种调度策略咯。所以,接下来我们就再讲讲各种调度方法把~ 我们可以把调度方法分为静态方法和动态方法,静态方法就是仅仅根据算法本身调度,动态方法就是根据算法及各 RS 当前的负载状态进行调度。

静态方法有如下几种:

RR,Round Robin,轮询调度,也就是无论个 RS 的性能,一个一个的进行调度。

WRR,Weighted RR,加权轮询,就是根据每个 RS 的性能不同,给每个设备不同的权值,权值大的就调度次数更多,比如有两台机器一个权值是 3,一个权值是 2,那么可以简单理解为先调用第一台机器 3 此,在调用第二台机器两次,这样一直轮询。

SH,Source Hashing,源地址哈希,假如我们提供服务的网站要保存用户的信息,比如说 session 会话之类的东东,如果用户 1 第一次访问被分配到 RS1 响应,然后把 session 之类的信息保存到了 RS1,然后用户 1 第二次访问时,被分配到了 RS2 响应,以前保存的用户相关的信息没了?!这写问题就闹大了。所以,为了解决这类问题,就出现了所谓的源地址哈希,就是如果某个请求是第一次收到,我们就对请求报文的源 ip 地址进行 hash 计算,保存到一个哈希表中,并对应这个请求的 RS 地址,当第后面收到请求时,查看哈希表找到这个请求对应的 RS,就直接传给上次访问的 RS。这样就解决了,上述问题啦~

DH,Destination Hashing,目标地址哈希

动态方法如下:

LC:least connections,最少连接:即后端服务器那个处理的请求连接数最少就选哪个 RS,公式为 OverHead=Active*250+Inactive,活动链接数乘以 250 加上非活动连接数,越小越优先选择。不过此方式的虽然考虑到了后端的负载,但是并没区别出不同性能的服务器,所以此方法还是有不足之处、

WLC,Weight LC,加权最少连接,既然要烤炉每个设备的不同性能,我们也可以给不同性能的 RS 以不同的权重值,公式为 OverHead=(Active*256+inactive)/weight,假如有三台机器,权重值分别是 5,2,1. 当第一个请求进来时,因为三台机器都没有链接,都是 0,调度器就会根据 RS 列表从上到下一次调度,但是如果放在最前面的是性能最差的机器怎么办,如果我们想从第一个请求开始就根据负载能力调度,那么就有了下面这种方法。

SED,Shortest Expection Delay,最短延迟预期,因为相对于活动连接来说,非活动链接的消耗,小的可以忽略不计,所以我们可以直接不计算非活动链接数,以此来减小计算,SED 公式如下 Overhead=(activeconns+1)*256/weight,这样权重值大的一定会被先选到。不过依然有个问题,假如有两台机器,一台权重为 1,另一台权重为 10,当地一个请求进来时,经过计算第一台为 256,第二个为 25.6,然后就把第一个请求给第二台服务器,第二请求过来,经过计算依然给第 2 台服务器,如果一次过来 9 个请求,都会全部给第二台主机,那么第一台就一直处于等待状态,就算能力再差也至少得处理一个请求把~ 所以有下面这种调度方法。

NQ,Never Queue,永不排队。假如有两台 RS,从 vs 过来两个请求,第一个给权重大的那个 RS,第二个给空闲的哪个,后面的再根据负载计算进行分配,这样就保证了即使权重小也不会一直控线啦。后面还有 LBLS,Locality-Based LC,基于本地的 LC 和 LBLCR,LBLC with copy 带复制功能的 LBLC。

更多详情见请继续阅读下一页的精彩内容:http://www.linuxidc.com/Linux/2017-03/141929p2.htm

正文完
星哥说事-微信公众号
post-qrcode
 
星锅
版权声明:本站原创文章,由 星锅 2022-01-21发表,共计15200字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中