LVS

目 录

  1. LVS
    1. 项目理论
      1. 项目介绍
      2. 体系结构
      3. IP负载均衡
      4. 负载调度
    2. 安装配置
      1. 简介
      2. 组件
      3. 背景
      4. 硬件/网络的要求
      5. 路由的必要条件
      6. 节点内部连接的必要条件
      7. 安装软件
      8. 配置
      9. 例子
    3. 简单实例


LVS

   LVS是章文嵩博士发起和领导的优秀的集群解决方案,许多商业的集群产品,比如RedHat的Piranha,TurboLinux公司的Turbo Cluster等,都是基于LVS的核心代码的。在现实的应用中,LVS得到了大量的部署,请参考http://www.linuxvirtualserver.org/deployment.html

   关于Linux LVS的工作原理和更详细的信息,请参考http://www.linuxvirtualserver.org。

[目录]


项目理论

[目录]


项目介绍

    本文介绍了Linux服务器集群系统――LVS(Linux Virtual Server)项目的产生背景和目标,并描述了LVS服务器集群框架及目前提供的软件,列举LVS集群系统的特点和一些实际应用,最后,本文谈论了LVS项目的开发进展和开发感触。

1. 背景

    当今计算机技术已进入以网络为中心的计算时期。由于客户/服务器模型的简单性、易管理性和易维护性,客户/服务器计算模式在网上被大量采用。在九十年代中期,万维网(World Wide Web)的出现以其简单操作方式将图文并茂的网上信息带给普通大众,Web也正在从一种内容发送机制成为一种服务平台,大量的服务和应用(如新闻服务、网上银行、电子商务等)都是围绕着Web进行。这促进Internet用户剧烈增长和Internet流量爆炸式地增长,图1显示了1995至2000年与Internet连接主机数的变化情况,可见增长趋势较以往更迅猛。

    Internet的飞速发展给网络带宽和服务器带来巨大的挑战。从网络技术的发展来看,网络带宽的增长远高于处理器速度和内存访问速度的增长,如100M Ethernet、ATM、Gigabit Ethernet等不断地涌现,10Gigabit Ethernet即将就绪,在主干网上密集波分复用(DWDM)将成为宽带IP的主流技术[2,3],Lucent已经推出在一根光纤跑800Gigabit的WaveStar? OLS 800G产品[4]。所以,我们深信越来越多的瓶颈会出现在服务器端。很多研究显示Gigabit Ethernet在服务器上很难使得其吞吐率达到1Gb/s的原因是协议栈(TCP/IP)和操作系统的低效,以及处理器的低效,这需要对协议的处理方法、操作系统的调度和IO的处理作更深入的研究。在高速网络上,重新设计单台服务器上的网络服务程序也是个重要课题。

    比较热门的站点会吸引前所未有的访问流量,例如根据Yahoo的新闻发布,Yahoo已经每天发送6.25亿页面。一些网络服务也收到巨额的流量,如American Online的Web Cache系统每天处理50.2亿个用户访问Web的请求,每个请求的平均响应长度为5.5Kbytes。与此同时,很多网络服务因为访问次数爆炸式地增长而不堪重负,不能及时处理用户的请求,导致用户进行长时间的等待,大大降低了服务质量。如何建立可伸缩的网络服务来满足不断增长的负载需求已成为迫在眉睫的问题。

    大部分网站都需要提供每天24小时、每星期7天的服务,对电子商务等网站尤为突出,任何服务中断和关键性的数据丢失都会造成直接的商业损失。例如,根据Dell的新闻发布[6],Dell现在每天在网站上的交易收入为一千四百万美元,一个小时的服务中断都会造成平均五十八万美元的损失。所以,这对网络服务的可靠性提出了越来越高的要求。

    现在Web服务中越来越多地使用CGI、动态主页等CPU密集型应用,这对服务器的性能有较高要求。未来的网络服务会提供更丰富的内容、更好的交互性、更高的安全性等,需要服务器具有更强的CPU和I/O处理能力。例如,通过HTTPS(Secure HTTP)取一个静态页面需要的处理性能比通过HTTP的高一个数量级,HTTPS正在被电子商务站点广为使用。所以,网络流量并不能说明全部问题,要考虑到应用本身的发展也需要越来越强的处理性能。

    因此,对用硬件和软件方法实现高可伸缩、高可用网络服务的需求不断增长,这种需求可以归结以下几点:

    ·可伸缩性(Scalability),当服务的负载增长时,系统能被扩展来满足需求,且不降低服务质量。
    ·高可用性(Availability),尽管部分硬件和软件会发生故障,整个系统的服务必须是每天24小时每星期7天可用的。
    ·可管理性(Manageability),整个系统可能在物理上很大,但应该容易管理。
    ·价格有效性(Cost-effectiveness),整个系统实现是经济的、易支付的。

2. 服务器集群系统

    对称多处理(Symmetric Multi-Processor,简称SMP)是由多个对称的处理器、和通过总线共享的内存和I/O部件所组成的计算机系统。SMP是一种低并行度的结构,是我们通常所说的"紧耦合多处理系统",它的可扩展能力有限,但SMP的优点是单一系统映像(Single System Image),有共享的内存和I/O,易编程。

    由于SMP的可扩展能力有限,SMP服务器显然不能满足高可伸缩、高可用网络服务中的负载处理能力不断增长需求。随着负载不断增长,会导致服务器不断地升级。这种服务器升级有下列不足:一是升级过程繁琐,机器切换会使服务暂时中断,并造成原有计算资源的浪费;二是越往高端的服务器,所花费的代价越大;三是SMP服务器是单一故障点(Single Point of Failure),一旦该服务器或应用软件失效,会导致整个服务的中断。

    通过高性能网络或局域网互联的服务器集群正成为实现高可伸缩的、高可用网络服务的有效结构。这种松耦合结构的服务器集群系统有下列优点:

性能
    网络服务的工作负载通常是大量相互独立的任务,通过一组服务器分而治之,可以获得很高的整体性能。

性能/价格比
    组成集群系统的PC服务器或RISC服务器和标准网络设备因为大规模生产降低成本,价格低,具有最高的性能/价格比。若整体性能随着结点数的增长而接近线性增加,该系统的性能/价格比接近于PC服务器。所以,这种松耦合结构比紧耦合的多处理器系统具有更好的性能/价格比。

可伸缩性
    集群系统中的结点数目可以增长到几千个,乃至上万个,其伸缩性远超过单台超级计算机。

高可用性
    在硬件和软件上都有冗余,通过检测软硬件的故障,将故障屏蔽,由存活结点提供服务,可实现高可用性。

当然,用服务器集群系统实现可伸缩网络服务也存在很多挑战性的工作:

透明性(Transparency)
    如何高效地使得由多个独立计算机组成的松藕合的集群系统构成一个虚拟服务器;客户端应用程序与集群系统交互时,就像与一台高性能、高可用的服务器交互一样,客户端无须作任何修改。部分服务器的切入和切出不会中断服务,这对用户也是透明的。

性能(Performance)
    性能要接近线性加速,这需要设计很好的软硬件的体系结构,消除系统可能存在的瓶颈。将负载较均衡地调度到各台服务器上。

高可用性(Availability)
需要设计和实现很好的系统资源和故障的监测和处理系统。当发现一个模块失败时,要这模块上提供的服务迁移到其他模块上。在理想状况下,这种迁移是即时的、自动的。

可管理性(Manageability)
    要使集群系统变得易管理,就像管理一个单一映像系统一样。在理想状况下,软硬件模块的插入能做到即插即用(Plug & Play)。

可编程性(Programmability)
    在集群系统上,容易开发应用程序。

3. Linux Virtual Server项目

    针对高可伸缩、高可用网络服务的需求,我们给出了基于IP层和基于内容请求分发的负载平衡调度解决方法,并在Linux内核中实现了这些方法,将一组服务器构成一个实现可伸缩的、高可用网络服务的虚拟服务器。

    虚拟服务器的体系结构如图2所示,一组服务器通过高速的局域网或者地理分布的广域网相互连接,在它们的前端有一个负载调度器(Load Balancer)。负载调度器能无缝地将网络请求调度到真实服务器上,从而使得服务器集群的结构对客户是透明的,客户访问集群系统提供的网络服务就像访问一台高性能、高可用的服务器一样。客户程序不受服务器集群的影响不需作任何修改。系统的伸缩性通过在服务机群中透明地加入和删除一个节点来达到,通过检测节点或服务进程故障和正确地重置系统达到高可用性。由于我们的负载调度技术是在Linux内核中实现的,我们称之为Linux虚拟服务器(Linux Virtual Server)。

    在1998年5月,我成立了Linux Virtual Server的自由软件项目,进行Linux服务器集群的开发工作。同时,Linux Virtual Server项目是国内最早出现的自由软件项目之一。

    Linux Virtual Server项目的目标:使用集群技术和Linux操作系统实现一个高性能、高可用的服务器,它具有很好的可伸缩性(Scalability)、可靠性(Reliability)和可管理性(Manageability)。

    目前,LVS项目已提供了一个实现可伸缩网络服务的Linux Virtual Server框架,如图3所示。在LVS框架中,提供了含有三种IP负载均衡技术的IP虚拟服务器软件IPVS、基于内容请求分发的内核Layer-7交换机KTCPVS和集群管理软件。可以利用LVS框架实现高可伸缩的、高可用的Web、Cache、Mail和Media等网络服务;在此基础上,可以开发支持庞大用户数的、高可伸缩的、高可用的电子商务应用。

3.1 IP虚拟服务器软件IPVS

    在调度器的实现技术中,IP负载均衡技术是效率最高的。在已有的IP负载均衡技术中有通过网络地址转换(Network Address Translation)将一组服务器构成一个高性能的、高可用的虚拟服务器,我们称之为VS/NAT技术(Virtual Server via Network Address Translation),大多数商品化的IP负载均衡调度器产品都是使用此方法,如Cisco的LocalDirector、F5的Big/IP和Alteon的ACEDirector。在分析VS/NAT的缺点和网络服务的非对称性的基础上,我们提出通过IP隧道实现虚拟服务器的方法VS/TUN(Virtual Server via IP Tunneling),和通过直接路由实现虚拟服务器的方法VS/DR(Virtual Server via Direct Routing),它们可以极大地提高系统的伸缩性。所以,IPVS软件实现了这三种IP负载均衡技术,它们的大致原理如下(我们将在其他章节对其工作原理进行详细描述),

Virtual Server via Network Address Translation(VS/NAT)
    通过网络地址转换,调度器重写请求报文的目标地址,根据预设的调度算法,将请求分派给后端的真实服务器;真实服务器的响应报文通过调度器时,报文的源地址被重写,再返回给客户,完成整个负载调度过程。

Virtual Server via IP Tunneling(VS/TUN)
    采用NAT技术时,由于请求和响应报文都必须经过调度器地址重写,当客户请求越来越多时,调度器的处理能力将成为瓶颈。为了解决这个问题,调度器把请求报文通过IP隧道转发至真实服务器,而真实服务器将响应直接返回给客户,所以调度器只处理请求报文。由于一般网络服务应答比请求报文大许多,采用VS/TUN技术后,集群系统的最大吞吐量可以提高10倍。

Virtual Server via Direct Routing(VS/DR)
    VS/DR通过改写请求报文的MAC地址,将请求发送到真实服务器,而真实服务器将响应直接返回给客户。同VS/TUN技术一样,VS/DR技术可极大地提高集群系统的伸缩性。这种方法没有IP隧道的开销,对集群中的真实服务器也没有必须支持IP隧道协议的要求,但是要求调度器与真实服务器都有一块网卡连在同一物理网段上。

    针对不同的网络服务需求和服务器配置,IPVS调度器实现了如下八种负载调度算法:

轮叫(Round Robin)
    调度器通过"轮叫"调度算法将外部请求按顺序轮流分配到集群中的真实服务器上,它均等地对待每一台服务器,而不管服务器上实际的连接数和系统负载。

加权轮叫(Weighted Round Robin)
    调度器通过"加权轮叫"调度算法根据真实服务器的不同处理能力来调度访问请求。这样可以保证处理能力强的服务器处理更多的访问流量。调度器可以自动问询真实服务器的负载情况,并动态地调整其权值。

最少链接(Least Connections)
    调度器通过"最少连接"调度算法动态地将网络请求调度到已建立的链接数最少的服务器上。如果集群系统的真实服务器具有相近的系统性能,采用"最小连接"调度算法可以较好地均衡负载。

加权最少链接(Weighted Least Connections)
    在集群系统中的服务器性能差异较大的情况下,调度器采用"加权最少链接"调度算法优化负载均衡性能,具有较高权值的服务器将承受较大比例的活动连接负载。调度器可以自动问询真实服务器的负载情况,并动态地调整其权值。

基于局部性的最少链接(Locality-Based Least Connections)
    "基于局部性的最少链接" 调度算法是针对目标IP地址的负载均衡,目前主要用于Cache集群系统。该算法根据请求的目标IP地址找出该目标IP地址最近使用的服务器,若该服务器是可用的且没有超载,将请求发送到该服务器;若服务器不存在,或者该服务器超载且有服务器处于一半的工作负载,则用"最少链接"的原则选出一个可用的服务器,将请求发送到该服务器。

带复制的基于局部性最少链接(Locality-Based Least Connections with Replication)
    "带复制的基于局部性最少链接"调度算法也是针对目标IP地址的负载均衡,目前主要用于Cache集群系统。它与LBLC算法的不同之处是它要维护从一个目标IP地址到一组服务器的映射,而LBLC算法维护从一个目标IP地址到一台服务器的映射。该算法根据请求的目标IP地址找出该目标IP地址对应的服务器组,按"最小连接"原则从服务器组中选出一台服务器,若服务器没有超载,将请求发送到该服务器,若服务器超载;则按"最小连接"原则从这个集群中选出一台服务器,将该服务器加入到服务器组中,将请求发送到该服务器。同时,当该服务器组有一段时间没有被修改,将最忙的服务器从服务器组中删除,以降低复制的程度。

