企业级负载均衡解决方案之一:Google四层负载均衡解决方案Meglev

一、前言

在之前的文章《IPVS概览》中给出了IPVS作为负载均衡解决方案的一些技术要求,但是从产品部署的角度讲,IPVS比较适用的场景还是小规模的内网或者外网部署。由于IPVS是使用Linux内核协议栈进行接入数据包的处理,所以接入的RPS最多可能在数万或者数十万级别,而考虑到像google、阿里或者腾讯,它们面临的总接入RPS应该是在数十万甚至上百万级别,而在热点事件发生的时候,可能要到数千万甚至上亿的级别(比如google的正常情况下搜索引擎系统的接入应该在数十万级别)。

这种数量级别的访问接入,接入请求来源的分布几乎是全球化的,后端服务器的数量应该是几万或者几十万甚至百万级别的,而且这些后端物理机的分布也是全球化的。这样的大规模分布式系统,单个IPVS主机是根本不能处理的,需要一个系统性的方案来保证任意位置接入的低时延和响应的低时延,并且系统处理能力能够动态平滑的横向扩展。Google的Meglev就是这样一个满足千万级分布式别接入需求的系统性解决方案,粗略的将可以把Meglev看作是一个分布式的带状态的单机性能也显著提升了的IPVS集群。

转载自https://blog.csdn.net/cloudvtech

二、Meglev概览

Meglev是Google基于普通商用Linux服务器打造的分布式负载均衡,主要负责维护一个分布式的后端服务器集群,对接入流量进行负载均衡,类似于LVS-DR模式,Meglev不负责处理任何响应流量,所有的响应流量都是后端服务器直接返回给请求端的。

企业级负载均衡解决方案之一:Google四层负载均衡解决方案Meglev

根据这张介绍Meglev的论文里面提供的流量示意图,可以看到如下接入和响应数据流:

  • 客户端查询域名,DNS根据用户地理位置返回合适的接入VIP
  • 客户端请求被路由到某个区域的接入路由器
  • 接入路由器通过ECMP协议选择后端一个Maglev实例,并将请求发送给这个实例
  • Maglev通过load balance策略选择一个后端服务器,并将请求发送这个这个后端服务器
  • 后端服务器处理这个请求并直接把响应发回给客户端

所以可以看到Meglev解决方案在域名查询层面(一个域名对应多个VIP),路由接入层面(一个VIP对应多个Meglev服务器)、后端服务器接入层(一个Meglev对应多个后端服务器)面都进行了负载均衡的处理来满足这种大范围大规模分布式接入需求。

Meglev的最终目标是在大流量分布式接入的情况下:

  • 保证接入流量的均衡分布
  • 维持每个连接的状态(同一个连接的包必须进入同一个后端服务器)
  • 每个Meglev服务器都有很高的接入RPS

转载自https://blog.csdn.net/cloudvtech

三、Meglev所使用的技术概览

3.1 路由器接入层面的负载均衡

在请求到达接入路由器之后,由于路由器后端绑定VIP的是一个Meglev服务器集群,所以接入路由器需要根据请求自带的信息来选择合适的后端作为服务的接入点,Meglev使用ECMP协议来选择一个Meglev服务器进一步处理接入请求。但是由于多数路由器或者交换机的ECMP协议都不支持一致性hash算法,所以需要Meglev的数据包分发算法来保证同一个连接的数据包能被同一个后端服务器处理。

每个Meglev服务器都会向接入路由器或者交换机announce基于BGP链路信息(同一个VIP的路径cost是一样的),来让接入设备知道每个Meglev服务器可以作为哪些VIP的接入点。所以针对某个VIP,接入设备上可能有多个Meglev服务器作为后续处理的可选节点,而ECMP协议通过基于5-tuple(源/目的IP地址、源/目的端口、所使用的协议)的一致性hash算法可以保证每个Meglev服务器有几乎等量的接入请求被处理。

3.2 Meglev服务器的技术

每个Meglev服务器由一个controller和一个forwarder组成。controller监控forwarder的状态并根据监控结果来确定是否要对外发布BGP路径cost信息以便接收外部处理请求。forwarder则进行数据包的接收、后端服务器选择和数据包往后端服务器的转发。

