深入理解基层知识
—— COM+和MTS, DCOM和MSMQ,
.NET中的序列化
作者:Ken Spencer
开发人员经常要我讲一些关于微软在今后对于以下几个方面的策略:COM+、微软事务服务(MTS)以及它的JIT引擎和对象缓冲(object pooling)、 微软消息队列(MSMQ)和DCOM。还有网站、应用服务器、ASP和组件整合之间的关系到底是什么?既然每个人都嚷着要答案,那么就让我们一次解决掉所有这些问题。首先,我来讲解一下有关COM+和MTS的问题。
使用COM+和MTS
COM+一直以来都很流行,所以如果需要用到COM+或MTS的特点,你可以使用微软.NET组件中的一些相应的技术。我认为:不管组件是否被发布都是解决方案的一部分。.NET中的组件就象COM组件,因为两者都是包含类的DLL ,都能被另一应用程序实例化。它们之间主要的不同之处在于它们的实现方式不同,这也超出了我们所要谈论的范围。
当考虑在一个应用程序中使用什么组件时,有几个可供选择。可以选择使用COM+,也可以选择使用MTS,或者这两者都不用。COM+和MTS都是建立在COM组件上的。这样,如果你要创建一个可以在这两者中都可运行的组件,那么这个组件必须符合COM的二进制标准,而且在它可以使用前,必须先在注册表中进行注册。
.NET框架(同样Visual Basic .NET)是通过COM互操作服务来支持COM+和MTS的。一个基于窗口的应用程序(COM组件或类似COM组件的应用程序)可以叫做一个.NET组件;同样,一个.NET应用程序可以叫做一个COM组件。这两种方式的协同工作能力是很强大的,允许你在应用程序中混合使用它们的技术。
正如我所说,COM+和MTS是建立在COM组件上的。如果你把一个.NET组件(已编译好的)放在一个MTS包中或者一个COM+应用程序中,则这个组件可以被一个.NET应用程序调用,就像直接调用.NET组件而并不是一个MTS或者COM+组件一样。
当使用COM互操作时,一个潜在的问题是会增加系统开销。因为.NET和COM的执行方式是不同的(.NET使用通用语言运行时(Common Language Runtime); COM则不是),而且.NET程序和COM组件的实现方式也是不同的(.NET用的是类型标准,而COM用的是二进制标准)。从一个环境中到另一个环境中进行调用显然会增加不少的系统开销,所以仅当必要时才使用COM互操作。实际上,对于每一次的互用操作都需要执行约20到30条的CPU指令。如果你调用一个基于COM+类的方法,则对于每个这样的调用,都会增加系统开销。
如果你的程序确实必须用到COM+的特征,或者必须用到MTS的特征,而且你确信需要所有的功能,那么就把你的组件放到COM+中,或者放到MTS中。如果你的组件是在单个数据库上执行事务的,并将总是仅在单个数据库上工作,则你没有必要用COM+来实现那些事务,你可以用ADO.NET来实现它们。不过,如果你需要对象缓冲或者对多数据库事务进行支持,那么就使用COM+或MTS。
如果你想实现在MTS或者COM+中的组件,那么你应该去查看.NET框架的MSDN文档,并且查看有关COM+的信息。这些文档会告诉你如何实现组件、如何使用不同的属性来自动化进程。
使用DCOM和MSMQ进行远程通信
你既可以使用.NET Remoting,也可以使用Web Services来取代DCOM。 那么这两种方法有什么区别呢?区别在于你的应用程序以及你是如何在不同的程序段中进行通信的,还有程序的结构是不是有一个位于前端的ASP.NET。而你可以把代码放在程序的多个地方。
第一,你可以把代码放到APS.NET后置代码页中。这使得该页面类似于大多数ASP页面,代码被连到输出页。对于这种情况,此应用程序并不是分布式的,而只是一个双层架构,即:ASP.NET在前端;数据库在后端。
第二,你可以把代码放在一个模块中。如果在你的项目中进行一个模块定义,则一个模块文件就是一个简单的Visual Basic文件。你可以把函数和全局变量放在模块中,以便你可以在程序的任何地方都可以调用它们。这样一来,模块就代替了那些用来存放共用代码的包含文件。
第三,你可以开始把共用代码移植到一个类集合中。具有类定义并且包含一个接口(属性和方法)的文件或者一个文件的区段叫做类,你既可以在ASP.NET项目中创建一个类,使它成为项目中的一部分,也可以单独创建一个项目来实现一个类。后一种方法由于其共用代码较受欢迎,因为共用的代码可以以DLL的形式出现。正如在COM世界中一样,这个DLL可以被许多应用程序共享。
我们假设这个类含有存取数据的代码,是用来执行事务的。为了说明,我采用图1中所示的设计。此图包含了两个.aspx页,调用了一个商务对象来获得一些需要的信息。无论客户(Customer)、产品(Product)或订单(Order)对象都调用了数据库层(Database Layer)对象,数据库层对象再对数据库进行数据存取或信息更新。
图1 订购体系结构
这个应用程序并不需要MSMQ或者.NET Remoting或者Web Services,因为所有的组件都在同一个服务器上。你可以把数据库层组件或者商务组件移到另一个服务器上,但是如同ASP.NET应用程序一样,将所有的组件都放在同一个服务器上的运行速度会更快。这是什么原因呢?因为组件可以像ASP.NET应用程序那样,在同一个程序空间(同一个进程)中运行,这样就免掉了进程间的通信。是访问组件最快速的方法。无论何时调用进程外组件,都会增加系统开销,从而会减慢你的应用程序的运行速度。
如果商务需要,你也可以将其分割,把某些组件放到另外一个服务器上。例如,假设应用程序允许用户输入数据,经处理后再送往数据库,而此时系统又很繁忙,经常在传送数据时出现瓶颈,一种缓解此问题的方法是将MSMQ插入此进程中。一般地,你的应用程序将从用户那里收集到信息,通知用户正在执行,然后将信息送进MSMQ。应用程序能在队列的另一端取出信息,并更新数据库。这种应用程序的性能将会是相当不错的,因为用户无须等待数据库更新。但是这种结构只有在应用程序支持一种无连接操作的架构时,才行得通。
当然,有时当你需要一个排队系统时,也可以使用MSMQ。你可以使用系统和消息命名空间中的一些类,把排队支持加入你的应用程序。这些排队特征也都被集成在Visual Studio.NET中,以便使你可以很方便的从你的应用程序中获得这些特征。
在把数据库层移到数据库服务器中时,你可以或者将数据库组件连同Web service都暴露出来,或者通过.NET Remoting进行连接通信。你可以采用其中任一技术为每一个组件创建一个组件服务器。在这种情况下,选择使用.NET Remoting还是Web Services依需要而定。有一个可行的方法,就是在应用服务器上放置ASP.NET应用程序,而在组件服务器上放置一些应用服务器需要使用的组件。在应用服务器上的应用程序与另一个服务器上的组件之间进行通信有两种方法。
一、你可以只在应用服务器上创建一个Web service,这个Web service要提供能访问不同组件方法的一些方法。这个办法允许应用服务器上的应用程序和组件可以通过Web service访问组件服务器上的组件。此方法的优势是灵活而且简单。这个就是需要明确地创建一个暴露类方法的Web service。
二、应用服务器上的应用程序可以使用.NET Remoting来访问另一个服务器上的组件。此方法十分灵活,而且在很多方面都要优于Web Services。.NET Remoting创建起来很简单。.NET Remoting体系结构被整合在.NET框架中,并且提供了你所需要的在不同系统上的组件的进程间通信的体系结构。这个体系结构提供了一个传输通道,你的应用程序就是通过这个传输通道在网络上进行通信的。
.NET Remoting支持的概念还延伸到很多不同的区域,例如内置的安全性。你也要顾及到在两个组件中传送的数据的安全性。它与Web Services的一个区别就是,它能改变在一个调用两端间传送的数据包类型。Web Services是基于简单对象访问协议(SOAP)工业标准上的。而Remoting可以使用SOAP,也可以使用XML,甚至是二进制格式。对于格式类型,你有选择权。你可以选择二进制格式,因为它比冗长的XML格式更安全、更紧凑。
图2中的体系结构显得稍许复杂了点。图中的局域网中有一台小型机,另有一台Web服务器,通过防火墙与局域网相连接。客户机通过在相互连接的服务器和客户机上的Web Services或者.NET Remoting,与这些不同服务器上的应用程序进行通信。因为大多数Web服务器可以放置Web Services,所以.NET应用程序也可通过那些服务与小型机通信,反之亦然。这样,小型机上的应用程序可以调用.NET服务器上的Web Services。.NET Remoting 也可以同不运行.NET的服务器通信,从而使.NET应用程序能与在不同操作系统上的服务器和应用程序通信。
图2 配备防火墙的局域网
当然,防火墙也是个问题。既然它们一般支持HTTP,而不支持其它协议,那么在Web服务器和其它服务器之间是通过什么协议通信的呢?当然,在这种情况下,Web Services照样可以正常工作,因为传输协议是HTTP。.NET Remoting也支持HTTP作为传输协议。但是出于性能和安全性的考虑,你也可以使用TCP/IP。
.NET中的序列化
由于许多读者都问及.NET中序列化的问题,我将在这里给出一个简要的总看法。一般说来,一个类会提供一个输出数据的serialize方法和一个取得流并把数据送回类的deserialize方法。
在过去,处理序列化是程序员所要做的工作。现在,这项处理序列化的功能被整合在.NET框架中。设想一个销售员,在去见客户前,需要从服务器上下载一批数据到笔记本上。于是他就在本地使用这些数据,事后再重新与服务器程序相连,并把数据返送回去。工作站应用程序能通过Web service连接到服务器再调用一个类方法取得数据。数据经序列化后,结果被传送给客户。然后客户可以通过保存经过序列化的XML流,在本地将结果存储起来。过后,这个销售员可以重新启动应用程序将XML流装载到一个本地的类副本中。随后,应用程序将连续的流送回服务器程序,服务器程序再将它解序列化,更新数据库。
.NET中的其它类也使用序列化。例如,数据集会自动在输入XML流时序列化,输出XML流时解序列化。.NET Remoting和排队也同样使用序列化。