负载均衡之基于L7负载

来源:互联网 发布:数据分析需求文档 编辑:程序博客网 时间:2024/04/28 15:05

L7负载平衡
  
另一种较为常用的负载平衡解决方案则是L7负载平衡。顾名思义,其主要通过OSI模型中的第七层应用层中的数据决定如何分发负载。
  
在运行时,L7负载平衡服务器上的操作系统会将接收到的各个数据包组织成为用户请求,并根据在该请求中所包含的的数据来决定由哪个服务实例来对该请求进行处理。其运行流程图大致如下所示:
这里写图片描述
相较于L3/4负载平衡服务所使用的数据,L7负载平衡服务所使用的应用层数据更贴近服务本身,因此其具有更精确的负载平衡行为。
  
在前面对L3/4负载平衡的讲解中我们已经介绍过,对于某些具有关联关系的各个请求,L3/4负载平衡服务器会根据某些算法(如计算IP的哈希值)来决定处理该请求的服务实例。但是这种方法并不是很稳定。当一个服务实例失效或用户的IP发生变化的时候,用户与服务实例之间的对应关系就将发生改变。此时用户原有的会话数据在新的服务实例上并不存在,进而导致一系列问题。
  
其实产生这个问题的最根本原因就是用户与服务实例之间的关联关系是通过某些外部环境创建的,而并非由用户/服务实例本身来管理。因此它不能抵御外部环境变化的冲击。如果要在用户和服务实例之间建立稳定的关联关系,那么就需要一种稳定的在用户和服务实例之间传递的数据。在Web服务中,这种数据就是Cookie。
  
简单地说,基于Cookie的负载平衡服务实际上就是分析用户请求中的某个特定Cookie并根据其值决定需要分发到的目标地址。其主要分为两种方式:Cookie Learning以及Cookie Insertion。
  
Cookie Learning是不具有侵入性的一种解决方案。其通过分析用户与服务实例通讯过程中所传递的Cookie来决定如何分派负载:在用户与服务第一次通讯时,负载平衡服务将找不到相应的Cookie,因此其将会把该请求根据负载平衡算法分配到某个服务实例上。而在服务实例返回的时候,负载平衡服务器将会把对应的Cookie以及服务实例的地址记录在负载平衡服务器中。当用户再次与服务通讯时,负载平衡服务器就会根据Cookie中所记录的数据找到前一次服务该用户的服务实例,并将请求转发到该服务实例上。
这里写图片描述
这么做的最大缺点就是对高可用性的支持很差。如果一旦负载平衡服务器失效,那么在该负载平衡服务器上所维护的Cookie和服务实例之间的匹配关系将全部丢失。这样当备份负载平衡服务器启动之后,所有的用户请求都将被定向到随机的服务实例。
  
而另一个问题就是会话维护功能对内存的消耗。与L3/4服务器上的会话维护不同,一个Cookie的失效时间可能非常长,至少在一次用户使用中可能会持续几个小时。对于一个访问量达到每秒上万次的系统而言,负载平衡服务器需要维护非常多的会话,甚至可能会将服务器的内存消耗殆尽。反过来,如果将负载平衡服务器中的Cookie过期时间设置得太短,那么当用户重新访问负载平衡服务器的时候,其将被导向到一个错误的服务实例。
  
除了Cookie Learning 之外,另一种常用的方法就是Cookie Insertion。其通过向响应中添加Cookie以记录被分派到的服务实例,并在下一次处理请求时根据该Cookie所保存的值来决定分发到的服务实例。在用户与服务器进行第一次通讯的时候,负载平衡服务器将找不到分派记录所对应的Cookie,因此其会根据负载平衡算法为该请求分配一个服务实例。在接收到服务实例所返回的数据之后,负载平衡服务器将会向响应中插入一个Cookie,以记录该服务实例的ID。当用户再次发送请求到负载平衡服务器时,其将根据该Cookie里所记录的服务实例的ID派发该请求。
这里写图片描述
相较于Cookie Learning,Cookie Insertion不需要在内存中维护Cookie与各个服务实例的对应关系,而且在当前负载平衡服务器失效的时候,备用负载平衡服务器也可以根据Cookie中所记录的信息正确地派发各个请求。
  
当然,Cookie Insertion也有缺陷。最常见的问题就是浏览器以及用户自身对Cookie的限制。在Cookie Insertion中,我们需要插入一个额外的Cookie 来记录分配给当前用户的服务实例。但是在某些浏览器中,特别是移动浏览器中,常常会限制Cookie的个数,甚至只允许出现一个 Cookie。为了解决这个问题,负载平衡服务器也会使用一些其它方法。如Cookie Modification,即修改一个已有的Cookie使其包含服务实例的ID。
  
而在用户禁用了Cookie的时候,Cookie Insertion将是完全失效的。此时负载平衡服务所能利用的将仅仅是JSESSIONID等信息。因此在一个L7负载平衡服务器中,Cookie Learning和Cookie Insertion常常同时使用:Cookie Learning会在用户启用Cookie的时候起主要作用,而在Cookie被用户禁用的情况下则使用Cookie Learning来根据JSESSIONID来保持用户与服务实例之间的关联关系。
  
或许您会想:L3/4负载平衡服务器在处理各个关联请求的时候是通过IP的哈希值来决定处理该请求的服务实例的。既然这些基于Cookie的解决方案能达到100%的准确,为什么我们不在L3/4负载平衡服务器中使用它们呢?答案是:由于L3/4负载平衡服务器主要关注于数据包级别的转发,而Cookie信息则藏匿于数据包之中,因此L3/4负载平衡服务器很难决定单一的数据包该如何转发。
  
例如在执行Cookie Insertion操作的时候,原有数据包中的所有数据都将被后移。此时需要负载平衡服务器接收到所有数据包之后才能完成:
这里写图片描述
试想一下接收所有数据包所可能发生的事情吧。在网络的一端发送多个数据包的时候,网络的另一端所接收到的数据包的顺序可能与原有的发送顺序并不一致。甚至在网络拥堵的时候,某些数据包可能会丢失,进而再次加长接收到所有数据包所需要的时间。
  
因此相较于将数据包直接转发的方法,等待所有的数据包到齐然后再插入Cookie的性能非常差。在后面对于解决方案的讲解中您会看到,L3/4负载平衡服务器对于性能的要求一般来说是很高的,而L7负载平衡服务器则可以通过一个集群来解决自身的性能问题。基于DNS的负载平衡,L3/4负载平衡服务器以及L7负载平衡服务器常常协同工作,以组成一个具有高可用性以及高可扩展性的系统。

1 0