一、负载均衡:

在web系统优化中,我们有scale up和scale out两种思路,而后者又是一个非常经济、实惠的方案。在scale out优化中,一个主要的手段是使用负载均衡。本文先介绍一下负载均衡的原理。

如果把系统部署到几个服务器上,用户的访问请求就可以分散到各个服务器,那单台服务器的压力就小得多了。但带来的问题是:机器多了,每个机器一个IP, 用户(客户端)可能就迷糊了,到底访问哪一个?

负载均衡原理和双机热备_服务器

 

肯定不能把这些服务器暴露出去,从客户角度看来,最好是只有一个服务器。

1、考虑使用现成的中间层dns:

       让我们网站的域名映射到多个服务器的IP,用户面对的是我们系统的域名,然后我们可以采用一种轮询的方式, 用户1的机器做域名解析的时候,DNS返回IP1, 用户2的机器做域名解析的时候,DNS返回IP2...... 这样不就可以实现各个机器的负载相对均衡了吗?

负载均衡原理和双机热备_服务器_02

       这样做有个很要命的问题,由于DNS这个分层的系统中有缓存,用户端的机器也有缓存,如果某个机器出故障,域名解析仍然会返回那个出问题机器的IP,那所有访问该机器的用户都会出问题, 即使我们把这个机器的IP从DNS中删除也不行, 这就麻烦了。

2、负载均衡中间件:

负载均衡原理和双机热备_负载均衡_03

 

Load Balancer 简称LB , 有两个IP,一个对外(115.39.19.22),一个对内(192.168.0.100)。用户看到的是那个对外的IP。 后面的真正提供服务的服务器有三个,称为RS1, RS2,RS3, 他们的网关都指向LB。

1)数据包分析:

用户发了一个HTTP的请求,想要访问我们网站的首页,这个HTTP请求被放到一个TCP报文中,再被放到一个IP数据报中, 最终的目的地就是我们的Load Balancer(115.39.19.22),如下图。

负载均衡原理和双机热备_服务器_04

但是这个数据包一看就是发给Load Balancer的, 怎么发给后面的服务器?答案是可以想NAT那样,进行偷天换日。

比如Load Balancer想把这个数据包发给RS1(192.168.0.10), 就可以做点手脚,把这个数据包改成这样, 然后这个IP数据包就可以转发给RS1去处理了。

负载均衡原理和双机热备_负载均衡_05

RS1处理完了,要返回首页的HTML,还要把HTTP报文层层封装:

负载均衡原理和双机热备_客户端_06

由于LB是网关,它还会收到这个数据包,它就可以再次施展手段,把源地址和源端口都替换为自己的,然后发给客户就可以了。

负载均衡原理和双机热备_服务器_07

整个过程的数据流:客户端 --> Load Balancer --> RS --> Load Balancer --> 客户端

Load Balancer 怎么样才能选取后面的各个真实的服务器, 可以有很多种策略:轮训、加权、最少连接...

3、四层还是七层:

对于用户的一个请求来说,可能会被分成多个数据包来发送, 如果这些数据包被我们的Load Balancer发到了不同的机器上,那就完全乱套了。我们的Load Balancer必须得维护一个表,这个表需要记录下客户端的数据包被我们转发到了哪个真实的服务器上, 这样当下一个数据包到来时,我们就可以把它转发到同一个服务器上去。换句话说:这个负载均衡软件需要是面向连接的,也就是OSI网络体系的第4层, 可以称为四层负载均衡

与之对应的是七层负载均衡,如果我们的Load Balancer把HTTP层的报文数据取出来,根据其中的URL,浏览器,语言等信息,把请求分发到后面真实的服务器去,那就是七层的负载均衡了。

4、责任分离:

        上面的Load Balancer存在这样一个瓶颈:所有的流量都要通过它,它要修改客户发来的数据包, 还要修改发给客户的数据包。网络访问还有个极大的特点,那就是请求报文较短而响应报文往往包含大量的数据。这是很容易理解的,一个HTTP GET请求短得可怜,可是返回的HTML却是极长 -- 这就进一步加剧了Load Balancer修改数据包的工作。

于是进一步优化,需要将请求和相应分开。

首先,让所有的服务器都有同一个IP, 我们把他称为VIP吧(如图中115.39.19.22)

负载均衡原理和双机热备_客户端_08

每个实际服务器的loopback都绑定了那个VIP, 不过有问题啊,这么多服务器都有同样的IP , 当IP数据包来的时候,到底应该由哪个服务器来处理?注意,IP数据包其实是通过数据链路层发过来的,你看看这个图。

负载均衡原理和双机热备_负载均衡_09

 

客户端的HTTP报文再次被封装储层TCP报文,端口号是80, 然后IP数据报中的目的地是115.39.19.22(VIP)。图中的问号是目的地的MAC地址, 该怎么得到呢?对, 是使用ARP协议,把一个IP地址(115.39.19.22)给广播出去,然后具有此IP机器就会回复自己的MAC地址。 但是现在有好几台机器都有同一个IP(115.39.19.22), 怎么办?

答案是:我们只让Load Balancer 响应这个VIP地址(115.39.19.22)的ARP请求,对于RS1,RS2,RS3, 抑制住对这个VIP地址的ARP响应,不就可以唯一地确定Load Balancer了。

如此一来,客户端的请求,通过数据链路层到达LB,LB得到了这个IP数据包, 它就可以用某个策略从RS1, RS2,RS3中选取一个服务器,例如RS1(192.168.0.10),把IP数据报原封不动, 修改数据链路层的mac地址包(目的地是RS1的MAC地址),直接转发就可以了。

负载均衡原理和双机热备_客户端_10

