作者:章文嵩
LVS集群的体系结构
本文主要介绍了LVS集群的体系结构。先给出LVS集群的通用体系结构,并讨论了其的设计原则和相应的特点;最后将LVS集群应用于建立可伸缩的Web、Media、Cache和Mail等网络服务。
1.引言
在过去的十几年中,Internet从几个研究机构相连为信息共享的网络发展成为拥有大量应用和服务的全球性网络,它正成为人们生活中不可缺少的一部分。虽然Internet发展速度很快,但建设和维护大型网络服务依然是一项挑战性的任务,因为系统必须是高性能的、高可靠的,尤其当访问负载不断增长时,系统必须能被扩展来满足不断增长的性能需求。由于缺少建立可伸缩网络服务的框架和设计方法,这意味着只有拥有非常出色工程和管理人才的机构才能建立和维护大型的网络服务。
针对这种情形,本文先给出LVS集群的通用体系结构,并讨论了其的设计原则和相应的特点;最后将LVS集群应用于建立可伸缩的Web、Media、Cache和Mail等网络服务。
2.LVS集群的通用体系结构
LVS集群采用IP负载均衡技术和基于内容请求分发技术。调度器具有很好的吞吐率,将请求均衡地转移到不同的服务器上执行,且调度器自动屏蔽掉服务器的故障,从而将一组服务器构成一个高性能的、高可用的虚拟服务器。整个服务器集群的结构对客户是透明的,而且无需修改客户端和服务器端的程序。
图1:LVS集群的体系结构
为此,在设计时需要考虑系统的透明性、可伸缩性、高可用性和易管理性。一般来说,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服务、或者两者都运行;第三层是共享存