目标地址散列(Destination Hashing)
    "目标地址散列"调度算法根据请求的目标IP地址,作为散列键(Hash Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器,否则返回空。

源地址散列(Source Hashing)
    "源地址散列"调度算法根据请求的源IP地址,作为散列键(Hash Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器,否则返回空。

3.2 内核Layer-7交换机KTCPVS

    在基于IP负载调度技术中,当一个TCP连接的初始SYN报文到达时,调度器就选择一台服务器,将报文转发给它。此后通过查发报文的IP和TCP报文头地址,保证此连接的后继报文被转发到该服务器。这样,IPVS无法检查到请求的内容再选择服务器,这就要求后端服务器组提供相同的服务,不管请求被发送到哪一台服务器,返回结果都是一样的。但是,在有些应用中后端服务器功能不一,有的提供HTML文档,有的提供图片,有的提供CGI,这就需要基于内容的调度(Content-Based Scheduling)。

    由于用户空间TCP Gateway的开销太大,我们提出在操作系统的内核中实现Layer-7交换方法,来避免用户空间与核心空间的切换和内存复制的开销。在Linux操作系统的内核中,我们实现了Layer-7交换,称之为KTCPVS(Kernel TCP Virtual Server)。目前,KTCPVS已经能对HTTP请求进行基于内容的调度,但它还不很成熟,在其调度算法和各种协议的功能支持等方面,有大量的工作需要做。

    虽然应用层交换处理复杂,它的伸缩性有限,但应用层交换带来以下好处:

    相同页面的请求被发送到同一服务器,可以提高单台服务器的Cache命中率。
    一些研究[5]表明WEB访问流中存在局部性。Layer-7交换可以充分利用访问的局部性,将相同类型的请求发送到同一台服务器,使得每台服务器收到的请求具有更好的相似性,可进一步提高单台服务器的Cache命中率。
    后端服务器可运行不同类型的服务,如文档服务,图片服务,CGI服务和数据库服务等。
4. LVS集群的特点

LVS集群的特点可以归结如下:

功能
    有实现三种IP负载均衡技术和八种连接调度算法的IPVS软件。在IPVS内部实现上,采用了高效的Hash函数和垃圾回收机制,能正确处理所调度报文相关的ICMP消息(有些商品化的系统反而不能)。虚拟服务的设置数目没有限制,每个虚拟服务有自己的服务器集。它支持持久的虚拟服务(如HTTP Cookie和HTTPS等需要该功能的支持),并提供详尽的统计数据,如连接的处理速率和报文的流量等。针对大规模拒绝服务(Deny of Service)攻击,实现了三种防卫策略。
有基于内容请求分发的应用层交换软件KTCPVS,它也是在Linux内核中实现。有相关的集群管理软件对资源进行监测,能及时将故障屏蔽,实现系统的高可用性。主、从调度器能周期性地进行状态同步,从而实现更高的可用性。

适用性
    后端服务器可运行任何支持TCP/IP的操作系统,包括Linux,各种Unix(如FreeBSD、Sun Solaris、HP Unix等),Mac/OS和Windows NT/2000等。
负载调度器能够支持绝大多数的TCP和UDP协议:


协议 内 容
    TCP HTTP,FTP,PROXY,SMTP,POP3,IMAP4,DNS,LDAP,HTTPS,SSMTP等
UDP DNS,NTP,ICP,视频、音频流播放协议等
无需对客户机和服务器作任何修改,可适用大多数Internet服务。


性能
    LVS服务器集群系统具有良好的伸缩性,可支持几百万个并发连接。配置100M网卡,采用VS/TUN或VS/DR调度技术,集群系统的吞吐量可高达1Gbits/s;如配置千兆网卡,则系统的最大吞吐量可接近10Gbits/s。

可靠性
    LVS服务器集群软件已经在很多大型的、关键性的站点得到很好的应用,所以它的可靠性在真实应用得到很好的证实。有很多调度器运行一年多,未作一次重启动。

软件许可证
    LVS集群软件是按GPL(GNU Public License)许可证发行的自由软件,这意味着你可以得到软件的源代码,有权对其进行修改,但必须保证你的修改也是以GPL方式发行。

5. LVS集群的应用

    LVS项目从成立到现在为止,受到不少关注,LVS集群系统已被应用于很多重负载的站点,就我所知该系统已在美、英、德、澳等国的几十个站点上正式使用。

    我们没有上百台机器和高速的网络来实际测试LVS的终极性能,所以举LVS的应用实例来说明LVS的高性能和稳定性。我们所知的一些大型LVS应用实例如下:

    英国国家JANET Cache Service(wwwcache.ja.net)是为英国150所以上的大学提供Web Cache服务。他们用28个结点的LVS集群代替了原有现50多台相互独立的Cache服务器,用他们的话说现在速度就跟夏天一样,因为夏天是放假期间没有很多人使用网络。

    Linux的门户站点(www.linux.com)用LVS将很多台VA Linux SMP服务器组成高性能的WEB服务,已使用将近一年。

    SourceForge(sourceforge.net)是在全球范围内为开发源码项目提供WEB、FTP、Mailing List和CVS等服务,他们也使用LVS将负载调度到十几台机器上。

    世界上最大的PC制造商之一采用了两个LVS集群系统,一个在美洲,一个在欧洲,用于网上直销系统。

    以RealPlayer提供音频视频服务而闻名的Real公司(www.real.com)使用由20台服务器组成的LVS集群,为其全球用户提供音频视频服务。在2000年3月时,整个集群系统已收到平均每秒20,000个连接的请求流。

    NetWalk(www.netwalk.com)用多台服务器构造LVS系统,提供1024个虚拟服务,其中本项目的一个美国镜像站点(www.us.linuxvirtualserver.org)。

    RedHat(www.redhat.com)从其6.1发行版起已包含LVS代码,他们开发了一个LVS集群管理工具叫Piranha,用于控制LVS集群,并提供了一个图形化的配置界面。

    VA Linux(www.valinux.com)向客户提供基于LVS的服务器集群系统,并且提供相关的服务和支持。

    TurboLinux的"世界一流Linux集群产品"TurboCluster实际上是基于LVS的想法和代码的,只是他们在新闻发布和产品演示时忘了致谢。

    红旗Linux和中软都提供基于LVS的集群解决方案,并在2000年9月召开的Linux World China 2000上展示。

    在这里,再引用两位LVS用户的评论,来进一步说明LVS的性能和可靠性。

"We tried virtually all of the commercial load balancers, LVS beats them all for reliability, cost, manageability, you-name-it"
Jerry Glomph Black, Director, Internet & Technical Operations, Real Networks, Seattle Washington, USA
http://marc.theaimsgroup.com/?1=linux-virtual-server&m=95385809030794&w=2
"I can say without a doubt that lvs toasts F5/BigIP solutions, at least in our real world implementations. I wouldn't trade a good lvs box for a Cisco Local Director either"
Drew Streib, Information Architect, VA Linux Systems, USA
http://marc.theaimsgroup.com/?1=linux-virtual-server&m=95385694529750&w=2

6. LVS项目的开发进展与感触

    LVS项目于1998年5月在网站上发布IPVS第一个版本源程序,一直得到了来自 Internet 的用户和开发者的鼓励和支持。应该说,刚开始发布的程序是非常简单的,由于用户的使用、反馈和期望,让我觉得这项工作的价值,并不断地化时间对该软件添加新功能和完善,其中也得到其他开发者的帮助,所以该软件逐渐发展成为功能较齐全、有用的系统,这远远超出我当初成立项目时的想象。在这里,我要感谢Julian Anastasov提供了很多系统的Bug fixes和改进,Joseph Mack博士编写了LVS HOWTO文档;还感谢一些厂商赞助我开发(如硬件设备等),和赞助我多次出国作相关的技术报告。

    目前,正在进行的 LVS项目开发工作包括:

    扩充IPVS对其他传输协议的支持,如AH(Authentication Header)和ESP(Encapsulating Security Payload )等,这样IPVS调度器将实现IPSec的服务器集群。

    提供一个统一的、功能较完善、更灵活的LVS集群管理软件。

    扩充和改进KTCPVS的调度算法和多种协议的支持,使之功能较完备和系统更稳定。

    在TCP粘合(TCP Splicing)和TCP转移(TCP Handoff)等方面,做一些尝试性工作,进一步改进LVS集群中的应用层调度。

    最后,我谈一下自己多年来做自由软件开发的几点感触。一是通过自由软件方式可以使得软件具有顽强的生命力;我以前也做过几个独立的系统,如在SUN上用Common Lisp开发的知识库系统和基于C++的对象数据库系统,有些地方也是做得非常漂亮的(如元级反射机制和对象的关系处理),但因为种种原因这些软件没有以开放源码方式发布,现在它们在我导师的软件仓库里已无人问津,我也已经忘记里面的实现细节;而LVS项目是我做着玩的,一开始只是个很简单的程序,通过自由软件的发布和开发,它发展成一个有用的、功能较齐全的软件,体现了自由软件的强大生命力。二是通过自由软件的集市开发,可以使得初始的想法不断地深入,可以学到很多东西。三是做自由软件后时间会更有效率,由于用户的反馈和期待,会自觉不断地改进和完善系统,于是没有时间去玩游戏和网上聊天。四是做自由软件会使得你有一点点成就感,每当收到用户的致谢和想到你的软件在实际系统中运行,会有一点满足。所以,行动起来吧,花一些时间做自由软件,你会有意想不到的收获。


[目录]


体系结构

    本文主要介绍了LVS集群的体系结构。先给出LVS集群的通用体系结构,并讨论了其的设计原则和相应的特点;最后将LVS集群应用于建立可伸缩的Web、Media、Cache和Mail等网络服务。

1.引言
    在过去的十几年中,Internet从几个研究机构相连为信息共享的网络发展成为拥有大量应用和服务的全球性网络,它正成为人们生活中不可缺少的一部分。虽然Internet发展速度很快,但建设和维护大型网络服务依然是一项挑战性的任务,因为系统必须是高性能的、高可靠的,尤其当访问负载不断增长时,系统必须能被扩展来满足不断增长的性能需求。由于缺少建立可伸缩网络服务的框架和设计方法,这意味着只有拥有非常出色工程和管理人才的机构才能建立和维护大型的网络服务。

    针对这种情形,本文先给出LVS集群的通用体系结构,并讨论了其的设计原则和相应的特点;最后将LVS集群应用于建立可伸缩的Web、Media、Cache和Mail等网络服务。

2.LVS集群的通用体系结构
    LVS集群采用IP负载均衡技术和基于内容请求分发技术。调度器具有很好的吞吐率,将请求均衡地转移到不同的服务器上执行,且调度器自动屏蔽掉服务器的故障,从而将一组服务器构成一个高性能的、高可用的虚拟服务器。整个服务器集群的结构对客户是透明的,而且无需修改客户端和服务器端的程序。

    为此,在设计时需要考虑系统的透明性、可伸缩性、高可用性和易管理性。一般来说,LVS集群采用三层结构,其体系结构如图1所示,三层主要组成部分为:

    负载调度器(load balancer),它是整个集群对外面的前端机,负责将客户的请求发送到一组服务器上执行,而客户认为服务是来自一个IP地址(我们可称之为虚拟IP地址)上的。
服务器池(server pool),是一组真正执行客户请求的服务器,执行的服务有WEB、MAIL、FTP和DNS等。
    共享存储(shared storage),它为服务器池提供一个共享的存储区,这样很容易使得服务器池拥有相同的内容,提供相同的服务。

    调度器是服务器集群系统的唯一入口点(Single Entry Point),它可以采用IP负载均衡技术、基于内容请求分发技术或者两者相结合。在IP负载均衡技术中,需要服务器池拥有相同的内容提供相同的服务。当客户请求到达时,调度器只根据服务器负载情况和设定的调度算法从服务器池中选出一个服务器,将该请求转发到选出的服务器,并记录这个调度;当这个请求的其他报文到达,也会被转发到前面选出的服务器。在基于内容请求分发技术中,服务器可以提供不同的服务,当客户请求到达时,调度器可根据请求的内容选择服务器执行请求。因为所有的操作都是在Linux操作系统核心空间中将完成的,它的调度开销很小,所以它具有很高的吞吐率。

    服务器池的结点数目是可变的。当整个系统收到的负载超过目前所有结点的处理能力时,可以在服务器池中增加服务器来满足不断增长的请求负载。对大多数网络服务来说,请求间不存在很强的相关性,请求可以在不同的结点上并行执行,所以整个系统的性能基本上可以随着服务器池的结点数目增加而线性增长。

    共享存储通常是数据库、网络文件系统或者分布式文件系统。服务器结点需要动态更新的数据一般存储在数据库系统中,同时数据库会保证并发访问时数据的一致性。静态的数据可以存储在网络文件系统(如NFS/CIFS)中,但网络文件系统的伸缩能力有限,一般来说,NFS/CIFS服务器只能支持3~6个繁忙的服务器结点。对于规模较大的集群系统,可以考虑用分布式文件系统,如AFS[1]、GFS[2.3]、Coda[4]和Intermezzo[5]等。分布式文件系统可为各服务器提供共享的存储区,它们访问分布式文件系统就像访问本地文件系统一样,同时分布式文件系统可提供良好的伸缩性和可用性。此外,当不同服务器上的应用程序同时读写访问分布式文件系统上同一资源时,应用程序的访问冲突需要消解才能使得资源处于一致状态。这需要一个分布式锁管理器(Distributed Lock Manager),它可能是分布式文件系统内部提供的,也可能是外部的。开发者在写应用程序时,可以使用分布式锁管理器来保证应用程序在不同结点上并发访问的一致性。

    负载调度器、服务器池和共享存储系统通过高速网络相连接,如100Mbps交换网络、Myrinet和Gigabit网络等。使用高速的网络,主要为避免当系统规模扩大时互联网络成为整个系统的瓶颈。

    Graphic Monitor是为系统管理员提供整个集群系统的监视器,它可以监视系统的状态。Graphic Monitor是基于浏览器的,所以无论管理员在本地还是异地都可以监测系统的状况。为了安全的原因,浏览器要通过HTTPS(Secure HTTP)协议和身份认证后,才能进行系统监测,并进行系统的配置和管理。

2.1. 为什么使用层次的体系结构

    层次的体系结构可以使得层与层之间相互独立,每一个层次提供不同的功能,在一个层次可以重用不同的已有软件。例如,调度器层提供了负载平衡、可伸缩性和高可用性等,在服务器层可以运行不同的网络服务,如Web、Cache、Mail和Media等,来提供不同的可伸缩网络服务。明确的功能划分和清晰的层次结构使得系统容易建设,以后整个系统容易维护,而且系统的性能容易被扩展。

2.2. 为什么是共享存储

    共享存储如分布式文件系统在这个LVS集群系统是可选项。当网络服务需要有相同的内容,共享存储是很好的选择,否则每台服务器需要将相同的内容复制到本地硬盘上。当系统存储的内容越多,这种无共享结构(Shared-nothing Structure)的代价越大,因为每台服务器需要一样大的存储空间,任何的更新需要涉及到每台服务器,系统的维护代价会非常高。

    共享存储为服务器组提供统一的存储空间,这使得系统的内容维护工作比较轻松,如Webmaster只需要更新共享存储中的页面,对所有的服务器都有效。分布式文件系统提供良好的伸缩性和可用性,当分布式文件系统的存储空间增加时,所有服务器的存储空间也随之增大。对于大多数Internet服务来说,它们都是读密集型(Read-intensive)的应用,分布式文件系统在每台服务器使用本地硬盘作Cache(如2Gbytes的空间),可以使得访问分布式文件系统本地的速度接近于访问本地硬盘。

    此外,存储硬件技术的发展也促使从无共享的集群向共享存储的集群迁移。存储区域网(Storage Area Networks)技术解决了集群的每个结点可以直接连接/共享一个庞大的硬盘阵列,硬件厂商也提供多种硬盘共享技术,如光纤通道(Fiber Channel)、共享SCSI(Shared SCSI)。InfiniBand是一个通用的高性能I/O规范,使得存储区域网中以更低的延时传输I/O消息和集群通讯消息,并且提供很好的伸缩性。InfiniBand得到绝大多数的大厂商的支持,如Compaq、Dell、Hewlett-Packard、IBM、Intel、Microsoft和SUN Microsystems等,它正在成为一个业界的标准。这些技术的发展使得共享存储变得容易,规模生产也会使得成本逐步降低。

2.3. 高可用性

    集群系统的特点是它在软硬件上都有冗余。系统的高可用性可以通过检测节点或服务进程故障和正确地重置系统来实现,使得系统收到的请求能被存活的结点处理。

    通常,我们在调度器上有资源监测进程来时刻监视各个服务器结点的健康状况。当服务器对ICMP ping不可达时或者探测她的网络服务在指定的时间没有响应时,资源监测进程通知操作系统内核将该服务器从调度列表中删除或者失效。这样,新的服务请求就不会被调度到坏的结点。资源监测进程能通过电子邮件或传呼机向管理员报告故障。一旦监测进程到服务器恢复工作,通知调度器将其加入调度列表进行调度。另外,通过系统提供的管理程序,管理员可发命令随时可以将新机器加入服务来提高系统的处理性能,也可以将已有的服务器切出服务,以便对服务器进行系统维护。

    现在前端的调度器有可能成为系统的单一失效点(Single Point of Failure)。一般来说,调度器的可靠性较高,因为调度器上运行的程序较少而且大部分程序早已经遍历过,但我们不能排除硬件老化、网络线路或者人为误操作等主要故障。为了避免调度器失效而导致整个系统不能工作,我们需要设立一个从调度器作为主调度器的备份。两个心跳(Heartbeat)进程[6]分别在主、从调度器上运行,它们通过串口线和UDP等心跳线来相互定时地汇报各自的健康状况。当从调度器不能听得主调度器的心跳时,从调度器通过ARP欺骗(Gratuitous ARP)来接管集群对外的Virtual IP Address,同时接管主调度器的工作来提供负载调度服务。当主调度器恢复时,这里有两种方法,一是主调度器自动变成从调度器,二是从调度器释放Virtual IP Address,主调度器收回Virtual IP Address并提供负载调度服务。这里,多条心跳线可以使得因心跳线故障导致误判(即从调度器认为主调度器已经失效,其实主调度器还在正常工作)的概论降到最低。

    通常,当主调度器失效时,主调度器上所有已建立连接的状态信息将丢失,已有的连接会中断。客户需要向重新连接,从调度器才会将新连接调度到各个服务器上,这对客户会造成一定的不便。为此,IPVS调度器在Linux 内核中实现一种高效状态同步机制,将主调度器的状态信息及时地同步到从调度器。当从调度器接管时,绝大部分已建立的连接会持续下去。

3.可伸缩Web服务

    基于LVS的Web集群的体系结构如图2所示:第一层是负载调度器,一般采用IP负载均衡技术,可以使得整个系统有较高的吞吐率;第二层是Web服务器池,在每个结点上可以分别运行HTTP服务或HTTPS服务、或者两者都运行;第三层是共享存储,它可以是数据库,可以是网络文件系统或分布式文件系统,或者是三者的混合。集群中各结点是通过高速网络相连接的。

    对于动态页面(如PHP、JSP和ASP等),需要访问的动态数据一般存储在数据库服务器中。数据库服务运行在独立的服务器上,为所有Web服务器共享。无论同一Web服务器上多个动态页面访问同一数据,还是不同Web服务器上多个动态页面访问同一数据,数据库服务器有锁机制使得这些访问有序地进行,从而保证数据的一致性。

    对于静态的页面和文件(如HTML文档和图片等),可以存储在网络文件系统或者分布式文件系统中。至于选择哪一种,看系统的规模和需求而定。通过共享的网络文件系统或者分布式文件系统,Webmaster可以看到统一的文档存储空间,维护和更新页面比较方便,对共享存储中页面的修改对所有的服务器都有效。

    在这种结构下,当所有服务器结点超载时,管理员可以很快地加入新的服务器结点来处理请求,而无需将Web文档等复制到结点的本地硬盘上。

    有些Web服务可能用到HTTP Cookie,它是将数据存储在客户的浏览器来追踪和标识客户的机制。使用HTTP Cookie后,来同一客户的不同连接存在相关性,这些连接必须被发送到同一Web服务器。一些Web服务使用安全的HTTPS协议,它是HTTP协议加SSL(Secure Socket Layer)协议。另有些Web服务可能使用安全的HTTPS协议,它是HTTP协议加SSL协议。当客户访问HTTPS服务(HTTPS的缺省端口为443)时,会先建立一个SSL连接,来交换对称公钥加密的证书并协商一个SSL Key,来加密以后的会话。在SSL Key的生命周期内,后续的所有HTTPS连接都使用这个SSL Key,所以同一客户的不同HTTPS连接也存在相关性。针对这些需要,IPVS调度器提供了持久服务的功能,它可以使得在设定的时间内,来自同一IP地址的不同连接会被发送到集群中同一个服务器结点,可以很好地解决客户连接的相关性问题。

4.可伸缩媒体服务

    基于LVS的媒体集群的体系结构如图3所示:第一层是负载调度器,一般采用IP负载均衡技术,可以使得整个系统有较高的吞吐率;第二层是Web服务器池,在每个结点上可以运行相应的媒体服务;第三层是共享存储,通过网络文件系统/分布式文件系统存储媒体节目。集群中各结点是通过高速网络相连接。

    IPVS负载调度器一般使用直接路由方法(即VS/DR方法,将在以后文章中详细叙述),来架构媒体集群系统。调度器将媒体服务请求较均衡地分发到各个服务器上,而媒体服务器将响应数据直接返回给客户,这样可以使得整个媒体集群系统具有很好的伸缩性。

    媒体服务器可以运行各种媒体服务软件。目前,LVS集群对于Real Media、Windows Media和Apple Quicktime媒体服务都有很好的支持,都有真实的系统在运行。一般来说,流媒体服务都会使用一个TCP连接(如RTSP协议:Real-Time Streaming Protocol)进行带宽的协商和流速的控制,通过UDP将流数据返回客户。这里,IPVS调度器提供功能将TCP和UDP集中考虑,保证来自同一客户的媒体TCP和UDP连接会被转发到集群中同一台媒体服务器,使得媒体服务准确无误地进行。

    共享存储是媒体集群系统中最关键的问题,因为媒体文件往往非常大(一部片子需要几百兆到几千兆的存储空间),这对存储的容量和读的速度有较高的要求。对于规模较小的媒体集群系统,例如有3至6个媒体服务器结点,存储系统可以考虑用带千兆网卡的Linux服务器,使用软件RAID和日志型文件系统,再运行内核的NFS服务,会有不错的效果。对于规模较大的媒体集群系统,最好选择对文件分段(File Stripping)存储和文件缓存有较好支持的分布式文件系统;媒体文件分段存储在分布式文件系统的多个存储结点上,可以提高文件系统的性能和存储结点间的负载均衡;媒体文件在媒体服务器上自动地被缓存,可提高文件的访问速度。否则,可以考虑自己在媒体服务器上开发相应的工具,如缓存工具能定时地统计出最近的热点媒体文件,将热点文件复制到本地硬盘上,并替换缓存中的非热点文件,最后通知其他媒体服务器结点它所缓存的媒体文件以及负载情况;在媒体服务器上有应用层调度工具,它收到客户的媒体服务请求,若所请求的媒体文件缓存在本地硬盘上,则直接转给本地媒体服务进程服务,否则先考虑该文件是否被其他媒体服务器缓存;如该文件被其他服务器缓存并且该服务器不忙,则将请求转给该服务器上的媒体服务进程处理,否则直接转给本地媒体服务进程,从后端的共享存储中读出媒体文件。

    共享存储的好处是媒体文件的管理人员看到统一的存储空间,使得媒体文件维护工作比较方便。当客户访问不断增加使得整个系统超载时,管理员可以很快地加入新的媒体服务器结点来处理请求。

    Real公司以其高压缩比的音频视频格式、Real媒体服务器和媒体播放器RealPlayer而闻名。Real公司正在使用以上结构将由20多台服务器组成的LVS可伸缩Web和媒体集群,为其全球用户提供Web和音频视频服务。Real公司的高级技术主管声称LVS击败所有他们尝试过的商品化负载均衡产品[7]。

5.可伸缩Cache服务

    有效的网络Cache系统可以大大地减少网络流量、降低响应延时以及服务器的负载。但是,若Cache服务器超载而不能及时地处理请求,反而会增加响应延时。所以,Cache服务的可伸缩性很重要,当系统负载不断增长时,整个系统能被扩展来提高Cache服务的处理能力。尤其,在主干网上的Cache服务可能需要几个Gbps的吞吐率,单台服务器(例如SUN目前最高端的Enterprise 10000服务器)远不能达到这个吞吐率。可见,通过PC服务器集群实现可伸缩Cache服务是很有效的方法,也是性能价格比最高的方法。

    基于LVS的Cache集群的体系结构如图4所示:第一层是负载调度器,一般采用IP负载均衡技术,可以使得整个系统有较高的吞吐率;第二层是Cache服务器池,一般Cache服务器放置在接近主干Internet连接处,它们可以分布在不同的网络中。调度器可以有多个,放在离客户接近的地方。

    IPVS负载调度器一般使用IP隧道方法(即VS/TUN方法,将在以后文章中详细叙述),来架构Cache集群系统,因为Cache服务器可能被放置不同的地方(例如在接近主干Internet连接处),而调度器与Cache服务器池可能不在同一个物理网络中。采用VS/TUN方法,调度器只调度Web Cache请求,而Cache服务器将响应数据直接返回给客户。在请求对象不能在本地命中的情况下,Cache服务器要向源服务器发请求,将结果取回,最后将结果返回给客户;若采用NAT技术的商品化调度器,需要四次进出调度器,完成这个请求。而用VS/TUN方法(或者VS/DR方法),调度器只调度一次请求,其他三次都由Cache服务器直接访问Internet完成。所以,这种方法对Cache集群系统特别有效。

    Cache服务器采用本地硬盘来存储可缓存的对象,因为存储可缓存的对象是写操作,且占有一定的比例,通过本地硬盘可以提高I/O的访问速度。Cache服务器间有专用的多播通道(Multicast Channel),通过ICP协议(Internet Cache Protocol)来交互信息。当一台Cache服务器在本地硬盘中未命中当前请求时,它可以通过ICP查询其他Cache服务器是否有请求对象的副本,若存在,则从邻近的Cache服务器取该对象的副本,这样可以进一步提高Cache服务的命中率。

    为150多所大学和地区服务的英国国家JANET Web Cache网在1999年11月用以上LVS结构实现可伸缩的Cache集群[8],只用了原有50多台相互独立Cache服务器的一半,用户反映网络速度跟夏天一样快(学生放暑假)。可见,通过负载调度可以摸平单台服务器访问的毛刺(Burst),提高整个系统的资源利用率。

6.可伸缩邮件服务

    随着Internet用户不断增长,很多ISP面临他们邮件服务器超载的问题。当邮件服务器不能容纳更多的用户帐号时,有些ISP买更高档的服务器来代替原有的,将原有服务器的信息(如用户邮件)迁移到新服务器是很繁琐的工作,会造成服务的中断;有些ISP设置新的服务器和新的邮件域名,新的邮件用户放置在新的服务器上,如上海电信现在用不同的邮件服务器public1.sta.net.cn、public2.sta.net.cn到public9.sta.net.cn放置用户的邮件帐号,这样静态地将用户分割到不同的服务器上,会造成邮件服务器负载不平衡,系统的资源利用率低,对用户来说邮件的地址比较难记。

    可以利用LVS框架实现高可伸缩、高可用的邮件服务系统。它的体系结构如图5所示:在前端是一个采用IP负载均衡技术的负载调度器;第二层是服务器池,有LDAP(Light-weight Directory Access Protocol)服务器和一组邮件服务器。第三层是数据存储,通过分布式文件系统来存储用户的邮件。集群中各结点是通过高速网络相连接。

    用户的信息如用户名、口令、主目录和邮件容量限额等存储在LDAP服务器中,可以通过HTTPS让管理员进行用户管理。在各个邮件服务器上运行SMTP(Simple Mail Transfer Protocol)、POP3(Post Office Protocol version 3)、IMAP4(Internet Message Access Protocol version 4)和HTTP/HTTPS服务。SMTP接受和转发用户的邮件,SMTP服务进程查询LDAP服务器获得用户信息,再存储邮件。POP3和IMAP4通过LDAP服务器获得用户信息,口令验证后,处理用户的邮件访问请求。这里,需要有机制避免不同服务器上的SMTP、POP3和IMAP4服务进程对用户邮件的读写冲突。HTTP/HTTPS服务是让用户通过浏览器可以访问邮件。

    IPVS调度器将SMTP、POP3、IMAP4和HTTP/HTTPS请求流负载较均衡地分发到各邮件服务器上,从上面各服务的处理流程来看,不管请求被发送到哪一台邮件服务器处理,其结果是一样的。这里,将SMTP、POP3、IMAP4和HTTP/HTTPS运行在各个邮件服务器上进行集中调度,有利于提高整个系统的资源利用率。

    系统中可能的瓶颈是LDAP服务器,对LDAP服务中B+树的参数进行优化,再结合高端的服务器,可以获得较高的性能。若分布式文件系统没有多个存储结点间的负载均衡机制,则需要相应的邮件迁移机制来避免邮件访问的倾斜。

    这样,这个集群系统对用户来说就像一个高性能、高可靠的邮件服务器(例如上海电信只要用一个邮件域名public.sta.net.cn就可以)。当邮件用户不断增长时,只要在集群中增加服务器结点和存储结点。用户信息的集中存储使得用户管理变得容易,且集群系统有利于提高资源利用率。

7.小结

    本文给出LVS集群的通用体系结构,并讨论了它的设计原则和相应的特点;最后将LVS集群应用于建立可伸缩的Web、Media、Cache和Mail网络服务,并指出了系统架设时应注意的要点。我们将在后续的文章中详细解释LVS集群的技术、实现和应用。


[目录]


IP负载均衡

本文在分析服务器集群实现虚拟网络服务的相关技术上,详细描述了LVS集群中实现的三种IP负载均衡技术(VS/NAT、VS/TUN和VS/DR)的工作原理,以及它们的优缺点。

1.前言
    在前面文章中,讲述了可伸缩网络服务的几种结构,它们都需要一个前端的负载调度器(或者多个进行主从备份)。我们先分析实现虚拟网络服务的主要技术,指出IP负载均衡技术是在负载调度器的实现技术中效率最高的。在已有的IP负载均衡技术中,主要有通过网络地址转换(Network Address Translation)将一组服务器构成一个高性能的、高可用的虚拟服务器,我们称之为VS/NAT技术(Virtual Server via Network Address Translation)。在分析VS/NAT的缺点和网络服务的非对称性的基础上,我们提出了通过IP隧道实现虚拟服务器的方法VS/TUN(Virtual Server via IP Tunneling),和通过直接路由实现虚拟服务器的方法VS/DR(Virtual Server via Direct Routing),它们可以极大地提高系统的伸缩性。VS/NAT、VS/TUN和VS/DR技术是LVS集群中实现的三种IP负载均衡技术,我们将在文章中详细描述它们的工作原理和各自的优缺点。

    在以下描述中,我们称客户的socket和服务器的socket之间的数据通讯为连接,无论它们是使用TCP还是UDP协议。下面简述当前用服务器集群实现高可伸缩、高可用网络服务的几种负载调度方法,并列举几个在这方面有代表性的研究项目。

2.实现虚拟服务的相关方法
    在网络服务中,一端是客户程序,另一端是服务程序,在中间可能有代理程序。由此看来,可以在不同的层次上实现多台服务器的负载均衡。用集群解决网络服务性能问题的现有方法主要分为以下四类。
2.1. 基于RR-DNS的解决方法

    NCSA的可伸缩的WEB服务器系统就是最早基于RR-DNS(Round-Robin Domain Name System)的原型系统[1,2]。它的结构和工作流程如下图所示:

    有一组WEB服务器,他们通过分布式文件系统AFS(Andrew File System)来共享所有的HTML文档。这组服务器拥有相同的域名(如www.ncsa.uiuc.edu),当用户按照这个域名访问时, RR-DNS服务器会把域名轮流解析到这组服务器的不同IP地址,从而将访问负载分到各台服务器上。

    这种方法带来几个问题。第一,域名服务器是一个分布式系统,是按照一定的层次结构组织的。当用户就域名解析请求提交给本地的域名服务器,它会因不能直接解析而向上一级域名服务器提交,上一级域名服务器再依次向上提交,直到RR-DNS域名服器把这个域名解析到其中一台服务器的IP地址。可见,从用户到RR-DNS间存在多台域名服器,而它们都会缓冲已解析的名字到IP地址的映射,这会导致该域名服器组下所有用户都会访问同一WEB服务器,出现不同WEB服务器间严重的负载不平衡。为了保证在域名服务器中域名到IP地址的映射不被长久缓冲,RR-DNS在域名到IP地址的映射上设置一个TTL(Time To Live)值,过了这一段时间,域名服务器将这个映射从缓冲中淘汰。当用户请求,它会再向上一级域名服器提交请求并进行重新影射。这就涉及到如何设置这个TTL值,若这个值太大,在这个TTL期间,很多请求会被映射到同一台WEB服务器上,同样会导致严重的负载不平衡。若这个值太小,例如是0,会导致本地域名服务器频繁地向RR-DNS提交请求,增加了域名解析的网络流量,同样会使RR-DNS服务器成为系统中一个新的瓶颈。

    第二,用户机器会缓冲从名字到IP地址的映射,而不受TTL值的影响,用户的访问请求会被送到同一台WEB服务器上。由于用户访问请求的突发性和访问方式不同,例如有的人访问一下就离开了,而有的人访问可长达几个小时,所以各台服务器间的负载仍存在倾斜(Skew)而不能控制。假设用户在每个会话中平均请求数为20,负载最大的服务器获得的请求数额高于各服务器平均请求数的平均比率超过百分之三十。也就是说,当TTL值为0时,因为用户访问的突发性也会存在着较严重的负载不平衡。

    第三,系统的可靠性和可维护性差。若一台服务器失效,会导致将域名解析到该服务器的用户看到服务中断,即使用户按“Reload”按钮,也无济于事。系统管理员也不能随时地将一台服务器切出服务进行系统维护,如进行操作系统和应用软件升级,这需要修改RR-DNS服务器中的IP地址列表,把该服务器的IP地址从中划掉,然后等上几天或者更长的时间,等所有域名服器将该域名到这台服务器的映射淘汰,和所有映射到这台服务器的客户机不再使用该站点为止。

2.2. 基于客户端的解决方法

    基于客户端的解决方法需要每个客户程序都有一定的服务器集群的知识,进而把以负载均衡的方式将请求发到不同的服务器。例如,Netscape Navigator浏览器访问Netscape的主页时,它会随机地从一百多台服务器中挑选第N台,最后将请求送往wwwN.netscape.com。然而,这不是很好的解决方法,Netscape只是利用它的Navigator避免了RR-DNS解析的麻烦,当使用IE等其他浏览器不可避免的要进行RR-DNS解析。

    Smart Client[3]是Berkeley做的另一种基于客户端的解决方法。服务提供一个Java Applet在客户方浏览器中运行,Applet向各个服务器发请求来收集服务器的负载等信息,再根据这些信息将客户的请求发到相应的服务器。高可用性也在Applet中实现,当服务器没有响应时,Applet向另一个服务器转发请求。这种方法的透明性不好,Applet向各服务器查询来收集信息会增加额外的网络流量,不具有普遍的适用性。

2.3. 基于应用层负载均衡调度的解决方法

    多台服务器通过高速的互联网络连接成一个集群系统,在前端有一个基于应用层的负载调度器。当用户访问请求到达调度器时,请求会提交给作负载均衡调度的应用程序,分析请求,根据各个服务器的负载情况,选出一台服务器,重写请求并向选出的服务器访问,取得结果后,再返回给用户。

    应用层负载均衡调度的典型代表有Zeus负载调度器[4]、pWeb[5]、Reverse-Proxy[6]和SWEB[7]等。Zeus负载调度器是Zeus公司的商业产品,它是在Zeus Web服务器程序改写而成的,采用单进程事件驱动的服务器结构。pWeb就是一个基于Apache 1.1服务器程序改写而成的并行WEB调度程序,当一个HTTP请求到达时,pWeb会选出一个服务器,重写请求并向这个服务器发出改写后的请求,等结果返回后,再将结果转发给客户。Reverse-Proxy利用Apache 1.3.1中的Proxy模块和Rewrite模块实现一个可伸缩WEB服务器,它与pWeb的不同之处在于它要先从Proxy的cache中查找后,若没有这个副本,再选一台服务器,向服务器发送请求,再将服务器返回的结果转发给客户。SWEB是利用HTTP中的redirect错误代码,将客户请求到达一台WEB服务器后,这个WEB服务器根据自己的负载情况,自己处理请求,或者通过redirect错误代码将客户引到另一台WEB服务器,以实现一个可伸缩的WEB服务器。

    基于应用层负载均衡调度的多服务器解决方法也存在一些问题。第一,系统处理开销特别大,致使系统的伸缩性有限。当请求到达负载均衡调度器至处理结束时,调度器需要进行四次从核心到用户空间或从用户空间到核心空间的上下文切换和内存复制;需要进行二次TCP连接,一次是从用户到调度器,另一次是从调度器到真实服务器;需要对请求进行分析和重写。这些处理都需要不小的CPU、内存和网络等资源开销,且处理时间长。所构成系统的性能不能接近线性增加的,一般服务器组增至3或4台时,调度器本身可能会成为新的瓶颈。所以,这种基于应用层负载均衡调度的方法的伸缩性极其有限。第二,基于应用层的负载均衡调度器对于不同的应用,需要写不同的调度器。以上几个系统都是基于HTTP协议,若对于FTP、Mail、POP3等应用,都需要重写调度器。

2.4. 基于IP层负载均衡调度的解决方法

    用户通过虚拟IP地址(Virtual IP Address)访问服务时,访问请求的报文会到达负载调度器,由它进行负载均衡调度,从一组真实服务器选出一个,将报文的目标地址Virtual IP Address改写成选定服务器的地址,报文的目标端口改写成选定服务器的相应端口,最后将报文发送给选定的服务器。真实服务器的回应报文经过负载调度器时,将报文的源地址和源端口改为Virtual IP Address和相应的端口,再把报文发给用户。Berkeley的MagicRouter[8]、Cisco的LocalDirector、Alteon的ACEDirector和F5的Big/IP等都是使用网络地址转换方法。MagicRouter是在Linux 1.3版本上应用快速报文插入技术,使得进行负载均衡调度的用户进程访问网络设备接近核心空间的速度,降低了上下文切换的处理开销,但并不彻底,它只是研究的原型系统,没有成为有用的系统存活下来。Cisco的LocalDirector、Alteon的ACEDirector和F5的Big/IP是非常昂贵的商品化系统,它们支持部分TCP/UDP协议,有些在ICMP处理上存在问题。

    IBM的TCP Router[9]使用修改过的网络地址转换方法在SP/2系统实现可伸缩的WEB服务器。TCP Router修改请求报文的目标地址并把它转发给选出的服务器,服务器能把响应报文的源地址置为TCP Router地址而非自己的地址。这种方法的好处是响应报文可以直接返回给客户,坏处是每台服务器的操作系统内核都需要修改。IBM的NetDispatcher[10]是TCP Router的后继者,它将报文转发给服务器,而服务器在non-ARP的设备配置路由器的地址。这种方法与LVS集群中的VS/DR类似,它具有很高的可伸缩性,但一套在IBM SP/2和NetDispatcher需要上百万美金。总的来说,IBM的技术还挺不错的。

    在贝尔实验室的ONE-IP[11]中,每台服务器都独立的IP地址,但都用IP Alias配置上同一VIP地址,采用路由和广播两种方法分发请求,服务器收到请求后按VIP地址处理请求,并以VIP为源地址返回结果。这种方法也是为了避免回应报文的重写,但是每台服务器用IP Alias配置上同一VIP地址,会导致地址冲突,有些操作系统会出现网络失效。通过广播分发请求,同样需要修改服务器操作系统的源码来过滤报文,使得只有一台服务器处理广播来的请求。

    微软的Windows NT负载均衡服务(Windows NT Load Balancing Service,WLBS)[12]是1998年底收购Valence Research公司获得的,它与ONE-IP中的基于本地过滤方法一样。WLBS作为过滤器运行在网卡驱动程序和TCP/IP协议栈之间,获得目标地址为VIP的报文,它的过滤算法检查报文的源IP地址和端口号,保证只有一台服务器将报文交给上一层处理。但是,当有新结点加入和有结点失效时,所有服务器需要协商一个新的过滤算法,这会导致所有有Session的连接中断。同时,WLBS需要所有的服务器有相同的配置,如网卡速度和处理能力。

3. 通过NAT实现虚拟服务器(VS/NAT)

    由于IPv4中IP地址空间的日益紧张和安全方面的原因,很多网络使用保留IP地址(10.0.0.0/255.0.0.0、172.16.0.0/255.128.0.0和192.168.0.0/255.255.0.0)[64, 65, 66]。这些地址不在Internet上使用,而是专门为内部网络预留的。当内部网络中的主机要访问Internet或被Internet访问时,就需要采用网络地址转换(Network Address Translation, 以下简称NAT),将内部地址转化为Internets上可用的外部地址。NAT的工作原理是报文头(目标地址、源地址和端口等)被正确改写后,客户相信它们连接一个IP地址,而不同IP地址的服务器组也认为它们是与客户直接相连的。由此,可以用NAT方法将不同IP地址的并行网络服务变成在一个IP地址上的一个虚拟服务。

    VS/NAT的体系结构如图2所示。在一组服务器前有一个调度器,它们是通过Switch/HUB相连接的。这些服务器提供相同的网络服务、相同的内容,即不管请求被发送到哪一台服务器,执行结果是一样的。服务的内容可以复制到每台服务器的本地硬盘上,可以通过网络文件系统(如NFS)共享,也可以通过一个分布式文件系统来提供。

    客户通过Virtual IP Address(虚拟服务的IP地址)访问网络服务时,请求报文到达调度器,调度器根据连接调度算法从一组真实服务器中选出一台服务器,将报文的目标地址Virtual IP Address改写成选定服务器的地址,报文的目标端口改写成选定服务器的相应端口,最后将修改后的报文发送给选出的服务器。同时,调度器在连接Hash表中记录这个连接,当这个连接的下一个报文到达时,从连接Hash表中可以得到原选定服务器的地址和端口,进行同样的改写操作,并将报文传给原选定的服务器。当来自真实服务器的响应报文经过调度器时,调度器将报文的源地址和源端口改为Virtual IP Address和相应的端口,再把报文发给用户。我们在连接上引入一个状态机,不同的报文会使得连接处于不同的状态,不同的状态有不同的超时值。在TCP连接中,根据标准的TCP有限状态机进行状态迁移,这里我们不一一叙述,请参见W. Richard Stevens的《TCP/IP Illustrated Volume I》;在UDP中,我们只设置一个UDP状态。不同状态的超时值是可以设置的,在缺省情况下,SYN状态的超时为1分钟,ESTABLISHED状态的超时为15分钟,FIN状态的超时为1分钟;UDP状态的超时为5分钟。当连接终止或超时,调度器将这个连接从连接Hash表中删除。

    这样,客户所看到的只是在Virtual IP Address上提供的服务,而服务器集群的结构对用户是透明的。对改写后的报文,应用增量调整Checksum的算法调整TCP Checksum的值,避免了扫描整个报文来计算Checksum的开销。

    在一些网络服务中,它们将IP地址或者端口号在报文的数据中传送,若我们只对报文头的IP地址和端口号作转换,这样就会出现不一致性,服务会中断。所以,针对这些服务,需要编写相应的应用模块来转换报文数据中的IP地址或者端口号。我们所知道有这个问题的网络服务有FTP、IRC、H.323、CUSeeMe、Real Audio、Real Video、Vxtreme / Vosiac、VDOLive、VIVOActive、True Speech、RSTP、PPTP、StreamWorks、NTT AudioLink、NTT SoftwareVision、Yamaha MIDPlug、iChat Pager、Quake和Diablo。

    VS/NAT的配置如下表所示,所有到IP地址为202.103.106.5和端口为80的流量都被负载均衡地调度的真实服务器172.16.0.2:80和172.16.0.3:8000上。目标地址为202.103.106.5:21的报文被转移到172.16.0.3:21上。而到其他端口的报文将被拒绝。

Protocol  Virtual IP Address  Port  Real IP Address  Port  Weight
TCP  202.103.106.5  80  172.16.0.2  80  1
172.16.0.3  8000  2
TCP  202.103.106.5  21  172.16.0.3  21  1

从以下的例子中,我们可以更详细地了解报文改写的流程。

访问Web服务的报文可能有以下的源地址和目标地址:

SOURCE  202.100.1.2:3456  DEST  202.103.106.5:80

调度器从调度列表中选出一台服务器,例如是172.16.0.3:8000。该报文会被改写为如下地址,并将它发送给选出的服务器。

SOURCE  202.100.1.2:3456  DEST  172.16.0.3:8000

从服务器返回到调度器的响应报文如下:

SOURCE  172.16.0.3:8000  DEST  202.100.1.2:3456

响应报文的源地址会被改写为虚拟服务的地址,再将报文发送给客户:

SOURCE  202.103.106.5:80  DEST  202.100.1.2:3456

这样,客户认为是从202.103.106.5:80服务得到正确的响应,而不会知道该请求是服务器172.16.0.2还是服务器172.16.0.3处理的。

4. 通过IP隧道实现虚拟服务器(VS/TUN)

    在VS/NAT的集群系统中,请求和响应的数据报文都需要通过负载调度器,当真实服务器的数目在10台和20台之间时,负载调度器将成为整个集群系统的新瓶颈。大多数Internet服务都有这样的特点:请求报文较短而响应报文往往包含大量的数据。如果能将请求和响应分开处理,即在负载调度器中只负责调度请求而响应直接返回给客户,将极大地提高整个集群系统的吞吐量。

    IP隧道(IP tunneling)是将一个IP报文封装在另一个IP报文的技术,这可以使得目标为一个IP地址的数据报文能被封装和转发到另一个IP地址。IP隧道技术亦称为IP封装技术(IP encapsulation)。IP隧道主要用于移动主机和虚拟私有网络(Virtual Private Network),在其中隧道都是静态建立的,隧道一端有一个IP地址,另一端也有唯一的IP地址。

    我们利用IP隧道技术将请求报文封装转发给后端服务器,响应报文能从后端服务器直接返回给客户。但在这里,后端服务器有一组而非一个,所以我们不可能静态地建立一一对应的隧道,而是动态地选择一台服务器,将请求报文封装和转发给选出的服务器。这样,我们可以利用IP隧道的原理将一组服务器上的网络服务组成在一个IP地址上的虚拟网络服务。VS/TUN的体系结构如图4所示,各个服务器将VIP地址配置在自己的IP隧道设备上。

    VS/TUN的工作流程如图5所示:它的连接调度和管理与VS/NAT中的一样,只是它的报文转发方法不同。调度器根据各个服务器的负载情况,动态地选择一台服务器,将请求报文封装在另一个IP报文中,再将封装后的IP报文转发给选出的服务器;服务器收到报文后,先将报文解封获得原来目标地址为VIP的报文,服务器发现VIP地址被配置在本地的IP隧道设备上,所以就处理这个请求,然后根据路由表将响应报文直接返回给客户。

    在这里需要指出,根据缺省的TCP/IP协议栈处理,请求报文的目标地址为VIP,响应报文的源地址肯定也为VIP,所以响应报文不需要作任何修改,可以直接返回给客户,客户认为得到正常的服务,而不会知道究竟是哪一台服务器处理的。

5. 通过直接路由实现虚拟服务器(VS/DR)

    跟VS/TUN方法相同,VS/DR利用大多数Internet服务的非对称特点,负载调度器中只负责调度请求,而服务器直接将响应返回给客户,可以极大地提高整个集群系统的吞吐量。该方法与IBM的NetDispatcher产品中使用的方法类似(其中服务器上的IP地址配置方法是相似的),但IBM的NetDispatcher是非常昂贵的商品化产品,我们也不知道它内部所使用的机制,其中有些是IBM的专利。

    VS/DR的体系结构如图7所示:调度器和服务器组都必须在物理上有一个网卡通过不分断的局域网相连,如通过高速的交换机或者HUB相连。VIP地址为调度器和服务器组共享,调度器配置的VIP地址是对外可见的,用于接收虚拟服务的请求报文;所有的服务器把VIP地址配置在各自的Non-ARP网络设备上,它对外面是不可见的,只是用于处理目标地址为VIP的网络请求。

    VS/DR的工作流程:它的连接调度和管理与VS/NAT和VS/TUN中的一样,它的报文转发方法又有不同,将报文直接路由给目标服务器。在VS/DR中,调度器根据各个服务器的负载情况,动态地选择一台服务器,不修改也不封装IP报文,而是将数据帧的MAC地址改为选出服务器的MAC地址,再将修改后的数据帧在与服务器组的局域网上发送。因为数据帧的MAC地址是选出的服务器,所以服务器肯定可以收到这个数据帧,从中可以获得该IP报文。当服务器发现报文的目标地址VIP是在本地的网络设备上,服务器处理这个报文,然后根据路由表将响应报文直接返回给客户。

    在VS/DR中,根据缺省的TCP/IP协议栈处理,请求报文的目标地址为VIP,响应报文的源地址肯定也为VIP,所以响应报文不需要作任何修改,可以直接返回给客户,客户认为得到正常的服务,而不会知道是哪一台服务器处理的。

    VS/DR负载调度器跟VS/TUN一样只处于从客户到服务器的半连接中,按照半连接的TCP有限状态机进行状态迁移。

6.三种方法的优缺点比较

    三种IP负载均衡技术的优缺点归纳在下表中:

_ VS/NAT  VS/TUN  VS/DR
Server  any  Tunneling  Non-arp device
server network  private  LAN/WAN  LAN
server number  low (10~20)  High (100)  High (100)
server gateway  load balancer  own router  Own router

    注:以上三种方法所能支持最大服务器数目的估计是假设调度器使用100M网卡,调度器的硬件配置与后端服务器的硬件配置相同,而且是对一般Web服务。使用更高的硬件配置(如千兆网卡和更快的处理器)作为调度器,调度器所能调度的服务器数量会相应增加。当应用不同时,服务器的数目也会相应地改变。所以,以上数据估计主要是为三种方法的伸缩性进行量化比较。

6.1. Virtual Server via NAT

    VS/NAT的优点是服务器可以运行任何支持TCP/IP的操作系统,它只需要一个IP地址配置在调度器上,服务器组可以用私有的IP地址。缺点是它的伸缩能力有限,当服务器结点数目升到20时,调度器本身有可能成为系统的新瓶颈,因为在VS/NAT中请求和响应报文都需要通过负载调度器。 我们在Pentium 166 处理器的主机上测得重写报文的平均延时为60us,性能更高的处理器上延时会短一些。假设TCP报文的平均长度为536 Bytes,则调度器的最大吞吐量为8.93 MBytes/s. 我们再假设每台服务器的吞吐量为800KBytes/s,这样一个调度器可以带动10台服务器。(注:这是很早以前测得的数据)

    基于VS/NAT的的集群系统可以适合许多服务器的性能要求。如果负载调度器成为系统新的瓶颈,可以有三种方法解决这个问题:混合方法、VS/TUN和VS/DR。在DNS混合集群系统中,有若干个VS/NAT负载调度器,每个负载调度器带自己的服务器集群,同时这些负载调度器又通过RR-DNS组成简单的域名。但VS/TUN和VS/DR是提高系统吞吐量的更好方法。

对于那些将IP地址或者端口号在报文数据中传送的网络服务,需要编写相应的应用模块来转换报文数据中的IP地址或者端口号。这会带来实现的工作量,同时应用模块检查报文的开销会降低系统的吞吐率。

6.2. Virtual Server via IP Tunneling

    在VS/TUN的集群系统中,负载调度器只将请求调度到不同的后端服务器,后端服务器将应答的数据直接返回给用户。这样,负载调度器就可以处理大量的请求,它甚至可以调度百台以上的服务器(同等规模的服务器),而它不会成为系统的瓶颈。即使负载调度器只有100Mbps的全双工网卡,整个系统的最大吞吐量可超过1Gbps。所以,VS/TUN可以极大地增加负载调度器调度的服务器数量。VS/TUN调度器可以调度上百台服务器,而它本身不会成为系统的瓶颈,可以用来构建高性能的超级服务器。

VS/TUN技术对服务器有要求,即所有的服务器必须支持“IP Tunneling”或者“IP Encapsulation”协议。目前,VS/TUN的后端服务器主要运行Linux操作系统,我们没对其他操作系统进行测试。因为“IP Tunneling”正成为各个操作系统的标准协议,所以VS/TUN应该会适用运行其他操作系统的后端服务器。

6.3. Virtual Server via Direct Routing

    跟VS/TUN方法一样,VS/DR调度器只处理客户到服务器端的连接,响应数据可以直接从独立的网络路由返回给客户。这可以极大地提高LVS集群系统的伸缩性。

跟VS/TUN相比,这种方法没有IP隧道的开销,但是要求负载调度器与实际服务器都有一块网卡连在同一物理网段上,服务器网络设备(或者设备别名)不作ARP响应,或者能将报文重定向(Redirect)到本地的Socket端口上。

7.小结

    本文主要讲述了LVS集群中的三种IP负载均衡技术。在分析网络地址转换方法(VS/NAT)的缺点和网络服务的非对称性的基础上,我们给出了通过IP隧道实现虚拟服务器的方法VS/TUN,和通过直接路由实现虚拟服务器的方法VS/DR,极大地提高了系统的伸缩性。

[目录]


负载调度

    本文主要讲述了LVS集群的IP负载均衡软件IPVS在内核中实现的各种连接调度算法。针对请求的服务时间变化很大,给出一个动态反馈负载均衡算法,它结合内核中的加权连接调度算法,根据动态反馈回来的负载信息来调整服务器的权值,来进一步避免服务器间的负载不平衡。

1. 前言
    在上一篇文章中,我们主要讲述了LVS集群中实现的三种IP负载均衡技术,它们主要解决系统的可伸缩性和透明性问题,如何通过负载调度器将请求高效地分发到不同的服务器执行,使得由多台独立计算机组成的集群系统成为一台虚拟服务器;客户端应用程序与集群系统交互时,就像与一台高性能的服务器交互一样。

    本文将主要讲述在负载调度器上的负载调度策略和算法,如何将请求流调度到各台服务器,使得各台服务器尽可能地保持负载均衡。文章主要由两个部分组成。第一部分描述IP负载均衡软件IPVS在内核中所实现的各种连接调度算法;第二部分给出一个动态反馈负载均衡算法(Dynamic-feedback load balancing),它结合内核中的加权连接调度算法,根据动态反馈回来的负载信息来调整服务器的权值,来进一步避免服务器间的负载不平衡。

    在下面描述中,我们称客户的socket和服务器的socket之间的数据通讯为连接,无论它们是使用TCP还是UDP协议。对于UDP数据报文的调度,IPVS调度器也会为之建立调度记录并设置超时值(如5分钟);在设定的时间内,来自同一地址(IP地址和端口)的UDP数据包会被调度到同一台服务器。

2. 内核中的连接调度算法
    IPVS在内核中的负载均衡调度是以连接为粒度的。在HTTP协议(非持久)中,每个对象从WEB服务器上获取都需要建立一个TCP连接,同一用户的不同请求会被调度到不同的服务器上,所以这种细粒度的调度在一定程度上可以避免单个用户访问的突发性引起服务器间的负载不平衡。

    在内核中的连接调度算法上,IPVS已实现了以下八种调度算法:

轮叫调度(Round-Robin Scheduling)
加权轮叫调度(Weighted Round-Robin Scheduling)
最小连接调度(Least-Connection Scheduling)
加权最小连接调度(Weighted Least-Connection Scheduling)
基于局部性的最少链接(Locality-Based Least Connections Scheduling)
带复制的基于局部性最少链接(Locality-Based Least Connections with Replication Scheduling)
目标地址散列调度(Destination Hashing Scheduling)
源地址散列调度(Source Hashing Scheduling)

    下面,我们先介绍这八种连接调度算法的工作原理和算法流程,会在以后的文章中描述怎么用它们。

2.1. 轮叫调度

    轮叫调度(Round Robin Scheduling)算法就是以轮叫的方式依次将请求调度不同的服务器,即每次调度执行i = (i + 1) mod n,并选出第i台服务器。算法的优点是其简洁性,它无需记录当前所有连接的状态,所以它是一种无状态调度。

    在系统实现时,我们引入了一个额外条件,当服务器的权值为零时,表示该服务器不可用而不被调度。这样做的目的是将服务器切出服务(如屏蔽服务器故障和系统维护),同时与其他加权算法保持一致。所以,算法要作相应的改动,它的算法流程如下:

轮叫调度算法流程
假设有一组服务器S = {S0, S1, …, Sn-1},一个指示变量i表示上一次选择的
服务器,W(Si)表示服务器Si的权值。变量i被初始化为n-1,其中n > 0。

j = i;
do {
        j = (j + 1) mod n;
        if (W(Sj) > 0) {
                i = j;
                return Si;
        }
} while (j != i);
return NULL;

    轮叫调度算法假设所有服务器处理性能均相同,不管服务器的当前连接数和响应速度。该算法相对简单,不适用于服务器组中处理性能不一的情况,而且当请求服务时间变化比较大时,轮叫调度算法容易导致服务器间的负载不平衡。

    虽然Round-Robin DNS方法也是以轮叫调度的方式将一个域名解析到多个IP地址,但轮叫DNS方法的调度粒度是基于每个域名服务器的,域名服务器对域名解析的缓存会妨碍轮叫解析域名生效,这会导致服务器间负载的严重不平衡。这里,IPVS轮叫调度算法的粒度是基于每个连接的,同一用户的不同连接都会被调度到不同的服务器上,所以这种细粒度的轮叫调度要比DNS的轮叫调度优越很多。

2.2. 加权轮叫调度

    加权轮叫调度(Weighted Round-Robin Scheduling)算法可以解决服务器间性能不一的情况,它用相应的权值表示服务器的处理性能,服务器的缺省权值为1。假设服务器A的权值为1,B的权值为2,则表示服务器B的处理性能是A的两倍。加权轮叫调度算法是按权值的高低和轮叫方式分配请求到各服务器。权值高的服务器先收到的连接,权值高的服务器比权值低的服务器处理更多的连接,相同权值的服务器处理相同数目的连接数。加权轮叫调度算法流程如下:

加权轮叫调度算法流程
假设有一组服务器S = {S0, S1, …, Sn-1},W(Si)表示服务器Si的权值,一个
指示变量i表示上一次选择的服务器,指示变量cw表示当前调度的权值,max(S)
表示集合S中所有服务器的最大权值,gcd(S)表示集合S中所有服务器权值的最大
公约数。变量i和cw最初都被初始化为零。

while (true) {
        if (i == 0) {
                cw = cw - gcd(S);
                if (cw <= 0) {
                cw = max(S);
                if (cw == 0)
                        return NULL;
                }
        } else i = (i + 1) mod n;
        if (W(Si) >= cw)
                return Si;
}

    例如,有三个服务器A、B和C分别有权值4、3和2,则在一个调度周期内(mod sum(W(Si)))调度序列为AABABCABC。加权轮叫调度算法还是比较简单和高效。当请求的服务时间变化很大,单独的加权轮叫调度算法依然会导致服务器间的负载不平衡。

    从上面的算法流程中,我们可以看出当服务器的权值为零时,该服务器不被被调度;当所有服务器的权值为零,即对于任意i有W(Si)=0,则没有任何服务器可用,算法返回NULL,所有的新连接都会被丢掉。加权轮叫调度也无需记录当前所有连接的状态,所以它也是一种无状态调度。

2.3. 最小连接调度

    最小连接调度(Least-Connection Scheduling)算法是把新的连接请求分配到当前连接数最小的服务器。最小连接调度是一种动态调度算法,它通过服务器当前所活跃的连接数来估计服务器的负载情况。调度器需要记录各个服务器已建立连接的数目,当一个请求被调度到某台服务器,其连接数加1;当连接中止或超时,其连接数减一。

    在系统实现时,我们也引入当服务器的权值为零时,表示该服务器不可用而不被调度,它的算法流程如下:

最小连接调度算法流程
假设有一组服务器S = {S0, S1, ..., Sn-1},W(Si)表示服务器Si的权值,
C(Si)表示服务器Si的当前连接数。

for (m = 0; m < n; m++) {
        if (W(Sm) > 0) {
                for (i = m+1; i < n; i++) {
                        if (W(Si) <= 0)
                                continue;
                        if (C(Si) < C(Sm))
                                m = i;
                }
                return Sm;
        }
}
return NULL;

    当各个服务器有相同的处理性能时,最小连接调度算法能把负载变化大的请求分布平滑到各个服务器上,所有处理时间比较长的请求不可能被发送到同一台服务器上。但是,当各个服务器的处理能力不同时,该算法并不理想,因为TCP连接处理请求后会进入TIME_WAIT状态,TCP的TIME_WAIT一般为2分钟,此时连接还占用服务器的资源,所以会出现这样情形,性能高的服务器已处理所收到的连接,连接处于TIME_WAIT状态,而性能低的服务器已经忙于处理所收到的连接,还不断地收到新的连接请求。

2.4. 加权最小连接调度

    加权最小连接调度(Weighted Least-Connection Scheduling)算法是最小连接调度的超集,各个服务器用相应的权值表示其处理性能。服务器的缺省权值为1,系统管理员可以动态地设置服务器的权值。加权最小连接调度在调度新连接时尽可能使服务器的已建立连接数和其权值成比例。加权最小连接调度的算法流程如下:

加权最小连接调度的算法流程
    假设有一组服务器S = {S0, S1, ..., Sn-1},W(Si)表示服务器Si的权值,
C(Si)表示服务器Si的当前连接数。所有服务器当前连接数的总和为
CSUM = ΣC(Si)  (i=0, 1, .. , n-1)。当前的新连接请求会被发送服务器Sm,
当且仅当服务器Sm满足以下条件
  (C(Sm) / CSUM)/ W(Sm) = min { (C(Si) / CSUM) / W(Si)}  (i=0, 1, . , n-1)
  其中W(Si)不为零
因为CSUM在这一轮查找中是个常数,所以判断条件可以简化为
  C(Sm) / W(Sm) = min { C(Si) / W(Si)}  (i=0, 1, . , n-1)
  其中W(Si)不为零

    因为除法所需的CPU周期比乘法多,且在Linux内核中不允许浮点除法,服务器的
权值都大于零,所以判断条件C(Sm) / W(Sm) > C(Si) / W(Si) 可以进一步优化
为C(Sm)*W(Si) > C(Si)* W(Sm)。同时保证服务器的权值为零时,服务器不被调
度。所以,算法只要执行以下流程。

for (m = 0; m < n; m++) {
        if (W(Sm) > 0) {
                for (i = m+1; i < n; i++) {
                        if (C(Sm)*W(Si) > C(Si)*W(Sm))
                                m = i;
                }
                return Sm;
        }
}
return NULL;


2.5. 基于局部性的最少链接调度

    基于局部性的最少链接调度(Locality-Based Least Connections Scheduling,以下简称为LBLC)算法是针对请求报文的目标IP地址的负载均衡调度,目前主要用于Cache集群系统,因为在Cache集群中客户请求报文的目标IP地址是变化的。这里假设任何后端服务器都可以处理任一请求,算法的设计目标是在服务器的负载基本平衡情况下,将相同目标IP地址的请求调度到同一台服务器,来提高各台服务器的访问局部性和主存Cache命中率,从而整个集群系统的处理能力。

    LBLC调度算法先根据请求的目标IP地址找出该目标IP地址最近使用的服务器,若该服务器是可用的且没有超载,将请求发送到该服务器;若服务器不存在,或者该服务器超载且有服务器处于其一半的工作负载,则用“最少链接”的原则选出一个可用的服务器,将请求发送到该服务器。该算法的详细流程如下:

LBLC调度算法流程
    假设有一组服务器S = {S0, S1, ..., Sn-1},W(Si)表示服务器Si的权值,
C(Si)表示服务器Si的当前连接数。ServerNode[dest_ip]是一个关联变量,表示
目标IP地址所对应的服务器结点,一般来说它是通过Hash表实现的。WLC(S)表示
在集合S中的加权最小连接服务器,即前面的加权最小连接调度。Now为当前系统
时间。

if (ServerNode[dest_ip] is NULL) then {
        n = WLC(S);
        if (n is NULL) then return NULL;
        ServerNode[dest_ip].server = n;
} else {
        n = ServerNode[dest_ip].server;
        if ((n is dead) OR
            (C(n) > W(n) AND
             there is a node m with C(m) < W(m)/2))) then {
                n = WLC(S);
                if (n is NULL) then return NULL;
                ServerNode[dest_ip].server = n;
        }
}
ServerNode[dest_ip].lastuse = Now;
return n;

    此外,对关联变量ServerNode[dest_ip]要进行周期性的垃圾回收(Garbage Collection),将过期的目标IP地址到服务器关联项进行回收。过期的关联项是指哪些当前时间(实现时采用系统时钟节拍数jiffies)减去最近使用时间超过设定过期时间的关联项,系统缺省的设定过期时间为24小时。

2.6. 带复制的基于局部性最少链接调度

    带复制的基于局部性最少链接调度(Locality-Based Least Connections with Replication Scheduling,以下简称为LBLCR)算法也是针对目标IP地址的负载均衡,目前主要用于Cache集群系统。它与LBLC算法的不同之处是它要维护从一个目标IP地址到一组服务器的映射,而LBLC算法维护从一个目标IP地址到一台服务器的映射。对于一个“热门”站点的服务请求,一台Cache服务器可能会忙不过来处理这些请求。这时,LBLC调度算法会从所有的Cache服务器中按“最小连接”原则选出一台Cache服务器,映射该“热门”站点到这台Cache服务器,很快这台Cache服务器也会超载,就会重复上述过程选出新的Cache服务器。这样,可能会导致该“热门”站点的映像会出现在所有的Cache服务器上,降低了Cache服务器的使用效率。LBLCR调度算法将“热门”站点映射到一组Cache服务器(服务器集合),当该“热门”站点的请求负载增加时,会增加集合里的Cache服务器,来处理不断增长的负载;当该“热门”站点的请求负载降低时,会减少集合里的Cache服务器数目。这样,该“热门”站点的映像不太可能出现在所有的Cache服务器上,从而提供Cache集群系统的使用效率。

    LBLCR算法先根据请求的目标IP地址找出该目标IP地址对应的服务器组;按“最小连接”原则从该服务器组中选出一台服务器,若服务器没有超载,将请求发送到该服务器;若服务器超载;则按“最小连接”原则从整个集群中选出一台服务器,将该服务器加入到服务器组中,将请求发送到该服务器。同时,当该服务器组有一段时间没有被修改,将最忙的服务器从服务器组中删除,以降低复制的程度。LBLCR调度算法的流程如下:

LBLCR调度算法流程
    假设有一组服务器S = {S0, S1, ..., Sn-1},W(Si)表示服务器Si的权值,
C(Si)表示服务器Si的当前连接数。ServerSet[dest_ip]是一个关联变量,表示
目标IP地址所对应的服务器集合,一般来说它是通过Hash表实现的。WLC(S)表示
在集合S中的加权最小连接服务器,即前面的加权最小连接调度;WGC(S)表示在
集合S中的加权最大连接服务器。Now为当前系统时间,lastmod表示集合的最近
修改时间,T为对集合进行调整的设定时间。

if (ServerSet[dest_ip] is NULL) then {
        n = WLC(S);
        if (n is NULL) then return NULL;
        add n into ServerSet[dest_ip];
} else {
        n = WLC(ServerSet[dest_ip]);
        if ((n is NULL) OR
            (n is dead) OR
            (C(n) > W(n) AND
             there is a node m with C(m) < W(m)/2))) then {
                n = WLC(S);
                if (n is NULL) then return NULL;
                add n into ServerSet[dest_ip];
        } else
        if (|ServerSet[dest_ip]| > 1 AND
            Now - ServerSet[dest_ip].lastmod > T) then {
                m = WGC(ServerSet[dest_ip]);
                remove m from ServerSet[dest_ip];
        }
}
ServerSet[dest_ip].lastuse = Now;
if (ServerSet[dest_ip] changed) then
        ServerSet[dest_ip].lastmod = Now;
