一种分布式计算技术构想
一种分布式计算技术构想 一种分布式计算技术构想
引言
随着计算机技术的发展,越来越多的领域开始使用计算机作为信息处理的工具。加之电子计算机带来的强大的处理能力导致原来很多因需要大量计算而无法实现的技术得以实现。比较典型的例子就是天气预报技术。使用数值计算实现的精确天气预报算法院遭遇计算机技术出现,但由于过于繁重的计算要求,使得天气预报变成了天气历史回顾。
二战期间,ENIAC的出现便直接显示出电子计算机的高速,准确的优点,并直接在二战中为打败法西斯作出贡献。在此前,英国的“巨人”更是为打败德国法西斯发挥了无可比拟的功劳。
在计算机技术发展的几十年间。计算机的应用范围逐步扩大,对计算的精度和速度要求也逐步提高。比如:高精度长期天气预报,模拟核试验,射电天文望远镜对电信号的傅利叶变换,人类基因组测序的编码等诸多方面。
对此类大量计算需求的解决办法一般有两种:一种是研究计算能力很强的超级计算机。另一种解决办法即用多台小型机或个人计算机应用分布式计算技术共同完成一个计算任务。
由于各国的超级计算机研究都是作为军事秘密而进行的,所以对于人民生产生活中需求的大量计算,几乎无可选择的使用了分布式计算技术。
近几年来,分布式计算技术有了一定程度的发展。既有像COM+,DCOM,CORBA一类的远程过程调用技术的支持,也有像Java,C++等跨平台语言的支持。在较近版本的Red hat Linux中,分布式计算库已经作为可选安装组件了。由此可见,在这种优越的环境下,分布式计算技术的成熟已经是呼之欲出了。
而本文所主要谈到的总线式调用实现的分布式计算主要参考了计算机中的指令,地址,数据三总线的工作方式,使方法的调用规范化而更容易实现。
由于分布式计算已经有了一些应用,所以本文所谈及的只是分布式计算实现结构上的一种探索,以供他人在将来设计实际应用时,可以有一种参考或提示。以便让本文直接或间接的为理论的发展作出贡献。
概述
分布式计算技术是一种应用技术,涉及很多已有领域和实际问题。其中,方法的规范化调用是一直困扰我的难题。
在我一次到抚顺市顺华铝轮毂公司实习的过程中,用于工艺流程控制的PLC中应用的总线技术给我很大的启发。一个指令只要指明要工作的器件地址和数据即可实现,而不必在乎此器件在物理上的实际位置。由此,我又联想到现代计算机技术中的指令,地址,数据的三总线结构。而使用这种规范化的调用便可忽略很多细节,而对调用方透明。
由于分布式计算技术涉及多台计算机的联合工作,而工作的计算机软硬件环境也可能不尽相同,网络传输的数据也应适应这些需求。实际实现中可采用TCP/IP,IPX相结合的方式,更灵活而高效的传输数据。
对于分布式计算的定义,我的理解就是让许多台计算机共同完成一个一台计算机无法完成的任务。所以,首先任务要先下到网络中的一台计算机上,再者,任务必须可分,且有必要分,并且让其他计算机共同完成。当然,热衷于虚拟机技术的人则倾向于把一个网络模拟成一台计算能力很强的计算机。而在我的构想中,受知识面的限制,我只把一个任务分解成为函数,所有的调用,任务分配都将转换为函数的调用,并且是规范化的函数调用。
三总线技术中指令,地址,数据三者密不可分。在我的构思中,由于所有的功能都由函数来实现,所以指令系统可以很简单。比如,指令可以用来标志函数的类别,状态等。地址,则是用来区分函数,可供选用的技术有很多。比如:COM中的ClassID; Java中的名字空间;或者是最简单的DLL中函数的index标志。对于数据,由于数据类型的多样性,所以在数据上,只保留几个指向特定类型的指针,再形成链表或树等完成参数,返回值的传递。当然,保留无类型和空类型指针是有必要的。
构想的实现
一,函数调用结构
由于在我的构想中的函数调用必须规范化,即所有的调用都可以使用同一结构类型来描述。所以需要制定一个通用的调用结构类型。对于结构中的可变长度部分则采用指针类型来实现。
以下为C语言实现的调用结构类型示例,实际应用中应添加部分字段以满足要求:
struct standardcall{
functionNo : longint; //用于标志函数的唯一号码
inputinterface:finterface; //函数的参数接口
outputinterface:finterface; //函数的返回值接口
state:fstate; //调用状态,比如失败次数等
};
结构中,functionNo保证了函数实现的唯一性,而调用端和实现端要在编程即保证双方所指的functionNo的同一性。同时,functionNo中要加入识别调用方机器名和进程号的标志,防止不同进程间同名函数的调用混乱。
inputinterface和outputinterface都是finterface类型的字段,分别代表函数的参数和返回值接口。这是一种扩充定义的函数,即函数的返回值可以有多个,且刻有各种不同类型。这样,传统定义中的函数,过程或子程序,面向对象编程中的方法都可以用这样一种广义的函数来表示。但同时,为了实现上的方便,我们作如下约定:
·所有的函数的参数都是值传递,包括其中使用指针进行传递的参数。
·函数执行完成时,只有在把所有的返回数据都传送完毕时,才可以将函数状态置为已完成。且返回数据队列只允许有一个实现返回数据。
这两个约定都是为了在多机,多进程,多线程协同作业下保护数据而制定的,参照了DBMS设计中“锁”的概念。参数的值传递保证了调用方的参数列表永远不变,直至销毁。这样当一个实现超时,死机等失败时,可保证下一个实现使用相同的参数,但是这时standardcall.state中失败次数计数器就需要加1了。
对于finterface类型,这是一个可容纳多种数据类型的,由指针构成的,链表为基础的自定义类型。为了增强跨语言的兼容性,它支持的基本数据类型十分有限。出于Pascal出众的强类型特性,以下给出Pascal实现的finterface类型,仅作示例:
type
nextlinepoint =linepoint;
linepoint=record
value:pointer;
next:nextlinepoint;
end;
finterface = record
booleanline:linepoint;
integerline:linepoint;
singleline:linepoint;
doubleline:linepoint;
othersline:linepoint;
end;
这样就实现了一个支持多种类型,可变参数个数的接口类型,也可以用此类型实现的inputinterface和outputinterface代理了一个函数的全部接口。
二,C/S接口
如果把函数的调用方称为client,函数的实现方称为server,那么调用结构就成为C/S结构。为了实现C/S连接,需要选择接口与传输协议。
值得庆幸的是我们在这个问题上可以有很多选择。比如我们可以使用自定义的网络协议,并可选用TCP,UDP协议,以及IPX等多种连接方式。但我们也可以使用一些现有的远程方法调用(RPC)技术来实现连接,可选用的技术包括DCOM/COM+,CORBA。他们都是成熟而可靠的RPC技术。
在具体实现中,可以支持多种连接方式。并进行高一级的封装。对命令的传递可以使用文本传输协议,接口的传递则需要用流格式来传递。
三,调用管理
现在我们假设有这样一个环境,一个程序运行有多个线程,部分线程在不同的时间确定了计算量较大的过程并向分布式计算的任务管理器提交申请,并等待实现。实现对调用是透明的,隐藏了大量细节,也增加了实现过程的不确定性。如:实现方死机,网络故障等。而且即便是过程申请也应该有优先级的差别。因此,分布式计算中需要进行调用管理。
调用管理要实现以下功能:
·计算资源分配。避免几台计算机同时实现一个调用而造成计算资源的浪费。
·超时管理。对于一个调用,调用方应给出时限,单次时限以及允许重试次数。如果一个实现超出了单次时限,调用管理器就应该放弃此实现而重新注册此调用。并且在超出时限或允许重试次数后向调用方返回实现失败的错误信息。
·优先级管理。在时限剩余相同或相近时,高优先级的调用应被安排在前面。
·为被动的负载均衡保存计算能力信息。
在编程上调用列表可用队列来实现,并由调用管理器维护。调用的排序可由调用的超时剩余时间和优先级共同加权排序。对于无法实现的调用,应保存日志。为客户程序的编写提供调试信息。
四,函数管理
函数管理位于C/S结构中的server方,即实现方。根据计算能力的不同,实现网络中不必使用相同的配置,即各实现机可有不同的函数列表。比如,高计算能力的机器维护的实现函数列表仅用于一些少网络传输而计算量极大的工作。而低计算能力的计算机则负责一些频繁调用而工作量较小的工作。
由于网络中实现机的软硬件环境各不相同。某些工作仅能由一些特殊的机器实现,如打印服务或代理服务器。
实际分布式计算网络开始运行后,client在本机发布一份调用申请列表。server在网段内搜索有调用列表的机器。并分析本机是否可以实现这个调用,即查找函数列表是否可实现。确定可实现后再进行负载均衡的分析。并最终确定是否实现这个调用。
实现函数可使用多种格式,如Windows下的.dll,COM,DCOM, COM+,DDE ; Linux/UNIX下的.so,管道...。对于不同的实现形式,函数管理器要负责加载,初始化,接口传递,释放一个函数的实现。
函数管理器还要实时处理各种实现的错误,并向调用机返回错误信息。
五,值传递
值传递是面向过程编程的一种参数传递形式,也是一种很安全的参数传递方式。有时为了实现值传递甚至要强加const关键字。而在我的设想中,值传递泛指参数与返回值在不同的机器间的传输。
在需要进行值传递时,首先得到指向finterface类型的指针,并用递归算法找到要传递的每一个变量。并在网络中用文本或流的格式来传递。最终在实现机上重现调用方的参数列表。如果调用和实现具有相同的数据高低位标准,甚至可以直接以流格式传送finterface型值。
我的构想是为了高安全性才只使用真正意义上的值传递。如果实际需要地址传递,如:对象调用或变量太大。可考虑用finterface模拟实现,比如对于大型变量使用分步传递。
六,负载均衡
为了保证网络中计算资源的高效利用,有必要进行负载均衡。负载均衡可选用:client主动均衡,server主动均衡和专用均衡服务器等几种方法。
几种均衡的方法都要遍历网络,而server主动均衡可根据自身计算能力评价是否实现。可实现更高效率的负载分配。对于client主动均衡则有可能出现几个client争抢一台高计算能力server的现象。所以不建议经常使用。
对于一个负载均衡任务,需要了解client需求和server实现能力。client需求由于编程变量的不确定性,一般只能由程序员估算。而server实现能力参数则可用一个负载能力函数来评价。负载能力函数可以选用一个固定计算次数的小型计算函数,并且测量实现时间来评价。
负载均衡的最高目标是所有的计算机都达到相同的使用率,但由于网络传输速度远低于本机内的速度。所以当一个机器使用率低于一定的百分比时,应优先使用本机实现。实现方也应通过负载能力函数的返回值来确定是否执行实现。另一个必须考虑的问题是机器的使用率。一台使用率低于5%的机器当然应该优先被使用。
综上,负载均衡可以使用如上三种方式的联合使用。当一个调用申请产生后,如本机有实现,且使用率不高,负载能力也较高时,应尽量在本机实现。如决定使用其他实现,调用机线搜索网络内的使用率低于10%的负载能力函数值最高的实现并连接,处理。如果网络内未找到,则等待其他实现的主动连接。而一个实现如果使用率低于50%且达到负载能力下限,则自动搜索网络内的调用并连接实现。而对于找不到实现的调用申请和略忙的实现则有负载均衡服务器自动收集,分配。
七,C/S ?
由上面的介绍大家可以发现,在我的构想中对一个调用-实现而言是C/S结构,而对于整个网络而言则不再区分C/S。一个实现也可以产生调用。
编程技术中的很多算法,如递归等需要大量的调用其它过程。因而这种结构很适合于实现多数算法,也十分有利于负载均衡。
一个问题可以输入网络中的任一台计算机,并由他进行初步计算后产生调用,并最终由整个网络实现完成。在输入机上返回最终运算结果。
八,机群计算的应用
另一类类似于分布式计算的应用是机群计算,这不太适合于我构想中结构的实现。比如:web服务器,DBMS等。这些计算要求有一个总的负载均衡服务器,对于网络外的每一个连接请求分配一台能力有余的计算机进行处理。但构想中的很多解决办法也可以应用在这种应用中,如:总线式调用,负载均衡等。
总结
总线式调用实现的分布式计算技术构想就是如上介绍的这样一种技术。他的工作过程是:产生调用申请-调用申请的规范化-发布申请-连接实现机-实现-返回结果。这个过程反复产生并由负载管理器全程管理。
总线式调用实现的分布式计算技术构想适合于网络内进行大规模的科学运算。缺点是,需要程序员了解运行原理,程序员要估算负载。负载均衡虽然得到了初略的解决,但不够细致,如:只由一个函数实现的大量循环是无法再去均衡的。调用的分配最小单位也只能到函数一级。
虽然总线式调用实现的分布式计算技术构想存在很多缺点和未解决的问题,但不失为一种完整的分布式计算解决方案。希望能给各位工程技术前辈提供一个可参考的选择。
后记
这是我升入大学后的第8篇介绍自己构想的文章。也是篇幅最大的一篇。文章的后三分之二由于时间的改变,是在一天内完成的。虽然有结构图的指导,但错误漏洞尚多,思路也很混乱,望海涵。
我在去年年末加入了赵福来老师的科研项目,帮助赵老师做Linux机群计算方面的研究。几个月来由于我的Linux操作较差,一直没能有什么有实际意义的帮助。这篇论文便是几个月来的见识与灵感的结晶,希望能给赵老师一点帮助。
由于几个月为时太短,且我没接触到任何相关的书籍,文中所有技术都几乎是在没有任何参考资料下完成的。并无任何抄袭,希望老师相信我。
最后。感谢赵福来老师,让我在他的实验室学到了很多知识。同时感谢石宝英老师和谢世满老师对于我编程问题的指导。
献给所有关心,爱护我的人。
刘晓明
河北理工学院2002级计算机2班
地址:唐山市卫国北路热力学苑A442号
电话:3860107
2004-8-27