Delphi 6 Web Services初步评估之二(转)
CPU:PIII 550
内存: 256MB
OS: Windows2000 Server + SP2
Web Server:IIS 5.0 + SP3
开发环境:Borland Delphi 6.0 Enterprise
Microsoft Visual Studio 7.0 Beta 2
Microsoft SOAP TOOLKIT 2.0
★ 基本测试过程:
Web Services通过接口方法调用返回值来获取调用结果,因此测试程序通过调用不同类型返回值的接口方法来作为测试方向,分为以下四种:字符串类型返回值,对象类型返回值,对象数组类型返回值和二进制文件返回值。
1、 TEST1(字符串类型返回值方法调用):
首先采用Delphi 6创建一个Web Services工程,Delphi 6通过向导自动生成一个单元,此单元包括了Web Services通讯所需要的各个控件:THTTPSoapDispatcher用于响应基于SOAP的请求,并转交给其它的处理控件;HTTPSoapPascalInvoker用于从THTTPSoapDispatcher接收SOAP消息,并进行分析调用合适的接口方法,最后对接口调用返回结果进行封装(Encode);TWSDLHTMLPublish则是用于公布描述此Web Service接口的WSDL文档。
要为Web Service服务提供接口方法,需要建立一个从IInvokable继承的接口,以及从TInvokable继承的实现此接口的对象。
下面,我们就可以为这个Web Service添加方法了。在这第一个评估测试中,我们需要添加一个字符串类型作为返回值的方法,而且为了尽量准确的测试响应效率,我们希望能传输比较大数据量的字符串。因此创建了一个1024个‘Hello, The World!’组合的字符串作为方法的返回值。
调用结果如图一所示:
(图一)
客户端的调用,顺利取得了服务器端的字符串并显示出来。毕竟服务器对返回值的编码也是文本类型,所以说码耗费的时间并不多,因此整个请求的效率还是可以让人满意的。
当然,正是因为Web Services是基于SOAP的,传递文本自然是“拿手好戏”,但在 我们实际应用中,需要的结果通常来说不是字符串文本,而是别的信息,为了继续
证明Web Services将会带给我们的惊喜,我进行了下一个测试。
2、 TEST2(对象类型返回值方法调用):
在实际应用中我们常常会遇到客户端需要的是从服务器端返回数据库查询结果,在这种情况下,返回的数据可能是各种类型数据的组合,这个测试将会告诉我们如何通过Web Services传递复杂类型资料信息。
传递的复杂类型资料信息可以通过对象进行封装,便于创建于使用中的管理,更重要的是因为Delphi“强迫”我们不得不这样做。在Delphi 6中,如果接口返回值为对象,则此对象必须是从Tremotable类继承下来,并且对客户端能访问的成员变量必须作为属性公布。
针对测试,我创建了一个从Tremotable继承的类TXSPerson,并且公布了六个属性:ID、Name、Age、Gender、Content、Email。因此我可以在客户端通过方法访问这个类实例的这六个成员变量的值。在服务器端,我分别对这六个值进行了赋值,并把类作为方法的返回值。客户端的调用此方法得到TXSPerson类型的对象实例,从而访问它的个属性值。
调用结果如图二所示:
(图二)
从上面的结果可以看出,传输对象的效率就没有传输字符串高了。首先一点,在服务器端程序和客户端程序都必须管理一个类,相对于传递字符串多了这些类的管理开销,自然影响了效率。
从这个测试中,我们可以传递复杂类型的资料了,对于绝大多数的实际应用来说,每次传递已比资料是不够的,我们可能需要的是大量的数据库记录传递。在Web Services中,可以通过使用动态数组来实现,正如下一个测试。
3、 TEST3(对象数组类型返回值方法调用):
当服务器端的一大笔数据库记录需要传递给客户端,每一条记录作为一个对象实例保存,所有的记录用一个对象数组保存,并且以对象数组作为返回值传递到客户端。在这个测试中,我采用了与数据库结合的方式进行测试,以便于去更真实的模拟实际的应用。数据库我采用了Access2000,通过ADO(Microsoft ActiveX Data Objects)进行连接访问,并创建一个动态数组保存查询的各个字段的结果,作为返回值返回到客户端。
调用结果如图三所示:
(图三)
可以看出来,调用仍然非常顺利,客户端获得了期望的资料纪录。但是相对于传输一条记录来说,效率再一次的降低了。应该说来是因为动态数组的原因导致了效率的降低,动态数组是Delphi的一个特征,在C/C++中是没有动态数组的,所以C/C++中数组的内存都是在编译期间分配的。而Delphi中引入了动态数组,这使得只能在运行期间动态的分配内存,从而导致了对动态数组管理所引起的开销,影响效率。
在实际应用中,有时候我们需要传递文件,例如说数据库里面的图片,通过Web Services应该怎么实现呢?作为一种简单的解决办法,我们再一次求助于动态数组。
4、 TEST4(二进制文件返回值方法调用):
在最后一个返回值类型测试中,为了测试Web Services对文件的传输能力,我通过方法结果传递一个JPEG的图片。要使客户端能接收到服务器端的图片,必须采用某种标准返回值类型来组织图片的内容,在测试中使用了动态数组TbyteDnyArray作为返回类型。
服务器端通过TfileStream读取出图片文件的内容,并拷贝到TbyteDnyArray数组中,客户端接收到TbyteDnyArray类型的数组后使用TmemoryStream写回到文件中去,从而完成了文件的传输过程。
调用结果如图四所示:
(图四)
功能的确实现了,但是测试的结果却让人大吃一惊,虽然也猜想到,采用如此“巨大”的动态数组会对效率产生比较大的影响,事实也的的确确也证明了,这种方式实现文件传输的方法是不可行的。
毫无疑问,如此低下的效率正是因为动态数组的开销所导致,对于15KB的图片来说,动态数组将为它的每一个字节生成一个元素,系统的内存管理终究也显得如此“捉襟见肘”。
虽然采用这种方法传递文件我们“失败”了,但是并不是说明没有高效率的传递文件的办法。作为二进制的文件,如果要作为Web Services的返回结果传递在网络上,就必须把二进制文件存放在SOAP信息中,SOAP却是文本文件,所以对于二进制文件作为文本文件再网上传输,完全可以采用已经成熟的协议了,最常用的莫过于MIME(Multipurpose Internet Mail Extension protocol)了。通过Base64编码或其他方式对图片进行编码以后,传递到客户端以后,在进行Base64的解码,效率将会数十倍的提高。但是因为Delphi 6虽然提供了Base64编码解码,但是因为一些不完善的原因使我放弃了对这个方法的测试。