return n;

    此外,对关联变量ServerSet[dest_ip]也要进行周期性的垃圾回收(Garbage Collection),将过期的目标IP地址到服务器关联项进行回收。过期的关联项是指哪些当前时间(实现时采用系统时钟节拍数jiffies)减去最近使用时间(lastuse)超过设定过期时间的关联项,系统缺省的设定过期时间为24小时。

2.7. 目标地址散列调度

    目标地址散列调度(Destination Hashing Scheduling)算法也是针对目标IP地址的负载均衡,但它是一种静态映射算法,通过一个散列(Hash)函数将一个目标IP地址映射到一台服务器。

    目标地址散列调度算法先根据请求的目标IP地址,作为散列键(Hash Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器,否则返回空。该算法的流程如下:

目标地址散列调度算法流程
    假设有一组服务器S = {S0, S1, ..., Sn-1},W(Si)表示服务器Si的权值,
C(Si)表示服务器Si的当前连接数。ServerNode[]是一个有256个桶(Bucket)的
Hash表,一般来说服务器的数目会运小于256,当然表的大小也是可以调整的。
算法的初始化是将所有服务器顺序、循环地放置到ServerNode表中。若服务器的
连接数目大于2倍的权值,则表示服务器已超载。

n = ServerNode[hashkey(dest_ip)];
if ((n is dead) OR
        (W(n) == 0) OR
    (C(n) > 2*W(n))) then
        return NULL;
return n;

    在实现时,我们采用素数乘法Hash函数,通过乘以素数使得散列键值尽可能地达到较均匀的分布。所采用的素数乘法Hash函数如下:

素数乘法Hash函数
static inline unsigned hashkey(unsigned int dest_ip)
{
    return (dest_ip* 2654435761UL) & HASH_TAB_MASK;
}
其中,2654435761UL是2到2^32 (4294967296)间接近于黄金分割的素数,
  (sqrt(5) - 1) / 2 =  0.618033989
  2654435761 / 4294967296 = 0.618033987

2.8. 源地址散列调度

    源地址散列调度(Source Hashing Scheduling)算法正好与目标地址散列调度算法相反,它根据请求的源IP地址,作为散列键(Hash Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器,否则返回空。它采用的散列函数与目标地址散列调度算法的相同。它的算法流程与目标地址散列调度算法的基本相似,除了将请求的目标IP地址换成请求的源IP地址,所以这里不一一叙述。

    在实际应用中,源地址散列调度和目标地址散列调度可以结合使用在防火墙集群中,它们可以保证整个系统的唯一出入口。

3. 动态反馈负载均衡算法

    动态反馈负载均衡算法考虑服务器的实时负载和响应情况,不断调整服务器间处理请求的比例,来避免有些服务器超载时依然收到大量请求,从而提高整个系统的吞吐率。图1显示了该算法的工作环境,在负载调度器上运行Monitor Daemon进程,Monitor Daemon来监视和收集各个服务器的负载信息。Monitor Daemon可根据多个负载信息算出一个综合负载值。Monitor Daemon将各个服务器的综合负载值和当前权值算出一组新的权值,若新权值和当前权值的差值大于设定的阀值,Monitor Daemon将该服务器的权值设置到内核中的IPVS调度中,而在内核中连接调度一般采用加权轮叫调度算法或者加权最小连接调度算法。

3.1. 连接调度

    当客户通过TCP连接访问网络访问时,服务所需的时间和所要消耗的计算资源是千差万别的,它依赖于很多因素。例如,它依赖于请求的服务类型、当前网络带宽的情况、以及当前服务器资源利用的情况。一些负载比较重的请求需要进行计算密集的查询、数据库访问、很长响应数据流;而负载比较轻的请求往往只需要读一个HTML页面或者进行很简单的计算。

    请求处理时间的千差万别可能会导致服务器利用的倾斜(Skew),即服务器间的负载不平衡。例如,有一个WEB页面有A、B、C和D文件,其中D是大图像文件,浏览器需要建立四个连接来取这些文件。当多个用户通过浏览器同时访问该页面时,最极端的情况是所有D文件的请求被发到同一台服务器。所以说,有可能存在这样情况,有些服务器已经超负荷运行,而其他服务器基本是闲置着。同时,有些服务器已经忙不过来,有很长的请求队列,还不断地收到新的请求。反过来说,这会导致客户长时间的等待,觉得系统的服务质量差。

3.1.1. 简单连接调度

    简单连接调度可能会使得服务器倾斜的发生。在上面的例子中,若采用轮叫调度算法,且集群中正好有四台服务器,必有一台服务器总是收到D文件的请求。这种调度策略会导致整个系统资源的低利用率,因为有些资源被用尽导致客户的长时间等待,而其他资源空闲着。

3.1.2. 实际TCP/IP流量的特征

    网络流量是呈波浪型发生的,在一段较长时间的小流量后,会有一段大流量的访问,然后是小流量,这样跟波浪一样周期性地发生。文献[2,3,4,5]揭示在WAN和LAN上网络流量存在自相似的特征,在WEB访问流也存在自相似性。这就需要一个动态反馈机制,利用服务器组的状态来应对访问流的自相似性。

3.2. 动态反馈负载均衡机制

    TCP/IP流量的特征通俗地说是有许多短事务和一些长事务组成,而长事务的工作量在整个工作量占有较高的比例。所以,我们要设计一种负载均衡算法,来避免长事务的请求总被分配到一些机器上,而是尽可能将带有毛刺(Burst)的分布分割成相对较均匀的分布。

    我们提出基于动态反馈负载均衡机制,来控制新连接的分配,从而控制各个服务器的负载。例如,在IPVS调度器的内核中使用加权轮叫调度(Weighted Round-Robin Scheduling)算法来调度新的请求连接;在负载调度器的用户空间中运行Monitor Daemon。Monitor Daemon定时地监视和收集各个服务器的负载信息,根据多个负载信息算出一个综合负载值。Monitor Daemon将各个服务器的综合负载值和当前权值算出一组新的权值。当综合负载值表示服务器比较忙时,新算出的权值会比其当前权值要小,这样新分配到该服务器的请求数就会少一些。当综合负载值表示服务器处于低利用率时,新算出的权值会比其当前权值要大,来增加新分配到该服务器的请求数。若新权值和当前权值的差值大于设定的阀值,Monitor Daemon将该服务器的权值设置到内核中的IPVS调度中。过了一定的时间间隔(如2秒钟),Monitor Daemon再查询各个服务器的情况,并相应调整服务器的权值;这样周期性地进行。可以说,这是一个负反馈机制,使得服务器保持较好的利用率。

    在加权轮叫调度算法中,当服务器的权值为零,已建立的连接会继续得到该服务器的服务,而新的连接不会分配到该服务器。系统管理员可以将一台服务器的权值设置为零,使得该服务器安静下来,当已有的连接都结束后,他可以将该服务器切出,对其进行维护。维护工作对系统都是不可少的,比如硬件升级和软件更新等,零权值使得服务器安静的功能很主要。所以,在动态反馈负载均衡机制中我们要保证该功能,当服务器的权值为零时,我们不对服务器的权值进行调整。

3.3. 综合负载

    在计算综合负载时,我们主要使用两大类负载信息:输入指标和服务器指标。输入指标是在调度器上收集到的,而服务器指标是在服务器上的各种负载信息。我们用综合负载来反映服务器当前的比较确切负载情况,对于不同的应用,会有不同的负载情况,这里我们引入各个负载信息的系数,来表示各个负载信息在综合负载中轻重。系统管理员根据不同应用的需求,调整各个负载信息的系数。另外,系统管理员设置收集负载信息的时间间隔。

    输入指标主要是在单位时间内服务器收到新连接数与平均连接数的比例,它是在调度器上收集到的,所以这个指标是对服务器负载情况的一个估计值。在调度器上有各个服务器收到连接数的计数器,对于服务器Si,可以得到分别在时间T1和T2时的计数器值Ci1和Ci2,计算出在时间间隔T2-T1内服务器Si收到新连接数Ni = Ci2 - Ci1。这样,得到一组服务器在时间间隔T2-T1内服务器Si收到新连接数{Ni},服务器Si的输入指标INPUTi为其新连接数与n台服务器收到平均连接数的比值,其公式为

    服务器指标主要记录服务器各种负载信息,如服务器当前CPU负载LOADi、服务器当前磁盘使用情况Di、当前内存利用情况Mi和当前进程数目Pi。有两种方法可以获得这些信息;一是在所有的服务器上运行着SNMP(Simple Network Management Protocol)服务进程,而在调度器上的Monitor Daemon通过SNMP向各个服务器查询获得这些信息;二是在服务器上实现和运行收集信息的Agent,由Agent定时地向Monitor Daemon报告负载信息。若服务器在设定的时间间隔内没有响应,Monitor Daemon认为服务器是不可达的,将服务器在调度器中的权值设置为零,不会有新的连接再被分配到该服务器;若在下一次服务器有响应,再对服务器的权值进行调整。再对这些数据进行处理,使其落在[0, ∞)的区间内,1表示负载正好,大于1表示服务器超载,小于1表示服务器处于低负载状态。获得调整后的数据有DISKi、MEMORYi和PROCESSi。

    另一个重要的服务器指标是服务器所提供服务的响应时间,它能比较好地反映服务器上请求等待队列的长度和请求的处理时间。调度器上的Monitor Daemon作为客户访问服务器所提供的服务,测得其响应时间。例如,测试从WEB服务器取一个HTML页面的响应延时,Monitor Daemon只要发送一个“GET /”请求到每个服务器,然后记录响应时间。若服务器在设定的时间间隔内没有响应,Monitor Daemon认为服务器是不可达的,将服务器在调度器中的权值设置为零。同样,我们对响应时间进行如上调整,得到RESPONSEi。

    这里,我们引入一组可以动态调整的系数Ri来表示各个负载参数的重要程度,其中ΣRi = 1。综合负载可以通过以下公式计算出:

    例如,在WEB服务器集群中,我们采用以下系数{0.1, 0.3, 0.1, 0.1, 0.1, 0.3},认为服务器的CPU负载和请求响应时间较其他参数重要一些。若当前的系数Ri不能很好地反映应用的负载,系统管理员可以对系数不断地修正,直到找到贴近当前应用的一组系数。

    另外,关于查询时间间隔的设置,虽然很短的间隔可以更确切地反映各个服务器的负载,但是很频繁地查询(如1秒钟几次)会给调度器和服务器带来一定的负载,如频繁执行的Monitor Daemon在调度器会有一定的开销,同样频繁地查询服务器指标会服务器带来一定的开销。所以,这里要有个折衷(Tradeoff),我们一般建议将时间间隔设置在5到20秒之间。

3.4. 权值计算

    当服务器投入集群系统中使用时,系统管理员对服务器都设定一个初始权值DEFAULT_WEIGHTi,在内核的IPVS调度中也先使用这个权值。然后,随着服务器负载的变化,对权值进行调整。为了避免权值变成一个很大的值,我们对权值的范围作一个限制[DEFAULT_WEIGHTi, SCALE*DEFAULT_WEIGHTi],SCALE是可以调整的,它的缺省值为10。

    Monitor Daemon周期性地运行,若DEFAULT_WEIGHTi不为零,则查询该服务器的各负载参数,并计算出综合负载值AGGREGATE_LOADi。我们引入以下权值计算公式,根据服务器的综合负载值调整其权值。

    在公式中,0.95是我们想要达到的系统利用率,A是一个可调整的系数(缺省值为5)。当综合负载值为0.95时,服务器权值不变;当综合负载值大于0.95时,权值变小;当综合负载值小于0.95时,权值变大。若新权值大于SCALE*DEFAULT_WEIGHTi,我们将新权值设为SCALE*DEFAULT_WEIGHTi。若新权值与当前权值的差异超过设定的阀值,则将新权值设置到内核中的IPVS调度参数中,否则避免打断IPVS调度的开销。我们可以看出这是一个负反馈公式,会使得权值调整到一个稳定点,如系统达到理想利用率时,权值是不变的。

    在实际使用中,若发现所有服务器的权值都小于他们的DEFAULT_WEIGHT,则说明整个服务器集群处于超载状态,这时需要加入新的服务器结点到集群中来处理部分负载;反之,若所有服务器的权值都接近于SCALE*DEFAULT_WEIGHT,则说明当前系统的负载都比较轻。

3.5. 一个实现例子

    我们在RedHat集群管理工具Piranha[6]中实现了一个简单的动态反馈负载均衡算法。在综合负载上,它只考虑服务器的CPU负载(Load Average),使用以下公式进行权值调整:

    服务器权值调整区间为[DEFAULT_WEIGHTi, 10*DEFAULT_WEIGHTi],A为DEFAULT_WEIGHTi /2,而权值调整的阀值为DEFAULT_WEIGHTi /4。1是所想要达到的系统利用率。Piranha每隔20秒查询各台服务器的CPU负载,进行权值计算和调整。

4. 小结

本文主要讲述了IP虚拟服务器在内核中实现的八种连接调度算法:

·轮叫调度(Round-Robin Scheduling)
·加权轮叫调度(Weighted Round-Robin Scheduling)
·最小连接调度(Least-Connection Scheduling)
·加权最小连接调度(Weighted Least-Connection Scheduling)
·基于局部性的最少链接(Locality-Based Least Connections Scheduling)
·带复制的基于局部性最少链接(Locality-Based Least Connections with Replication Scheduling)
·目标地址散列调度(Destination Hashing Scheduling)
·源地址散列调度(Source Hashing Scheduling)

    因为请求的服务时间差异较大,内核中的连接调度算法容易使得服务器运行出现倾斜。为此,给出了一个动态反馈负载均衡算法,结合内核中的加权连接调度算法,根据动态反馈回来的负载信息来调整服务器的权值,来调整服务器间处理请求数的比例,从而避免服务器间的负载不平衡。动态反馈负载算法可以较好地避免服务器的倾斜,提高系统的资源使用效率,从而提高系统的吞吐率。

[目录]


安装配置

    这篇文档将解释怎样建立和管理可提供高质量的web和ftp服务的lvs(linux虚拟服务器)集群。

-------------------------------------------------------------------------------
目录
-------------------------------------------------------------------------------
简介
一个lvs集群的组件
lvs集群的背景
硬件/网络的要求
lvs路由的必要条件
集群节点内部连接的必要条件
安装软件
配置一个lvs集群
例子---建立一个5节点的集群

[目录]


简介

    linux虚拟服务器集群是一个被特别配置的,可提供高性能web和ftp服务的服务器的集合。在下面的图表中阐述了lvs集群是怎样工作的。到达一个lvs集群的服务请求被寻址到一个虚拟的服务器上。一个公开广告的,完整网域名称与一个浮动的ip地址相关联,这种浮动ip地址能迁移到不同的节点。

Figure 1. LVS Cluster Interactions


                             _/\__/\_
                            |        |
                           / Internet \
                           \_  _  _  _/
                             \/ \/ \/
                                 |
                                 |
                       Virtual Server IP/FQDN
             |------------------------------------------|
             |eth0                                      |eth0
       ------|-----                              -------|-----
       | Primary  |                              |   Backup  |
       |  Node    |                              |    Node   |    LVS
       |          |                              |           |  routers
       ------|-----                              -------|-----
             |eth1                                      |eth1
             |-------|------------|-----------------|---|
                     |            |                 |
                     |            |                 |
                     |            |                 |
                |----|----|  |----|----|       |----|----|
                | Web/FTP |  | Web/FTP |       | Web/FTP |        real
                |  Node#1 |  |  Node#2 |  ...  |  Node#n |       servers
                |_________|  |_________|       |_________|


    一个lvs集群由一个或两个路由节点和很多数量的web/ftp服务器(底部)组成。我们把lvs路由节点称作lvs 路由,而将web/ftp服务器的汇集称作真实服务器。真实服务器通过内部网络相连。lvs 路由同时相连着内部网络和公共网络。对于把lvs 路由与内部网络和公共网络连接起来的适配器(图中的eth0和eth1)可以是任何的设备,但是每个路由上的设备必须是相同的。
    在同一时刻,仅有一个路由是激活的。激活的路由扮演的角色是将虚拟服务器上的服务请求重定向到真实服务器。重定向基于四种负载平衡算法规则中的一种(如表一)。激活的路由通过三种被支持方式中的一种(如图二),动态的监视真实服务器的健康情况和每个服务器的工作量。如果有一个真实服务器无效了,在工作的router将停止向这台服务器发送任务直到服务器恢复正常运转。

    lvs 路由定期通过公共网互相交换“我活着的”心脏跳动信息。当备份的节点在与其在一段时间间隔内没有接收到心脏跳动信息,它将启动failover以取代激活的路由。在failover过程中,备份路由将接管失败的路由的浮动ip地址(在集群配置文件中指示),利用arp(地址解析协议)欺骗技术,开始宣布自己为失败节点ip包寻址的目的地。当失败的节点恢复服务时,它将承担热备份这个角色。

    当前,lvs集群支持一个路由选择的方式,net address translation(nat)(将来,tunneling和direct routing将被加入。)。下面的图表阐述了一个nat虚拟服务器是怎样工作的。

Figure 2. An LVS Cluster Implemented with NAT Routing

                             _/\__/\_
                            |        |
                           / Internet \
                           \_  _  _  _/
                             \/ \/ \/
                                 |
                                 |
             |------------------------------------------| public
                                 |                        network
                            eth0 | virtual server IP address
                       --------------------
                       |   active router  |
                       |                  |
                       --------------------
                            eth1 | NAT router IP address
                                 |
             |-------|-------------------------|--------| private
                     |                         |          network
                     |                         |
                     |                         |
                |----|----------|  |-----------|---|
                | real server#1 |  | real server#2 |
                |               |  |               |  ...
                |_______________|  |_______________|


    客户端的服务请求到达一个虚拟服务器的ip地址。这是个公共广告地址,它被网站管理员与一个完整网域名称相关联(例如,lvs.agax.com)。在叙述中只看到了一个虚拟服务器地址,但是也可有多个。一个独立的虚拟服务器地址包含了三个部分: 一个协议(tcp或udp),一个ip地址和端口号。

    虚拟服务器的地址的ip部分是浮动的地址。他们也许是一个通过lvs路由连接到公共网络的设备的别名(例如,eth0:1),或者是每个ip地址与一个单独的设备相联系。nat路由ip地址也是个浮动ip地址,每个在内部网络中的真实服务器使用这个ip地址为默认路由,与活动的路由通信。对于虚拟服务器的地址,nat路由ip地址可以是连接虚拟服务器到真实服务器网络的一个设备的别名(例如,eth1:1),或者也可与一个独立的设备相关联。

    虚拟服务器和nat寻址只可在被激活的路由上才可运行。因此,如果激活状态下的路由失败了,通过接管浮动ip地址,备份路由便可运行虚拟服务器和nat寻址。如图二所示的拓扑学原理,虚拟服务器寻址在eth0设备上运行,而nat路由寻址在eth1上运行。

    核心中的ipvs表映射所有内部网络中从虚拟服务器地址到真实服务器地址的请求。例如,在一个虚拟服务器1.2.3.1上,一个tcp请求被寻址到80端口也许被按指定路线发送到真实服务器192.168.1.2的80端口。在ipvs表中,对任务实际映射到哪个真实服务器上是基于使用某个负载平衡规则。表一描述了被支持的负载平衡方式。

Table 1. Load-balancing Methods

   名称                            描述
Round robin                将工作平均的分配到服务器

Least-connections          向较少连接的服务器分配较多的工作
                           (IPVS 表存储了所有的活动的连接。)

Weighted round robin       向较大容量的服务器分配较多的工作。
                           容量通过用户指定的砝码来说明,
                           可以根据装载信息动态的向上或向下调整。

Weighted least-connections 考虑它们的容量向较少连接的服务器分配较多的工作。
                           容量通过用户指定的砝码来说明,
                           可以根据装载信息动态的向上或向下调整。

    当真实服务器处理一个请求时,它将包返回到活动的路由,包中真实服务器的地址也被虚拟服务器的地址所代替。在这种规则下,对于客户的请求,内部网络中的真实服务器被伪装起来。


[目录]


组件

    下面介绍一个lvs集群的组件。

pulse
    这是控制启动其他守护进程的过程所需的。正常情况下它是在系统启动时,在lvs路由上通过/etc/rc.d/init.d/pulse脚本启动。通过pulse,提供一种简单的心跳检测,非活动的lvs路由决定活动的路由是否健康,是否需要启动failover。

lvs
    lvs守护进程在lvs路由上运行。它读入配置文件,调用ipvsadm来建立和维护ipvs路由选择表。

nanny
    nanny将监视在活动的lvs路由上运行的守护进程。通过这个守护进程,活动的路由决定每个真实服务器是否健康,同时获得服务器的工作量。它是一个被每个虚拟服务器使用的,独立的在每个真实服务器上运行的进程。

/etc/lvs.cf
    只是lvs集群的配置文件。直接或间接的,所有的守护进程都从这个文件中获得它们的配置信息。

piranha
    这是一个图形化的监视,配置和管理lvs集群的工具。通常情况下,你将用这个工具来维护/etc/lvs.cf,重新启动运行的守护进程,监视一个lvs集群。

ipvsadm
    这个工具用来更新核心中的ipvs路由选择表。lvs守护进程通过调用ipvsadm向ipvs路由选择表添加,改变或删除项目来建立和管理一个lvs集群。

[目录]


背景

lvs集群的背景
    redhat lvs集群是基于linux社团直接的贡献,要不然就是linux社团工程使它的成分更富于灵感,更丰富。

    lvs集群主要是源于wensong zhang的linux虚拟服务器核心选择规则(请看http://www.linuxvirtualserver.org)。当前redhat lvs支持的功能:

    建立虚拟的服务器:公共网络中的服务请求到达的地址,采用浮动ip地址。

    虚拟服务器上的服务请求到真实服务器上的路由选择。

    负载平衡(看表一)。

    包转发中的网络地址翻译。

    lvs的创新被redhat lvs集群所支持,它以很多的技术为基础,包括网络地址的翻译(nat),ip伪装,端口转发。对于一般性的讨论和相关howto的索引以及有关的主题,请看http://www.linas.org/linux/load.html

[目录]


硬件/网络的要求

硬件/网络的要求
    一个lvs集群由一个或两个lvs路由,一些提供web和ftp服务的真实服务器组成。下面描述了连接和硬件的要求。

lvs路由
    一个基本的lvs路由的要求是一个linux服务器。这台机器要有两个网络适配器,一个与公共网络连接而另一个与真实服务器的内部网络连接。

    如果要有failover功能,你需要有第二个linux服务器来作为备份lvs路由。这台机器也需要两块适配器来连接公共网络和有真实服务器的内部网络。两个lvs路由中的适配器设备必须相匹配。因此,如果主lvs路由设备eth0和eth1分别与公共网和内部网相连,在备份lvs路由中的相同设备也要分别与公共网和内部网连接。注意,备份lvs路由是个纯热候补机器。

真实服务器
    lvs路由连接的内部网包括一定数量的web/ftp服务器主机。寻址到虚拟服务器上的工作被重定向到真实的服务器,这些服务器可以是各种各样的,运行任何操作系统或是web服务器的计算机平台。

    在配置过程中,你对每个真实服务器的砝码进行赋值。这是一个反映每个服务器处理能力的,与其它服务器相关联在一起的整数(以内存,处理器速度,处理器个数,等等为基础)。它们是成比例的(2/1,20/10,200/100),这很有效。例如,分配的砝码是2000的服务器表示它的计算能力是砝码为1000的服务器的两倍。通过两个有效的任务计划规则(表一所示),以装载信息为基础来分配砝码,从而动态的调节砝码。你应该准备制定一个准确的砝码。


[目录]


路由的必要条件

lvs路由的必要条件
    lvs路由要求redhat linux6.1或更高的版本。在lvs路由上,packet-forwarding,packet defragmenting和ip masquerading必须是激活的。

    激活packet-forwarding和defragmenting,确定/etc/sysconf/network中由这两行:

    FORWARD_IPV4=yes
    DEFRAG_IPV4=yes

    这些行将使/etc/rc.d/rc.sysinit在路由启动时执行:

    echo 1 > /proc/sys/net/ipv4/ip_forward
    echo 1 > /proc/sys/net/ipv4/ip_always_defrag

    激活ip masquerading,用这个命令:

    ipchains -A forward -j MASQ -s n.n.n.n/type -d 0.0.0.0/0

    其中:

n.n.n.n是内部子网的真实服务器的连接地址。

类型是8.16.24.32,他们表示地址的类型和掩码:      netmask         | type | Subnet
     ~~~~~~~~~~~~~~~~|~~~~~~|~~~~~~~~~~~~~~~
     255.0.0.0       | 8    | Class A
     255.255.0.0     | 16   | Class B
     255.255.255.0   | 24   | Class C
     255.255.255.255 | 32   | Point-to-point

    你也许要将ipchains命令加入到init脚本中去(例如,/etc/rc.d/rc.local),这样在lvs路由系统启动时masquerading将被配置好。

    ipchains是一个在核心的tcp栈中设定的,用来产生和管理防火墙规则的工具。masquerading使用这些规则的一个小的部分,它允许机器通过内部网络的ip与外面的网络通信。使用ipchains对系统的安全有很大的影响。如果你对系统安全有兴趣,请阅读ipchains howto。(http://www.linuxdoc.org/HOWTO/IPCHAINS-HOWTO.html).


[目录]


节点内部连接的必要条件

    在配置过程中,你选择的工具集(rsh或ssh)将被用于在lvs路由中对/etc/lvs.cf
配置文件进行同步。选择的工具必须在lvs路由中被激活,如此这样每个路由上的root才可在没有管理者介入的情况下登陆到另外的路由上去。

    并且在配置过程中,你也要选择工具(uptime,ruptime,或rup)在活动的路由上用来监视真实服务器上的工作量。在真实服务器上激活这些被选中的工具。如果不能做到这点(例如,你的一个真实服务器是windows/nt web服务器),集群将仍然提供高性能的服务。然而,weighted round robin 和weighted least-connections(表一介绍的)运算规则将受到影响。换句话说,因为装载的信息将不再有效,用户分配的砝码将静态的被应用而不是动态的基于服务器工作量来调整。

    表二描述了在通常情况下,你要在源主机和目标主机上做什么来激活这些工具。要了解详细的情况,请看man文件。注意,用rsh和ssh,root必须能在网络中登陆。为了在redhat linux系统中激活远程登陆,从文件/etc/pam.d/login中移去下面这一行:

auth      required     /lib/security/pam_security.so

    这是个安全漏洞,虽然很小。确信你的lvs节点有一个合适的防火墙,这样可以允许值得信赖的节点登陆。

rsh
    在目标主机上的根目录下创建一个.rhosts文件,其属性为600,注明源 主机和用户(例如,foo.host1.com root)。

ssh
    获得并安装工具,由于法律原因没有在国际的linux版本发行。在源主机和目标主机上禁止通过所有其它的方式远程登陆,使用./ssh/authorized_keys建立基于rsa的认证,然后启动sshd。

uptime
    如上所示的方法,在每一个真实服务器上激活rsh或是ssh。

ruptime
    设置在启动时,每一个lvs路由和真实服务器上启动rwhod。

rup
    设置在启动时,每一个真实服务器启动rpc.rstatd。

[目录]


安装软件

安装软件
lvs集群的软件包含三个发行的rpm软件包:

piranha(程序)
piranha-gui(图形界面的配置工具)
piranha-docs(文档) 你可用这命令从6.1的光盘中安装这些软件包:

   #rpm -Uvh /mnt/cdrom/RedHat/RPMS/piranha*.rpm

因为你的硬件平台的缘故,获得这些软件包合理的升级,请访问redhat的网站http://www.redhat.com/corp/support/errata/rh61-errata-updates.html


[目录]


配置

配置一个lvs集群
    你可以从lvs路由通过编辑配置文件和启动或重新启动pulse守护进程,来安装和维护lvs集群。特别的几个步骤是:

    在主路由上,编辑配置文件/etc/lvs.cf。

    拷贝编辑好的配置文件到备份路由上。

    首先在主路由上启动(或重启)pulse守护进程,然后是备份路由。

    你可用你喜欢的编辑器编辑配置文件,从shell中执行这几步。在shell中的启动重启和停止的命令是:

    /etc/rc.d/init.d/pulse start
    /etc/rc.d/init.d/pulse restart
    /etc/rc.d/init.d/pulse stop

    当需要时,pulse守护进程启动或重启其他的lvs集群守护进程,它们的配置文件信息是直接或间接的从当前的配置文件中获得的。

    如果你停止pulse(为了关闭集群),首先要停止在备份路由上的pulse。这将阻止有可能备份路由代替激活的路由。

    作为一种选择,你可用piranha来建立,监视和管理你的lvs集群。可在它的窗口中设置或是改变/etc/lvs.cf中的一些行,这里还有启动,停止和重启集群的按钮。使用piranha的要求是你的lvs路由必须配置好了x window系统。使用piranha的好处是它可同步主路由和备份路由上的配置文件,你可在激活的路由上执行所有的管理任务执行。

    下一章将描述lvs集群的配置文件。如果你要手工配置这些文件,请阅读这一章。如果你选择使用piranha,请看 the section called Using the Piranha Configuration Tool.

编辑配置文件
    /etc/lvs.cf文件有三个部分。全局部分,在表三中描述,建立lvs路由和特殊的网络和心脏跳动检测参数。这有一组集群的参数。预设虚拟服务器一部分,在表四中描述,定义虚拟服务器的地址,建立虚拟服务器和真实服务器之间的关联,还有特别的任务计划参数。对每个被定义的虚拟服务器都有一组独立的参数。预设真实服务器一部分在表五中描述,定义从每个虚拟服务器到真实服务器的路由选择。对每个虚拟服务器有一组参数。

Table 3. Setting Global Parameters
参数 描述

primary =
    输入通过连接主lvs路由到公共网络的适配器的ip地址。

backup = backup=
    输入通过连接备份lvs路由到公共网络的适配器的ip地址。

heartbeat_port =
    输入在主路由和备份路由上使用心脏跳动检测的端口号。

keepalive =
    输入心脏跳动检测时间间隔是多少秒。

deadtime =
    输入在等待几秒后宣布无响应路由死亡并且启动failover

rsh_command = [rsh|ssh]
    输入熟悉的命令以同步主路由和备份路由的配置文件。重点:在表二中讲述,你必须在主路由和备份路由上激活被选择的命令。

network = [nat|direct|tunnel]
    现在只有网络地址翻译被支持。
nat_router =
    输入浮动ip地址和nat路由设备。这个ip地址必须是每个真实服务器和活动lvs路由通信的默认路由。连接lvs路由到内部网络上的真实服务器的设备是ip地址的别名(例如,eth1:1)。在两个lvs路由上的设备必须是相同的(例如,eth1)。

Table 4. Setting Per-Virtual-Server Parameters
参数 描述

name
    输入一个唯一定义的虚拟服务器名字

address =
    输入虚拟服务器的ip地址:一个与全称域名相关联的浮动ip地址
active = [0|1]
    激活(1)或屏蔽(0)这个ip地址
load_monitor = [uptime|ruptime|rup]
    选择在活动路由上用于监视真实服务器工作量的工具(默认是uptime)。重点:如表二中所述,除非你在真实服务器上激活选好的命令,使用动态载入信息的运行规则,将被应用于静态的砝码上,而不是通过载入信息来调整砝码。如果你选择默认方式(uptime),这个你为了"rsh_command"而指定的工具,在登陆到真实服务器上时使用。在真实服务器端,这个工具必须被激活。

timeout =
    输入在真实服务器被确定死亡而移出路由表之前的一个失效时间(默认是10秒)

reentry =
    输入一个以恢复的真实服务器被重新加入到路由表中之前的持续正常的秒数(默认是180秒)。

port = [http/80|ftp/21]
    输入在虚拟服务器上的监听端口:http用80(默认)或ftp用21端口。或是你也可输入数字。

scheduler = [wlc|lc|wrr|rr]
    选择从虚拟服务器上到真实服务器,分配任务的运行规则(默认是wlc)选项在表一中描述。

Table 5. Setting Per-Real-Server Parameters
参数 描述

name
    输入唯一的真实服务器名字

address =
    输入真实服务器在内部网络中的ip地址

active = [0|1]
    激活(1)或是屏蔽(0)真实服务器

weight =
    输入一个指定这台服务器的处理能力的整数(默认是1),它与其它真实服务器相关联。

使用piranha配置工具

    启动piranha的方法时,成为root用户然后打入piranha &。当你这样做了后,它的主窗口将被打开。窗口由四个标签:
    控制/监视--第一个标签。用于start/stop/restart集群守护进程和监视运行状态。看 the section called Controls/Monitoring Tab.

Global Settings --
    用于设定主lvs路由和nat路由的ip地址。请看 the section called Global Settings Tab.

Redundancy --
    设定备份路由的地址和心脏跳动检测的参数。请看 the section called Redundancy Tab.

Virtual Servers --
    用于设定服务器地址,建立服务器地址和真实的web/ftp服务器主机之间的路由选择。请看 the section called Virtual Servers.

piranha窗口有一些这样的按钮:

OK -- 应用改变同时退出窗口。
Apply -- 应用改变但不退出窗口。
Close -- 不应用改变而退出窗口。

Controls/Monitoring Tab
区域/按钮 描述

Start/Stop
    当集群守护进程还没有运行时,这个按钮标记为开始:点击它来启动集群。当集群守护进程没有运行时,这个按钮标记为停止:点击它停止集群守护进程。

Add pulse daemon to this runlevel
    选择在这个运行级中,在系统启动时启动pulse。

Update information now
    点击来显示当前核心路由表的信息。

Auto-update
    选择在特定的时间间隔内自动显示核心路由表信息。


Global Settings Tab
区域/按钮 描述

Primary LVS server IP
    包含了lvs主路由的公共ip地址

NAT Router IP
    包含了与连接虚拟服务器网络到真实服务器网络的网络适配器相关联的浮动ip地址。这个地址被用作真实服务器与虚拟服务器通信的网关。如果这个节点失败,其地址将被lvs备份路由节点所继承。

NAT Router Device
    与nat路由ip地址相联系的设备的名字。这个通过地址别名来实现。例如,nat路由的ip可以为物理设备eth1化名为eth1:1。

Sync tool
    选择用来同步主路由和备份路由的工具。你选的工具必须激活,这样lvs路由才可相互登陆而不用输入密码。一般的过程请看表二 。


Redundancy Tab
区域/按钮 描述

Enable redundant server
    选择激活failover。

Redundant LVS server
    IP 包含备份路由的公共ip。

Heartbeat interval (seconds)
    包含了两次心脏跳动检测之间的秒数:备份lvs节点检测主lvs节点看是否还活着的时间间隔。

Assume dead after (seconds)
    如果时间用完了主lvs节点还无响应,备份路由将启动failover。在failover过程中,备份路由接管所有的在主lvs路由上处理的虚拟服务器的ip,无条件广播arps,通知它的mac地址作为寻址到主路由包的目标地址。

Heartbeat port
    输入在主路由和备份路由中用于心跳检测的端口。

Virtual Servers
    屏幕显示一排当前被定义的虚拟服务器的信息。点击一排信息来选择它。在屏幕右边的按钮是应用当前选择的虚拟服务器。点击删除是移去选择的虚拟服务器。

区域/按钮  描述

Status
    显示激活或屏蔽。点击屏蔽来关闭一个激活的虚拟服务器。点击激活来启动一个选择的虚拟服务器。改变状态后,你必须要重启pulse守护进程来使改变生效。要这样做的话,到controls/monitoring tab,点击停止按钮(它的名字变为了启动),而后点击启动。

Name
    包含一个唯一定义的虚拟服务器名。
Port
    包含监听到来的服务请求的端口。
Protocol
    当前只有tcp被支持。

Add/Edit a Virtual Server
    点击添加按钮来创建一个新的未被定义的虚拟服务器。点击编辑按钮(或是双击这排信息)来定义或修改一个虚拟服务器。点击真实服务器标签来观看或是修改被选好的与真实服务器相关联的虚拟服务器。

区域/按钮 描述

Name
    输入对这个虚拟服务器唯一定义的名字
Application
    点击选择http或是ftp
Port
    输入监听到来的服务请求的端口
Address
    输入服务请求到达的浮动ip地址。这个服务请求到达的地址已和一个全称的域名相关联。
Device
    一个连接lvs路由到公共网络,其浮动ip地址通过ip别名相关联的适配器设备的名字(例如,eht0:1)。如果活动路由失败,在这期间虚拟服务器地址和端口将转到在备份路由上的对应设备上,从而备份路由成为活动路由。

Re-entry Time
    输入一个以恢复的真实服务器被重新加入到路由表中之前的持续正常的秒数(默认是180秒)。

Service timeout
    输入一个以秒为单位的时间,在这段时间里真实服务器必须响应一个重定向请求。如果主机超过了这个时间,它将被宣布为死亡并从集群中移除。
    每个两秒钟在活动路由上运行的nanny进程发送一个心脏跳动检测(必要的ping连接)到每个真实服务器。如果成功了,服务连接(必要的一个telnet连接)将被送到一个特定的服务端口。如果nanny收到从真实服务器返回的任何响应,真实服务器和提供的服务被推定为活着。如果无响应服务超时超过了有效秒数,那么这个真实服务器将被推定为死亡并被一除出路由表。但是nanny通过每两秒钟发送一次心跳检测继续监视着服务器和它提供的服务。如果,在一次成功的ping以后,一个被移出去的服务器保持"re-entery time"时间的存活,它将被重新加入到核心路由表中去。

Load monitoring tool
    选择用于决定在真实服务器上工作量的工具(uptime,ru,或ruptime)。在表二的表格中描述了激活这些工具的一般过程。

Scheduling
    选择从虚拟服务器到真实服务器上的请求的路由选择规则。在表以中描述了选项。

Real Servers
    屏幕显示了每个当前被定义的真实服务器的一排信息。点击这一排信息来选定它。屏幕右边的按钮是应用当前选择的一排。点击删除来移去一个被选择的真实服务器。

区域/按钮 描述

Status
    显示激活或屏蔽。点击屏蔽来关闭一个激活的虚拟服务器。点击激活来启动一个选择的虚拟服务器。改变状态后,你必须要重启pulse守护进程来使改变生效。要这样做的话,到controls/monitoring tab,点击停止按钮(它的名字变为了启动),而后点击启动。

Name
    显示服务器在集群中的名字。

Address
    显示服务器的ip地址。


Add/Edit a Real Server
    点击添加按钮来创建一个新的未被定义的真实服务器。点击编辑按钮(或是双击这排信息)来定义或修改一个真实服务器。

区域/按钮 描述

Name
    输入一个描述名字。

Address
    输入一个才内部网络中的真实服务器的ip地址。

Weight
    输入一个指定这台服务器的处理能力的整数,它与其它真实服务器相关联。

[目录]


例子

例子---建立一个5节点的集群
    这一节将一步步地介绍怎样建立一个由两个lvs路由和三个web/ftp服务器的集群。首先,收集信息然后照着接下来一节说明的一样来建立五个系统。然后是从shell方式对这个例子加以补充(在 the section called Implementing the Example from the Shell中解释)或是启动一个图形界面的配置工具(在 the section called Implementing the Example with Piranha说明) 。

    图三显示了在你装完lvs路由和真实服务器后将出现的网络。所有显示的网络地址是为了阐述得更明白。

Figure 3. Layout of the Example Network

|-------|------------------------------------------|---------| Public network
        |eth0=1.2.3.2                              |eth0=1.2.3.3
        |eth0:1=1.2.3.1 (vs1)                      |
  ------|-----                              -------|-----
  |  active  |                              |   backup  |
  |  router  |                              |   router  |
  |          |                              |           |
  ------|-----                              -------|-----
        |eth1=192.168.1.1                          |eth1=192.168.1.2
        |eth1:1=192.168.1.254 (NAT router)         |
|-------|-|------------------|-----------------|---|----------| Private network
          |eth0=192.168.1.3  |eth0=192.168.1.4 |eth0=192.168.1.5
          |                  |                 |
          |---------|        |---------|       |---------|
          |   rs1   |        |   rs2   |       |   rs3   |
          |_________|        |_________|       |_________|

初步设置

    从网络管理员那获得虚拟服务器的ip地址。在我们的例子中将是1.2.3.1。在lvs集群中的服务请求将被寻址到一个和这个地址相关联的全称域名上。

    定位五个服务器和指定它们的角色:1个主lvs路由,1个备份路由,3个真实服务器。lvs路由必须装上了linux系统,运行red hat 6.1或更高。真实服务器可以是任何平台,运行任何操作系统和web服务器。
3-7步建立lvs路由。

    在每个lvs路由上,装有两个以太网卡,eth0和eth1。在eth0上建立一个公共ip界面和一个内部ip界面。公共界面的设备(eth0)是用于心脏跳动检测的设备。虚拟服务器的地址是这个设备的别名。


Primary node Backup node
eth0 1.2.3.2 1.2.3.3
eth1 192.168.1.1 192.168.1.2

    为路由上连接活动路由到内部网络的设备(eth1)制定一个ip地址(192.168.1.254)。这个浮动ip地址将在路由设备上化名为eth1:1,同时将成为每个真实服务器与活动路由通信的默认路由和内部网络的网关。

在每个lvs路由上:

    激活package forwarding。在系统启动时执行,确信文件/etc/sysconf/newwork包含了这以行forward_ipv4=yes。激活package forwarding而不用重启,登陆为root输入下面命令:

    echo "1" > /proc/sys/net/ipv4/ip_forward

    激活packet defragmenting。在系统启动时便执行,确信文件/etc/sysconf/network包含这一行defrag_piv4=yes。激活package defragmenting而不用重启,登陆为root输入下面的命令:

    echo "1" > /proc/sys/net/ipv4/ip_always_defrag

    伪装内部网络。输入下面这条命令到/etc/rc.d/rc.local:


    ipchains -A forward -j MASQ -s 192.168.1.0/24 -d 0.0.0.0

    决定是否使用类似于rsh或ssh进行lvs集群文件同步。验证你的选择是否安装,这样lvs路由才可登陆到其他的路由上,而不用管理者介入。在这个例子中,我们选择rsh。

    在每个lvs路由上,验证lvs集群软件是否装好。

    8-11步是建立真实服务器。

    在每个真实服务器上,装有一个以太网卡,eth0。照第3步在同一个内部子网络中建立一个ip地址,为每个服务器分配一个砝码,这是一个反映每个服务器处理能力的,与其它服务器相关联在一起的整数。在这个例子中,rs1有两倍于rs2和rs3的处理能力(两个处理器)

rs1 rs2 rs3
eth0 192.168.1.3 192.168.1.4 192.168.1.5
weight 2000 1000 1000

    在每个真实服务器上验证在第四步中注明的地址是它与活动路由通信的默认路由。

    决定用哪个程序(uptime,ruptime,rup)在活动路由上运行,用来监视真实服务器上的工作量。如果选择uptime,每个lvs路由必须在无管理员介入的情况下与每个真实服务器连接,在第6步中使用你选择的类似的工具。得到一般的激活指令请看表二。如果你选择的工具不能被激活(例如,其中一个真实服务器是一个nt系统),使用动态装载信息的计划规则仍将工作,但是用户分配的砝码将静态的被应用而不是动态的基于服务器工作量来调整。

    验证每个真实服务器上安装和配置了http服务。注意:真实服务器必须监听与虚拟服务器对应的同一个端口(如例中的80)。

    验证(例中用telnet或ping)每个真实服务器可到达公共网络上的主机。如果一个在内部网络上的真实服务器不可达到,这预示着服务器与活动路由间的通信失败了。看8和9步。
确定运行参数。对于这里的一些参数,你也许需要测试一定的时间来获得一个恰当的值。在这个例子中,我们用了列表中的值。

取值 参数描述

1050
    主路由和备份路由心跳检测的监听端口。

2
    心跳检测的时间间隔秒数 。

10
    宣布无响应路由死亡并且启动failover的等待秒数。

10
    无响应真实服务器被确定死亡而移出路由表的等待秒数 。

180
    当一个真实服务器被移出路由表后开始又有了响应,在被重新加入到路由表的等待秒秒数。

wlc
    使用weight least-connections负载平衡规则(考虑其动态调整的砝码,分配较多的工作给不忙的服务器)。对选项的描述请看表一。

http
    应用程序。可选项有ftp。
80
    虚拟服务器上的端口数。在虚拟服务器上的监听端口,在真实服务器上也是同样的。

    现在我么准备补充一个例子。你可向下一节中的例子一样在shell下工作。或者你也可象例( the section called Implementing the Example with Piranha.)中的用图形界面的配置工具。

补充一个shell下配置的例子

    用你喜欢的编辑器,打开/etc/lvs.cf文件,设置如下所示的值。 右边的数字是在 the section called Preliminary Setup 中讨论配置的每步的链接。

# Global section
primary = 1.2.3.2                    3
backup =  1.2.3.3                    3
keepalive = 2                        13
deadtime = 10                        13
heartbeat_port = 1050                13
rsh_command = rsh                    6
network = nat
nat_router = 192.168.1.254 eth1:1    4
# Per-virtual-server section
virtual server vs1 {                 8
address = 1.2.3.1                   1
active = 1
load_monitor = ruptime              10
timeout = 10                        13
reentry = 180                       13
port = 80                           13
scheduler = wlc                     13
# Per-real-server section
server rs1 {                        8
  address = 192.168.1.3              8
  active = 1
  weight = 2000                      8
}
server rs2 {                        8
  address = 192.168.1.4              8
  active = 1
  weight = 1000                      8
}
server rs3 {                        8
  address = 192.168.1.5              8
  active = 1
  weight = 1000                      8
}
}

    拷贝编辑好的配置文件到备份路由上。
在主路由上,用这个命令启动pulse守护进程:
              /etc/rc.d/init.d/pulse start

    在备份路由上启动pulse守护进程。
    补充一个用piranha的例子

    在主路由上,登陆为root,打入piranha &启动图形配置工具。
    点击global settings标签输入下面的值:

Field Enter: See Step:
Primary LVS server IP 1.2.3.2 3
NAT Router IP 192.168.1.254 4
NAT Router Device eth1:1 4
Sync tool rsh 6

    点击redundancy标签输入下面的值:

Field Enter: See Step:
Enable Redundant server (select)
Redundant LVS server IP 1.2.3.3 3
Heartbeat interval 2 13
Assume dead after 10 13
Heartbeat port 1050 13

    点击virtual servers标签。在标签上,点击add,然后是edit,输入下面
的值:

Field Enter: See Step:
Name vs1
Application http 13
Port 80 13
Address 1.2.3.1 1
Device eth0:1 3
Re-entry time 180 13
Service timeout 10 13
Load monitoring tool ruptime 10
Scheduling weighted least-connections 13

    点击real servers标签。在标签上,点击add,然后是edit,输入下面的值:

Field Enter: See Step:
Name rs1 8
Address 192.168.1.3 8
Weight 2000 8

    在rs2和rs3上重复第5步。对于他们来说,输入砝码为1000,这表示了rs1的运算能力是rs2和rs3的两倍。

    点击close回到real servers标签。在这里,选择每一个真实服务器点击activate来激活它。

    点击close回到virtual servers标签。在这里,选择每一个虚拟服务器点击activate来激活它。

    点击controls/monitoring标签:

    点击start按钮(名字改变为stop)。

    如果你选中"add pulse daemon to this runlevel"集群将在系统启动时启动,在piranha启动时,上面的按钮通常将被标为stop。

    登陆到备份路游泳这条命令启动pulse:

              /etc/rc.d/init.d/pulse start

    如果你正确的输入了上面所示的值,piranha将在配置文件最后产生一个如下结构的信息,这些将在虚拟服务器和它的真实服务器上使用。

network = nat
nat_router = 192.168.1.254 eth1:1

virtual vs1 {
        address = 1.2.3.1 eth0:1
        active = 1
        scheduler = wlc
        load_monitor = ruptime
        timeout = 5

        server rs1 {
                address = 192.168.1.3
                active = 1
                weight = 2000
        }
        server rs2 {
                address = 192.168.1.4
                active = 1
                weight = 1000
        }
        server rs3 {
                address = 192.168.1.5
                active = 1
                weight = 1000
        }
}

[目录]


简单实例

    通过Linux LVS,实现WWW,Telnet服务的负载平衡。这里实现Telnet集群服务仅为了测试上的方便。

    LVS有三种负载平衡方式,NAT(Network Address Translation),DR(Direct Routing),IP Tunneling。其中,最为常用的是DR方式,因此这里只说明DR(Direct Routing)方式的LVS负载平衡。

网络拓扑结构。

    为测试方便,4台机器处于同一网段内,通过一交换机或者集线器相连。实际的应用中,最好能够将虚拟服务器vs1和真实服务器rs1, rs2置于于不同的网段上,即提高了性能,也加强了整个集群系统的安全性。

服务器的软硬件配置
    首先说明,虽然本文的测试环境中用的是3台相同配置的服务器,但LVS并不要求集群中的服务器规格划一,相反,可以根据服务器的不同配置和负载情况,调整负载分配策略,充分利用集群环境中的每一台服务器。

    这3台服务器中,vs1作为虚拟服务器(即负载平衡服务器),负责将用户的访问请求转发到集群内部的rs1,rs2,然后由rs1,rs2分别处理。

client为客户端测试机器,可以为任意操作系统。

4台服务器的操作系统和网络配置分别为:

vs1: RedHat 6.2, Kernel 2.2.19
vs1: eth0 192.168.0.1
vs1: eth0:101 192.168.0.101

rs1: RedHat 6.2, Kernel 2.2.14
rs1: eth0 192.168.0.3
rs1: dummy0 192.168.0.101

rs2: RedHat 6.2, Kernel 2.2.14
rs2: eth0 192.168.0.4
rs2: dummy0 192.168.0.101

client: Windows 2000
client: eth0 192.168.0.200

其中,192.168.0.101是允许用户访问的IP。

虚拟服务器的集群配置
    大部分的集群配置工作都在虚拟服务器vs1上面,需要下面的几个步骤:

重新编译内核。
    首先,下载最新的Linux内核,版本号为2.2.19,下载地址为:http://www.kernel.org/,解压缩后置于/usr/src/linux目录下。

    其次需要下载LVS的内核补丁,地址为:http://www.linuxvirtualserver.org/software/ipvs-1.0.6-2.2.19.tar.gz。这里注意,如果你用的Linux内核不是2.2.19版本的,请下载相应版本的LVS内核补丁。将ipvs-1.0.6-2.2.19.tar.gz解压缩后置于/usr/src/linux目录下。

然后,对内核打补丁,如下操作:
[root@vs2 /root]# cd /usr/src/linux
[root@vs2 linux]# patch -p1 < ipvs-1.0.6-2.2.19/ipvs-1.0.6-2.2.19.patch

下面就是重新配置和编译Linux的内核。特别注意以下选项:
1 Code maturity level options--->


*           [*]Prompt for development and/or incomplete code/drivers


2 Networking部分:
          [*] Kernel/User netlink socket
           [*] Routing messages
           <*> Netlink device emulation
*          [*] Network firewalls
           [*] Socket Filtering
           <*> Unix domain sockets
*          [*] TCP/IP networking
           [*] IP: multicasting
           [*] IP: advanced router
           [ ] IP: policy routing
           [ ] IP: equal cost multipath
           [ ] IP: use TOS value as routing key
           [ ] IP: verbose route monitoring
           [ ] IP: large routing tables
           [ ] IP: kernel level autoconfiguration
*          [*] IP: firewalling
           [ ] IP: firewall packet netlink device
*          [*] IP: transparent proxy support
*          [*] IP: masquerading
           --- Protocol-specific masquerading support will be built as modules.
*          [*] IP: ICMP masquerading
           --- Protocol-specific masquerading support will be built as modules.
*          [*] IP: masquerading special modules support
*          <M> IP: ipautofw masq support (EXPERIMENTAL)(NEW)
*          <M> IP: ipportfw masq support (EXPERIMENTAL)(NEW)
*          <M> IP: ip fwmark masq-forwarding support (EXPERIMENTAL)(NEW)
*          [*] IP: masquerading virtual server support (EXPERIMENTAL)(NEW)
           [*]  IP Virtual Server debugging (NEW)  <--最好选择此项,以便观察LVS的调试信息
*          (12) IP masquerading VS table size (the Nth power of 2) (NEW)
*          <M> IPVS: round-robin scheduling (NEW)
*          <M> IPVS: weighted round-robin scheduling (NEW)
*          <M> IPVS: least-connection scheduling (NEW)
*          <M> IPVS: weighted least-connection scheduling (NEW)
*          <M> IPVS: locality-based least-connection scheduling (NEW)
*          <M> IPVS: locality-based least-connection with replication scheduling (NEW)
*          [*] IP: optimize as router not host
*          <M> IP: tunneling
           <M> IP: GRE tunnels over IP
           [*] IP: broadcast GRE over IP
           [*] IP: multicast routing
           [*] IP: PIM-SM version 1 support
           [*] IP: PIM-SM version 2 support
*          [*] IP: aliasing support
           [ ] IP: ARP daemon support (EXPERIMENTAL)
*          [*] IP: TCP syncookie support (not enabled per default)
           --- (it is safe to leave these untouched)
           < > IP: Reverse ARP
           [*] IP: Allow large windows (not recommended if <16Mb of memory)
           < > The IPv6 protocol (EXPERIMENTAL)


上面,带*号的为必选项。
    然后就是常规的编译内核过程,不再赘述,请参考编译 Linux 教程

    在这里要注意一点:如果你使用的是RedHat自带的内核或者从RedHat下载的内核版本,已经预先打好了LVS的补丁。这可以通过查看/usr/src/linux/net/目录下有没有几个ipvs开头的文件来判断:如果有,则说明已经打过补丁。

编写LVS配置文件,实例中的配置文件如下: #lvs_dr.conf (C) Joseph Mack mack@ncifcrf.gov
LVS_TYPE=VS_DR
INITIAL_STATE=on
VIP=eth0:101 192.168.0.101 255.255.255.0 192.168.0.0
DIRECTOR_INSIDEIP=eth0 192.168.0.1 192.168.0.0 255.255.255.0 192.168.0.255
SERVICE=t telnet rr rs1:telnet rs2:telnet
SERVICE=t www rr rs1:www rs2:www
SERVER_VIP_DEVICE=dummy0
SERVER_NET_DEVICE=eth0
#----------end lvs_dr.conf------------------------------------

将该文件置于/etc/lvs目录下。

使用LVS的配置脚本产生lvs.conf文件。该配置脚本可以从http://www.linuxvirtualserver.org/Joseph.Mack/configure-lvs_0.8.tar.gz 单独下载,在ipvs-1.0.6-2.2.19.tar.gz包中也有包含。
脚本configure的使用方法:

[root@vs2 lvs]# configure lvs.conf

这样会产生几个配置文件,这里我们只使用其中的rc.lvs_dr文件。

修改/etc/rc.d/init.d/rc.local,增加如下几行:
echo 1 > /proc/sys/net/ipv4/ip_forward
echo 1 > /proc/sys/net/ipv4/ip_always_defrag
# 显示最多调试信息
echo 10 > /proc/sys/net/ipv4/vs/debug_level

配置NFS服务。这一步仅仅是为了方便管理,不是必须的步骤。
假设配置文件lvs.conf文件放在/etc/lvs目录下,则/etc/exports文件的内容为:
/etc/lvs ro(rs1,rs2)

然后使用exportfs命令输出这个目录:
[root@vs2 lvs]# exportfs

如果遇到什么麻烦,可以尝试:
[root@vs2 lvs]# /etc/rc.d/init.d/nfs restart
[root@vs2 lvs]# exportfs

这样,各个real server可以通过NFS获得rc.lvs_dr文件,方便了集群的配置:你每次修改lvs.conf中的配置选项,都可以即可反映在rs1,rs2的相应目录里。

修改/etc/syslogd.conf,增加如下一行: kern.*           /var/log/kernel_log

这样,LVS的一些调试信息就会写入/var/log/kernel_log文件中.

real server的配置
    real server的配置相对简单,主要是是以下几点:
    配置telnet和WWW服务。telnet服务没有需要特别注意的事项,但是对于www服务,需要修改httpd.conf文件,使得apache在虚拟服务器的ip地址上监听,如下所示:
Listen 192.168.0.101:80
    关闭real server上dummy0的arp请求响应能力。这是必须的,具体原因请参见ARP problem in LVS/TUN and LVS/DR(http://www.linuxvirtualserver.org/arp.html)。关闭dummy0的arp响应的方式有多种,比较简单地方法是,修改/etc/rc.d/rc.local文件,增加如下几行: echo 1 > /proc/sys/net/ipv4/conf/all/hidden
ifconfig dummy0 up
ifconfig dummy0 192.168.0.101 netmask 255.255.255.0 broadcast 192.168.0.0 up
echo 1 > /proc/sys/net/ipv4/conf/dummy0/hidden

再次修改/etc/rc.d/rc.local,增加如下一行:(可以和步骤2合并)
echo 1 > /proc/sys/net/ipv4/ip_forward
四 LVS的测试
    好了,经过了上面的配置步骤,现在可以测试LVS了,步骤如下:
分别在vs1,rs1,rs2上运行/etc/lvs/rc.lvs_dr。注意,rs1,rs2上面的/etc/lvs目录是vs2输出的。如果您的NFS配置没有成功,也可以把vs1上的/etc/lvs/rc.lvs_dr复制到rs1,rs2上,然后分别运行。
    确保rs1,rs2上面的apache已经启动并且允许telnet。
    然后从client运行telnet 192.168.0.101,如果登录后看到如下输出就说明集群已经开始工作了:(假设以guest用户身份登录)

[guest@rs1 guest]$-----------说明已经登录到服务器rs1上。

再开启一个telnet窗口,登录后会发现系统提示变为:
[guest@rs2 guest]$-----------说明已经登录到服务器rs2上。

然后在vs2上运行如下命令:
[root@vs2 /root]ipvsadm
运行结果应该为:

IP Virtual Server version 1.0.6 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port             Forward Weight ActiveConn InActConn
TCP  192.168.0.101:telnet rr
-> rs2:telnet                     Route   1      1          0
-> rs1:telnet                     Route   1      1          0
TCP  192.168.0.101:www rr
-> rs2:www                        Route   1      0          0
-> rs1:www                        Route   1      0          0


    至此已经验证telnet的LVS正常。

    然后测试一下WWW是否正常:用你的浏览器查看http://192.168.0.101/是否有什么变化?为了更明确的区别响应来自那个real server,可以在rs1,rs2上面分别放置如下的测试页面(test.html): <HTML>
<BODY>
我是real server #1 or #2
</BODY>
</HTML>

    然后刷新几次页面(http://192.168.0.101/test.html),如果你看到“我是real server #1”和“我是real server #2”交替出现,说明www的LVS系统已经正常工作了。

    但是由于Internet Explore 或者Netscape本身的缓存机制,你也许总是只能看到其中的一个。不过通过ipvsadm还是可以看出,页面请求已经分配到两个real server上了,如下所示:

    IP Virtual Server version 1.0.6 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port             Forward Weight ActiveConn InActConn
TCP  192.168.0.101:telnet rr
-> rs2:telnet                     Route   1      0          0
-> rs1:telnet                     Route   1      0          0
TCP  192.168.0.101:www rr
-> rs2:www                        Route   1      0          5
-> rs1:www                        Route   1      0          4


    或者,可以采用linux的lynx作为测试客户端,效果更好一些。如下运行命令:

[root@client /root]while true; do lynx -dump http://10.64.1.56/test.html; sleep 1; done

    这样,每隔1秒钟“我是realserver #1”和“我是realserver #2”就交替出现一次,清楚地表明响应分别来自两个不同的real server。

五调试技巧
    如果您的运气不好,在配置LVS的过程中也许会遇到一些困难,下面的技巧或许有帮助:

    首先确定网络硬件没有问题,尤其是网线,ping工具就足够了。
    使用netstat查看端口的活动情况。
    使用tcpdump查看数据包的流动情况。
    查看/var/log/kernel_log文件。


[目录]


[ 本文件由良友·收藏家自动生成 ]