RS1(192.168.0.10)这个服务器收到了数据包,拆开一看,目的地IP是115.39.19.22,是自己的IP, 那就可以处理了。处理完了以后,RS1可以直接响应发回给客户端,完全不用再通过Load Balancer。因为自己的地址就是115.39.19.22。对于客户端来说,它看到的还是那个唯一的地址115.39.19.22, 并不知道后台发生了什么事情。

注:这种方式,由于Load Balancer 根本不会修改IP数据报,其中的TCP的端口号自然也不会修改,这就要求RS1, RS2,RS3上的端口号必须得和Load Balancer一致才行。

整个过程的数据流:客户端 --> Load Balancer --> RS --> 客户端

综上,本文描述的负载均衡,其实就是著名开源软件LVS的原理,上面讲的两种负载均衡的方式,就是LVS的NAT和DR。

LVS是章文嵩博士在1998年5月成立的自由软件项目,现在已经是Linux内核的一部分。想想那时候我还在不亦乐乎地折腾个人网页,学会安装和使用Linux 没多久 , 服务器端开发也仅限于ASP,像LVS这种负载均衡的概念压根就没有听说过。 

编程语言可以学,差距也能弥补,但是这种境界和眼光的差距,简直就是巨大的鸿沟,难以跨越啊!

二、双机热备:

细心的你会发现,上面的负载均衡存在“单点”问题,有因为LB在业务的最前端,所以如何解决这种单点问题显得极为重要。该如何解决呢?上两台LB,那么问题又来了,客户端该如何访问这两个LB?如果用DNS就又回到前面的问题了;如果前面再加一个LB,那么岂不是又是单点?

于是,另辟蹊径。

1、双机热备:

在客户端看来,这两个Load Balancer 最好是一个整体,就像一个虚拟的服务器, 这个虚拟的服务对外提供一个IP (简称VIP)。

负载均衡原理和双机热备_服务器_11

两个Load Balancer中,一个叫做Master, 另外一个可以叫做Backup , 平时Master 负责干活, Backup待命,一旦Master挂掉, Backup 服务器立刻接管。  在外界看来,那个虚拟的服务器还在工作,并不知道内部发生的“大地震”。

1)如何实现IP漂移:

一个网卡可以设置多个地址,比如在Linux上eth0表示网卡1,它可以绑定一个IP, 与此同时,还可以设置一个ip alias  或者 secondary ip 。
eth0 --> 192.168.1.10
eth0:1  --> 192.168.1.100
我可以让这个192.168.1.100为VIP,如果服务器是Master, 就可以把这个IP给绑定上, 如果是Backup,那就不绑定。
换句话说,通过动态地绑定/解绑 就可以让这个VIP在两个服务器之间来回“漂移”了。

2)如何感知master挂了:

从道理上说,很简单,只需要让Master不断地给Backup发“心跳”消息即可(可以采用广播的方式发消息), 这个Backup(LoadBalancer2)得有个定时器, 如果在一个特定的时间(嗯,这个时间应该可以设置)内收不到心跳,那就认为Master完蛋了,就需要挺身而出。

过一段时间,如果LB1又活了,接下来该如何处理呢?

这里得定义一个策略,每个机器都得有个优先级(一个整数),在允许抢占的情况下,谁的优先级高,谁就是Master!

负载均衡原理和双机热备_客户端_12

2、mac地址漂移:

上面的方案中,我们可以很容易的让IP地址在两个主机之间漂移,实现主备切换, 但是MAC地址怎么办? 

因为在数据传输中,IP包是被封装在以太网帧中发送的,其中需要MAC地址。

负载均衡原理和双机热备_服务器_13

 

在发送第一个请求的时候,客户端(确切说是直接向Load Balancer发数据的那个机器)先是知道了VIP(如:192.168.1.100), 接下来它需要知道这个VIP的MAC地址,这样才能发送数据。

为了拿到MAC地址,它需要发起ARP查询: 这个VIP(192.168.1.100)的 MAC的地址是什么?

如果Load Balancer 1是Master ,就会回复: 是23:39:8D:9C:0A:33  (记为 MAC1)

这时候客户端就会缓存,记下来。

然后Load Balancer 1 挂掉, Load Balancer 2 成为 Master。

此时客户端如果再次发送数据,还会往MAC1去放送,于是就出错了。

解决方法:

也可以搞一个虚拟的MAC地址啊。无论是哪个机器成为Master, 每次响应ARP请求的时候,都返回这个虚拟的MAC地址。这样客户端面对的MAC地址就唯一了。看来虚拟IP + 虚拟的MAC 地址才能完整地解决问题!

综上,本节描述的就是著名的开元软件keepalived,keepalived软件会做初始化,把虚拟的ip和mac都设置好。

 

3、资源利用率:

到这里,有的同学可能会发现,双机热备虽然很完善,可以很完美的解决单点问题,但是存在着“资源利用率低”的问题,因为在同一时刻总是有一个服务在“休息”。针对这个问题,其实我们在现实业务中是可以完全避免的,例如:两台LB都作为master,分别为不同业务做负载均衡,并且同时设置对方为slave,这样就可以做到既可靠,又不浪费。

声明:本文是摘自liuxin老师的文章https://mp.weixin.qq.com/s/ZK3HURE6M6p3BDKI-r_UKQ和https://mp.weixin.qq.com/s?__biz=MzAxOTc0NzExNg==&mid=2665514539&idx=1&sn=e36b47d93396844bb1a46c82c9b65df7&chksm=80d67e68b7a1f77e80052ea57e4676ea79c5c53b49a038f597ee99dba54ad15d2abdfe36433c&scene=21#wechat_redirect