摘要:在分布式多层应用系统中,把应用程序服务器分布在两台或更多的计算机中执行,根据负载平衡的原理,客户端应用程序连接到其中一台计算机的应用程序服务器要求服务。如果客户端应用程序当前连接的应用程序服务器计算机发生故障而无法继续执行,在Agent的帮助下,他可以动态连接到其他机器中的应用程序服务器继续要求新的应用程序服务器为其提供服务。如果运行应用服务器的所有机器都发生故障,仍可以在客户端保存更新的资料,待应用程序服务器的机器恢复功能后,再自动把原先保存的资料更新回远程数据库服务器中,使得分布式多层应用系统的容错性能得到极大的提高。
关键词:负载平衡;分布式;Agent;容错
Realization of Faulttolerant Technique in Distributed Multilayer System
YANG Wanan, CAO Xiedong, FENG Xiao, LI Zhen
(Southwest Petroleum Institute, Chengdu, 610500, China)
Abstract:In distributed multilayer system, we distribute application server in t wo or more computers, according to load balancing, client application can connect wit h one of application servers and ask for services If the application server fai ls and can't keep providing servicesUnder the help of Agent, client applicati on can link to other application server running in other computers and ask for s ervi ces If all the computers running application servers fail, client application c an save updating data, when the computers failed come back to normal states, cli ent application write the saved data back to the remote database automatically, so the fault tolerance of distributed multilayer application system is improved greatly.
Keywords:load balancing; distributed; Agent; fault tolerance
1系统介绍
过去开发软件时,没有考虑充分实现系统的容错功能,有些软件虽然有简单的容错功能,但是以牺牲系统的效率为代价。当前,由于一些计算机硬件存在缺陷,且计算机病毒的蔓延以及其他诸如停电、自然灾害等原因,导致计算机系统陷于瘫痪是非常普遍的现象。在分布式多层体系结构中,应用服务器的稳定对整个系统的稳定起着至关重要的作用,应用程序服务器发生故障,所有的客户端都会瘫痪,而应用服务器端发生故障是最普遍的现象。当客户端应用程序正在请求执行一些重要任务时,决不希望因为应用程序服务器的故障而造成整个多层应用系统无法工作(在其他的很多系统中,因为应用程序服务器无法工作从而导致整个系统瘫痪是不足为奇的),鉴于此,在软件开发中,采用了多级容错技术防止灾难的发生。在分布式多层应用系统中,应用程序服务器运行在多台计算机上,如果正在执行任务的应用程序服务器所在的机器发生故障而无法继续执行时,客户端应用程序探测到错误后,转而自动连接到其他计算机中的应用程序服务器继续要求新的服务器为其提供服务。如果运行应用程序服务器的所有计算机都发生故障,系统可以把数据暂时保存在客户端计算机中,保证客户端当前操作过的资料不会丢失,等到有应用服务器恢复功能时,客户端计算机再通过他自动把资料传回远程数据库服务器中,这样,分布式多层应用系统就具有极高的容错性和稳定性。
开发工具应用程序服务器和客户端采用Borland公司的Delphi 7.0开发;数据库采用微软的数据库SQL Server 2000。
系统结构在分布式多层应用系统中,公共逻辑分发到应用服务器上,分散的客户端可以从异地远程调用,客户端不能直接连接数据库,只能通过应用程序服务器与数据库连接,数据连接逻辑独立出来,做成公共逻辑放在应用程序服务器上,可以充分实现系统的容错功能。系统的结构如图1所示。 (图片) 该体系结构包括3部分:
客户端对应于表示层,他存放在各科室的计算机上,用于实现用户的接口。
应用程序服务器对应于功能层,为各客户端提供公共数据服务,他存放在所有客户端可访问的几台中心计算机上,本文采用的是Delphi中的MIDAS应用程序服务器。
远程数据库服务器用来存储客户端的数据资料及其公共资料和运行Ora cle 8i数据库管理系统。
2系统设计
2.1基本原理
Agent(在本系统中采用了一个中介组件TSimple Object Broker)的功能就是负责维护运行应用程序服务器机器的目录和实现负载平衡。
(1)当正在运行应用服务器的机器发生故障时,Agent把这台机器从目录中删除,当故障机器恢复功能时,又把他的加进目录。
(2)当有许多的客户端应用程序需要连接应用程序服务器时,Agent能够分配不同的客户端应用程序连接到不同机器之中,以便平均每一台应用服务器的负荷。
操纵数据库信息的逻辑是处在AppServer上, AppServer与数据库交互,从而使不同的客户端应用程序能够共享数据,这样,可以使客户端应用程序很“瘦”,因为复杂的业务逻辑全放在了应用服务器上。客户端不能直接操纵数据库,只能通过应用服务器这个中介,通过应用程序服务器,客户端只能操纵规定范围的数据,这样可以有效地防止非法用户操作破坏数据。当客户端要运行应用程序时,首先必须激活任意一台AppServer,再通过App Server连接远程的数据库(必须是数据库授权的用户),才能访问数据库中的数据,这样保证了数据的安全。如果只把应用服务器运行在一台计算机上,那么该系统不能达到容错的最好效果,系统要求至少要2台计算机加载应用程序服务器,如果有多台计算机,可以把同样的AppServer分发到每一台计算机上,这样就能最大限度地实现系统的稳定和容错。
2.2方法和实现
这里以2台计算机分别运行应用程序服务器(AppServer1和AppServer2)为例说明系统如何工作(多于两台计算机的情形是完全一样的)。若只有一个客户端,他可以连接应用服务器1或应用服务器2,当客户端有2个以上时,根据负载平衡的原理,服务器1和 服务器2一定会同时工作。现在,假定只有一个客户端连接到应用服务器1进行数据录入(多个客户端的道理是一样的),如果在客户端调用ApplyUpdate方法保存数据的那一瞬间,应用程序服务器1突然故障了,这会导致ApplyUpdates方法执行失败,而且操作系统的COM/DCO M执行时期函数库将回传一个错误,客户端应用程序必须能够处理这个错误,否则,客户端应用程序更新的数据可能会丢失。如果此时有另外一个应用程序服务器激活并且向Agent注册,或者在Agent中已经有其他的应用程序服务器存在的话,那么客户端应用程序就可以使用这些额外的应用程序服务器来处理更新的数据。问题是怎样让Agent分派另外一个提供相同服务的应用程序服务器给客户端应用程序呢?假设恰好此时在网络中有另外一台机器正在运行应用程序服务器2,AppServer2向Agent注册。此情况如图2所示。
(图片) 图2的情形发生后,客户端应用程序可以遵照图3的步骤和Agent通讯。首先当客户端应用程序察觉AppServer1已经故障后,可以立刻调用Agent的SetConnectedStatus(false)通知Agen t AppServer1发生了故障无法继续使用,然后调用Agent的GetComputerForProgID要求Agent搜寻另外一台提供相同服务的AppServer给客户端应用程序。(图片) 当Agent接受到要求后,他会在他维护的AppServer目录中搜寻一台提供相同服务而且可以工作的应用程序服务器回传给客户端应用程序。如图4所示。(图片) 当客户端应用程序再次从Agent接收到其提供的应用程序服务器后,就可以调用这个新的应 用程序服务器的ApplyUpdates方法要求他更新数据。此时的更新数据一定与故障时的数据一样。在Delphi 的MIDAS 3.0中,客户端应用程序维护了一个Delta属性,这 是一个很特别的属性,他的值就是客户端更新的数据,他独立于任何应用程序服务器之外。客户端应用程序的更新数据都存储在客户端数据集(TClientDataSet)的Delta属 性之中。当客户端应用程序调用客户端数据集(TClientDataSet)的ApplyUpdates方法更新 数据时,把TClientDataSet的Delta值传递给应用程序服务器的数据提供者(TDataSetProv ider)的ApplyUpdats方法。因此一个客户端应用程序的Delta值可以传递给任何提供相同服 务的应用程序服务器,只要这个应用程序服务器和原先的应用程序服务器提供相同的服务,而且都有一个TDataSetProvider组件连接到要更新的数据表即可。
由于应用服务器1和客户端应用程序之间会维护一些内部的信息,但是应用服务器2没有和客户端维护这些信息,那么,客户端应用程序如何能够让应用程序服务器2更新数据呢?即使客户端应用程序和应用程序服务器1中Delphi会维护一个Cursor信息,但这个信息只是为了让应用程序服务器知道客户端应用程序下一次需要的数据封包是哪一个。但是这个Cu rsor信息和更新数据没有关系,数据提供者(TDataSetProvider)完全根据客户端应用程序传递来的Delta值作为更新数据的依据,所以,即使应用程序服务器1故障了,只要客户 端应用程序仍然保存了Delta值,那么客户端应用程序就能通过其他的应用程序服务器为他更新数据。在MIDAS 3.0中,不论是在客户端应用程序存取数据还是更新数据都使用无状态的观念来处理数据,因此,我们建立的是无状态对象,在这种情形下TDataSetProvider不会为客户端应用程序维护Cursor信息,更新数据同样存在问题。(图片) 假设一段时间后,AppServer1又恢复了功能,他可以通知Agent把他的状态恢复成可提供服务的AppServer,当Agent接收到且AppServer1又可以提供服务的消息后,就把他加入到目录中,Agent内部维护的应用服务器目录就恢复成最原始的状态,如图5所示。此时,Agent内部的应用服务器目录中能提供服务的应用服务器有AppServer1和AppServer2。
前面已经讨论了至少一台应用程序服务器处于良好状态的情况。现在,最坏的情况出现了,即当AppServer1故障后,客户端应用程序欲通过AppServer2更新数据时,AppServe r2也故障了,所以,客户端应用程序只好再执行一次SetConnectedStantus(false)方法要求Agent再为他搜寻另外一台能够提供相同服务的应用程序服务器。但是此时所有的应用程序服务器都发生故障,所以Agent无法再找到任何能够提供服务的应用程序服务器,那么客户端应用程序更新的数据怎么办呢?这个时候是不是用户只好关闭客户端应用程序,让更新的数据白白丢失,等到有应用程序服务器恢复运作时再重新录入要更新的数据呢?
当然,如果你的多层应用系统是这样运作而用户也接受的话,那么没有什么问题。但是,我们的目标是让系统提供更好的容错能力,即使所有应用程序服务器故障了,客户端仍然能够保存已经更新的数据而不至于丢失,等到应用程序服务器恢复时再自动把以前要更新的数据更新回后台数据中。
当客户端应用程序无法通过任何的应用程序服务器更新数据时,可以利用客户数据集组件保存客户端数据的功能,把所有数据暂时存储在文件中,Delphi的TClientDataSet提供 了一个SaveToFile方法,当调用这个方法把数据保存于临时文件时,他同时存储客户端记录原始数据和更新数据并且自动合并原始数据和更新数据。当应用程序服务器恢复功能时,可以利用客户数据集组件加载临时文件中的数据,Delphi的TClientDataSet提供LoadFromFile方法加载临时文件中的数据到TClientDataSet之中,再调用Agent的方法(Delphi中就是GetComputerForProgID)和恢复功能的应用程序服务器通信,再调用取得的应用程序服务器的App lyUpdates方法更新数据回数据库中。这个过程对客户端来说是透明的,客户端并不知道上次数据没有成功写到远程数据库中。
3性能评估
由于本系统采用一个智能Agent来管理运行应用程序服务器的机器名目录,当某客户端连接的应用服务器故障时,由Agent自动分配一台计算机给客户端,不会浪费客户端的资源,对客户端来说,这个过程是透明的,又因为这个容错的过程是由应用程序服务器完成的,不会影响客户端的效率。如果运行应用服务器的计算机有多台,同一时间运行应用程序服务器的全部计算机崩溃的概率非常小,系统的稳定性就越好。不足之处就是比其他系统多占用了计算机。但是,对于要求高可靠性的系统来说,这还是一个较合理的选择。分布式多层系统中,软件的容错很难做到。Windows的COM没有提供容错机制。Corba 本身也没有提供容错机制,只是在Corba 3.0中,新增加了2个异步请求模型:回调模型和查询模型,可以采用异步通信机制来实现部分容错。回调模型是一种消息触发机制,不会出现忙等待的现象,但由于回调的消息驱动本质,使得必须采用关键段和同步对象协调客户端,控制非常复杂,必须很好地使用各种同步和互斥机制,客户必须为每个调用提供一个额外的应答处理对象引用。消息服务的查询模型采用传统的控制模块,由于采用轮询的方式,会出现“忙等待”,浪费处理器等系统资源,客户端的处理逻辑和容错逻辑结合,难以修改和维护。对于Corba来说,使用Delphi的MIDAS实现负载平衡和容错更方便。
4结语
本文提供了实现多层应用系统容错的基本原理和实现方法。并且,已经把他应用于后勤保障辅助决策系统和仓储管理中,他的可靠性已经经过评估。首先,在两台计算机运行应用程序服务器,同时运行4个客户端,根据负载平衡的原理,2个应用服务器一定在同时工作,更新数据前,把其中一台计算机的应用程序服务器关闭,所有的客户端通过另一个应用服务器仍然成功地实现了数据的更新。第二步,更新数据前,把所有的应用服务器都关闭,当打开一台应用服务器后,所有的客户端把上一次的更新数据成功地更新回数据库中。下一步工作是进一步提高系统的可靠性和效率。因为当客户端很多时,应用服务器的负荷很重,应用服务器占用大量的系统资源,可能造成应用服务器的不可使用,从而影响相关的客户端。还要进一步改善负载平衡的算法,比如:根据网路的远近,运行应用服务器计算机硬件的性能选择相应的应用服务器。
在这里要注意的是,Delphi 5.0中的TClientDataSet的SaveToFile方法有一个缺陷,即这个方法会通过应用程序服务器取得数据表中的所有数据(改进后只存储客户端已存在的数据),若数据表中存在着大量的记录,就会造成大量的数据在网络上流动,从而使网络瞬间发生堵塞,这样客户端可能出现等待现象,降低了客户端的执行效率,若数据在广域网络中流动,效率进一步降低,还需要进一步改进这个方法。
参考文献
[1]Scotts Valley. CA 950663249. Developer′s Guide.
[2]郭长国,周明辉,贾焰,等.基于Corba消息服务的容错机制[J].计算机学报2002,25(10): 1059-1 064.
[3]韩伟峰.Delphi 6程序设计教程[M].北京:清华大学出版社,2002
[4]李维.Delphi 5.X分布式多层应用系统篇[M].北京:机械工业出版社,2000.
[5]黄超,罗宏宇.Delphi网络应用开发技术与实例[M].北京:清华大学出版社,2002.
[6]Mark Baker.Cluster Computing White Paper[D],University o f Portsmouth, UK.
[7]Rajkumar Buyya.High Performance Cluster Computing Architect ures and Systems[M].北京:电子工业出版社,2001.
作者单位:西南石油学院
11/29/2005
|