forwarder直接从NIC接收数据包,根据数据包TCP连接5-tuple信息选择后端,然后生产一个GRE/IP封包(类似于IPVS-TUN模式),最后将数据包直接发送到NIC。在forwarder内部有如下一些优化:

  • 整个处理过程都是在用户态进行的,完全bypass Linux内核(使用了和DPDK类似的用户态网卡驱动技术)
  • 在用户态数据包处理过程中,所有的处理线程都会独占特定的CPU,避免cache miss和memory contention
  • 和网卡共享大页内存,整个处理过程没有任何数据拷贝,是有队列指针的移动
  • 所有数据包处理线程之间不共享任何数据,Meglev开发的一致性hash算法是thread local的
  • 数据包处理线程尽可能以批量的形式处理数据包(这个和VPP优点类似),从而让一批数据包分摊中间的各种开销

通过这种优化,Meglev单机可以达到针对小包的在10Gbps网络的线速转发(100 bytes [email protected])。在一个以64KBytes(5-tuple)数据包为基准的测试中,Meglev的表现如下:

企业级负载均衡解决方案之一:Google四层负载均衡解决方案Meglev


3.3 后端服务器接入层面的负载均衡

Meglev根据数据包TCP连接5-tuple信息选择后端,通过Meglve的一致性hash算法,算出一个hash值,根据hash值来选择后端服务器,如果后端服务器还不在connection tracking的表里面,则将数据包和后端的对应关系加入这个表,该TCP连接后续的数据包都会根据这个表项直接获得后端服务器,这样可以保证同一个TCP连接的数据包总是被同一个后端服务器处理。这里需要考虑的问题是connection tracking表项是占用一定内存空间的,在Google这样的网站,大量的接入请求会导致connection tracking表占用大量内存空间。

在选择好后端之后,forwarder会将数据包封装在一个GRE隧道里面发送给选择的后端服务器,后端服务器接收到这个GRE包之后会解封并且处理这个接入请求,处理好请求之后,后端服务器会使用VIP作为响应数据包的源地址,将响应直接返回给客户端。

3.4 failure情况下的连接状态保持

Meglev是一个三层架构的系统,其中的Meglev服务器是以集群的形式组成服务实体接入前端路由器/交换机,而后端服务器也是以集群的形式接入Meglev服务器的,这种接入方式在遇到需要保持状态的TCP连接请求来说,要求前端路由器和Meglev服务器能够有某种机制来保证无论两个集群出现什么样的变动(比如集群中节点的加入和退出以及升级处理),绝大多数的请求都不受影响并且能均衡分布。

一般来讲,一个负载均衡方案要考虑两个方面:

  • 接入请求是否均衡的分配到后端服务器
  • 在集群状态出现波动的时候对连接的影响尽量小

分配的均衡性和出错之后影响的大小其实是一个需要平衡的矛盾,为了在满足Google网络接入特点的前提下平衡这两个方面,Meglev自己开发了一个local consistent hashing算法,这个算法在确保均衡性的前提下,可以接受在集群状态出错的时候对有状态连接一定程度的影响,这个算法被使用在Meglev服务器选择后端服务器的流程中。

这个local consistent hashing使用一个本地(thread local和Meglev server local)计算出来的lookup table,在不需要跨线程协作和跨Meglev节点通信的情况下,维持全局一致性的接入请求均衡转发,保证同一个连接的数据包可以被同一个后端服务器处理,同时在Megelev服务器和后端服务器出错的情况下也能保证最小程度的影响。

这个local consistent hashing算法对于集群错误状态的容忍度测试结果如下:

企业级负载均衡解决方案之一:Google四层负载均衡解决方案Meglev

3.5 其它技术

当然,由于google是一个多样性网络服务提供商(根据Meglev论文提供的信息,GCE也是使用Meglev来进行流量负载均衡),所以Meglev要面临的是相对复杂的网络接入请求,所以还有许多技术被引入来满足这些接入请求,比如:

  • IP分段的处理
  • 集群整体失效的处理

等更多的技术细节请参考Meglev的原始论文

转载自https://blog.csdn.net/cloudvtech