为了分散单机系统压力,一个最直接的想法就是把系统部署到几个服务器上,用户的访问请求就可以分散到各个服务器,那单台服务器的压力就小得多了。机器多了,每个机器一个IP, 用户可能就迷糊了,到底访问哪一个?
然后我们可以设置一下DNS,让我们网站的域名映射到多个服务器的IP,用户面对的是我们系统的域名,然后我们可以采用一种轮询的方式, 用户1的机器做域名解析的时候,DNS返回IP1, 用户2的机器做域名解析的时候,DNS返回IP2。
但这样做有个问题,由于DNS这个分层的系统中有缓存,用户端的机器也有缓存,如果某个机器出故障,域名解析仍然会返回那个出问题机器的IP,那所有访问该机器的用户都会出问题, 即使我们把这个机器的IP从DNS中删除也不行。因此,我们需要在中间加一个服务器LB,用来将外部来的请求转发给内网服务器,他有两个IP,一个对外(115.39.19.22),一个对内(192.168.0.100)。用户看到的是那个对外的IP。 后面的真正提供服务的服务器有三个,称为RS1, RS2,RS3, 他们的网关都指向LB。
用户发了一个HTTP的请求,想要访问网站的首页,这个HTTP请求被放到一个TCP报文中,再被放到一个IP数据报中, 最终的目的地就是我们的Load Balancer(115.39.19.22)。
如果Load Balancer想把这个数据包发给RS1(192.168.0.10), 就可以做点手脚,把这个数据包改成这样, 然后这个IP数据包就可以转发给RS1去处理了。
RS1处理完了,要返回首页的HTML,还要把HTTP报文层层封装:
由于LB是网关,它还会收到这个数据包,它就可以再次施展手段,把源地址和源端口都替换为自己的,然后发给客户。
总结了一下数据的流向:
客户端 --> Load Balancer --> RS --> Load Balancer --> 客户端,客户端根本就感受不到后面有好几台服务器在工作,后面的各个真实的服务器,可以有很多种策略:
轮询:这个最简单,就是一个挨一个轮换。
加权轮询:为了应对某些服务器性能好,可以让他们的权重高一点,被选中的几率大一点。
最少连接:哪个服务器处理的连接少,就发给谁。
加权最少连接:在最少连接的基础上,也加上权重。
这样又带来另外一个问题,对于用户的一个请求来说,可能会被分成多个数据包来发送, 如果这些数据包被我们的Load Balancer发到了不同的机器上,那就完全乱套了。因此Load Balancer必须得维护一个表,这个表需要记录下客户端的数据包被我们转发到了哪个真实的服务器上, 这样当下一个数据包到来时,我们就可以把它转发到同一个服务器上去。所以负载均衡软件需要是面向连接的,也就是OSI网络体系的第4层, 可以称为四层负载均衡。如果Load Balancer把HTTP层的报文数据取出来,根据其中的URL,浏览器,语言等信息,把请求分发到后面真实的服务器去,那就是七层的负载均衡了。
不难看出,Load Balancer存在着性能瓶颈:所有的流量都要通过它,它要修改客户发来的数据包, 还要修改发给客户的数据包。同时网络访问还有个极大的特点,那就是请求报文较短而响应报文往往包含大量的数据。这是很容易理解的,一个HTTP GET请求短得可怜,可是返回的HTML却是极长 -- 这就进一步加剧了Load Balancer修改数据包的工作。为了解决这个问题,需要把请求和响应分开处理,让Load Balancer只处理请求,让各个服务器把响应直接发给客户端。为了分开处理,首先让所有的服务器都有同一个IP(如图中115.39.19.22)。
这么多服务器都有同样的IP , 当IP数据包来的时候,到底应该由哪个服务器来处理?IP数据包其实是通过数据链路层发过来的,如下图:
客户端的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了?
既然Load Balancer得到了这个IP数据包, 它就可以用某个策略从RS1, RS2,RS3中选取一个服务器,例如RS1(192.168.0.10),把IP数据报原封不动, 封装成数据链路层的包(目的地是RS1的MAC地址),直接转发就可以了。
RS1(192.168.0.10)这个服务器收到了数据包,拆开一看,目的地IP是115.39.19.22,是自己的IP, 那就可以处理了。处理完了以后,RS1可以直接响应发回给客户端,完全不用再通过Load Balancer。因为自己的地址就是115.39.19.22。对于客户端来说,它看到的还是那个唯一的地址115.39.19.22, 并不知道后台发生了什么事情。
总结了一下数据的流向:
客户端 --> Load Balancer --> RS --> 客户端
版权所有
转载链接请注明出处