2.2.2 DCOM系统核心架构:
上图就是DCOM系统架构图,图中涉及到的一些概念已经在前面的部分中有所介绍。下面就通过阐述隐藏在一个具体的应用例程背后DCOM系统的执行情况来阐明DCOM系统核心架构。
客户端应用程序代码如下:
void main()
{
ISample *pISample;//定义接口指针
//定义pISample ->method的三个参数
Parameter1 para1;
Parameter2 para2;
Parameter3 para3;
Result resl;//定义结果变量
CoInitialize(NULL); // 初始化 COM
CoCreateInstance(CLSID_CSample, NULL, CLSCTX_SERVER,
IID_ISample, (void**) &pISample);//生成所需对象并返回接口指针
resl=pISample ->method(para1, para2,para3);//利用接口指针进行远程调用
CoUninitialize();
}
服务端应用程序代码如下:
void main()
{
hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);//服务端是多线程,因此通过hEvent来协调
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
CClassFactory* pcf = new CClassFactory;
hr = CoRegisterClassObject(CLSID_CSample, pcf,
CLSCTX_SERVER, REGCLS_MULTIPLEUSE , &dwRegister);//注册函数执行后,主线程切换到服务线程
WaitForSingleObject(hEvent, INFINITE); // 等到hEvent被 SetEvent(hEvent)函数设置,此函数在CSample的析构函数 CSample::~CSample ()中被调用。此时,服务器端启动的服务线程切换到主线程
CloseHandle(hEvent);
CoUninitialize();
}
下面分两个过程来阐明隐藏在简单的应用程序背后DCOM系统的复杂的执行过程。
过程一:对象激活过程
当客户端应用进程用CLSID_CSample和IID_ISample调用 COM库中的CoCreateInstance()函数, COM库就把任务委派给客户端的SCM,如果此SCM向当地的注册表咨询后发现所需的对象应位于另外的某台机器(服务端)上,它就向服务端的SCM发送请求,然后服务端的SCM就启动所需的服务(可看成是一个组件),此启动的服务(组件)要和一个object exporter关联起来,而此object exporter要被赋予一个OXID.
启动服务的过程也就是生成所需服务对象(一般意义上来说,一个服务组件可以只有一个对象,也可以有多个对象)的过程,而生成对象则需通过这些对象相应的类厂,大致是服务端的SCM先从注册表中找到从所需的类厂信息,然后载入类厂代码并生成类厂的对象,并将此对象的接口指针注册在一个类对象表(class object table)中(注册过程对应于服务端应用程序代码中的 CoRegisterClassObject(),不过可以从程序中看到,注册后服务端当前进程就处于等待状态,其他的操作都要交给其他进程来完成),如果类对象表中本来就有所需的类厂对象接口指针则不需上述过程,然后服务端的SCM要从类对象表中检索到所需的类厂对象接口指针,调用其 CreateInstance()方法(IClassFactory::CreateInstance )生成所需的服务对象。然后被启动的服务对象的绑定信息和其对应的OXID要在服务端的OXID resolver中注册。
CreateInstance()生成所需的服务对象并通过调用 QueryInterface() 返回了IID_ISample接口指针,服务端就为新产生的服务对象生成了一个对应的object stub(即stub manager),此object stub就先调用CoMarshalInterface函数将接口指针IID_ISample接口指针marshal成标准格式(marshal后的接口指针实际包含的具体内容参看前面部分),接着,CoMarshalInterface又调用IMarshal::GetUnmarshalClass方法来得到一个CLSID,此CLSID将决定在客户端哪一个proxy类被载入客户进程空间并生成相应的 proxy manager.这个CLSID将和marshal后的IID_ISample接口指针一起返回给客户端。 object stub还要通过向注册表咨询为IID_ISample生成相应的interface stub ,并把这个interface stub 和服务对象实际的IID_ISample接口关联起来。
然后服务端的SCM就把CLSID和marshal后的IID_ISample接口指针返回给客户端。在客户端,IClassFactory::CreateInstance(在客户端代码的 CoCreateInstance函数的内部被调用)实际上调用了一个CoUnmarshalInterface函数,此函数从返回的消息包中读出CLSID 并通过调用CoCreateInstance生成了一个object proxy(即proxy manager).此object proxy接着 unmarshal返回的IID_ISample接口指针,通过咨询注册表为IID_ISample生成了其客户端的 interface proxy.并且object proxy从unmarshal后的IID_ISample接口指针中得到所需的OXID以及服务端的OXID resolver的绑定信息,接着调用当地OXID resolver的 IOXIDResolver:ResolveOxid 方法。
客户端的OXID resolver先查看它内部是否缓存了所需的OXID和此OXID对应的服务对象的绑定信息,如果没有,它就向服务端的OXID resolver发请求,然后服务端的OXID resolver就返回给它需要的服务对象的绑定信息。客户端OXID resolver先把此信息缓存,然后将其返回给object proxy.
现在,客户端已经生成了IID_ISample对应的interface proxy,而且object proxy也得到了所需的服务对象的绑定信息。下一步,object proxy就要把这个interface proxy和一个 RPC channel对象联系起来,从此,客户端的interface proxy就可以利用远程服务对象的绑定信息,并通过这个RPC channel对象直接和远程服务端相应的interface stub交互。
最后,在客户端,此interface proxy对象的接口指针将返回给客户端应用进程,即赋给了示例程序的pISample,从此,客户应用进程就可以利用pISample方便地调用远程的方法了。
过程二:远程方法调用过程
客户应用程序中执行了pISample ->method(para1, para2,para3),实际上是触发了interface proxy对象,interface proxy把三个参数marshal成标准格式(NDR格式)后和其他一些信息在一起制成一个RPC消息包,然后调用RPC channel 对象的SendReceive() 方法把这个RPC消息包传送给服务器端的RPC channel 对象。
服务器端的RPC channel 对象通过服务端的 OXID resolver的解析工作找到目标object exporter,向目标object exporter发送一个请求。另外,RPC消息包中含有一个接口指针标示符(即IPID,它是服务端当初返回给客户端的接口指针中含有的),RPC channel 对象就利用这个IPID找到目标 interface stub,并触发了interface stub对象。
interface stub接着就unmarshal参数,并利用RPC消息包中含有的方法序号(method number)调用实际服务对象相应的方法,此方法执行后得到的结果返回给interface stub,interface stub再将此返回结果marshal成NDR格式,再通过RPC channel 对象发送给客户端。客户端再经过类似过程就把结果返回给了应用进程。
以上也就是所举例子中DCOM系统执行的主要过程了,这也就把DCOM系统核心架构及其运行情况基本上阐明。毫无疑问,真正的成熟DCOM系统中还有许多复杂的机制(比如与安全,容错相关的)在本文中并未涉及,但是如果有了DCOM系统的核心架构,学习和研究其他相关的机制也就简单的多了。
3.web services:
3.1 web services简介:
随着分布计算的进一步发展,出现了面向web,开放的,适合于整个internet的分布计算体系,那就是web service.传统的分布组件技术在构建面向web的服务体系时存在着几个缺点:
1。互操作(interoperate)差:几个标准(DCOM,CORBA,RMI)在细节上往往不能一致,比如生命周期管理,是否支持构造函数,以及对继承性实现的程度等。
2。它们要求服务客户端与系统提供的服务本身之间必须进行紧密耦合,即要求一个同类基本结构。这样的系统往往十分脆弱:如果一端的执行机制发生变化,那么另一端便会崩溃。相反,Web服务彼此是松散偶合的。连接中的任何一方均可更改执行机制,却不影响应用程序的正常运行。
3。对DCOM和CORBA/IIOP来说,如果防火墙或代理服务器分隔开了客户和服务器的机器,任何IIOP或DCOM包要通过的可能性是很低的,主要是由于大多数Internet连接技术对HTTP协议的偏爱所致。
因此,虽然利用传统的分布组件技术来构建intranet环境下的服务体系非常合适,但用来构建web服务是很困难的。web service体系应运而生。
什么是web service?一种比较普遍接受的定义是:一种web service是一个应用程序或者组件,它被一个URI(统一资源标示符)标示,它的接口和绑定信息能被一种标准形式来描述,并且它可以经由标准的internet协议与其他的应用软件或组件直接交互。web service的出现导致了一种新概念的产生-- SOA(Service-Oriented Architecture),即面向服务体系结构,而实际上,先前的分布组件体系(DCOM,CORBA,RMI)就是SOA。虽然web service作为面向web ,开放的体系的确在很多方面有了很大创新,但毫无疑问的是,我们还能够很容易的从它的原理中发现很多传统分布计算原理的影子。下面就简单介绍一下web services的主要原理。
有人把web services称做一种internet中间件,但这个新型的中间件不需要完全新型的协议(这点不同与先前的中间件系统),下面就以协议为核心介绍一下web services的结构:
(1)数据格式:web services用XML (Extensible Markup Language)作为数据格式协议,它不仅为web服务提供了统一的数据格式,极大方便了跨平台的互操作性,而且此协议也是web services其他协议的基础。
(2)数据传输:web services主要用SOAP(simple object access protocol,一种XML的扩展协议)来定义web services体系的传输和消息格式。
SOAP的消息格式是XML,可以表示为一个RPC触发消息(在消息体中要以XML的格式包含一个RPC参数和返回值的结构),也可以表示为一个XML文挡。
SOAP定义的绑定信息可以使消息传输于不同的协议之上,但毫无疑问的是,HTTP协议是主要的而且是应用最广泛的协议,也正是web services之所以能面向因特网的重要因素之一。
SOAP 的其他部分内容还有如何将程序数据表示为 XML,以及如何使用 SOAP 进行远程过程调用 (RPC)。这些可选的规范部分用于实现 RPC 形式的应用程序。
(3)服务描述:web services用WSDL(Web Services Description Language )来描述服务,其实WSDL很象DCOM中的IDL,一个WSDL文档描述了web服务的抽象接口,具体绑定信息等,并且可以被编译生成客户端代理,此代理可以通过SOAP来调用web服务。
(4)发现机制:web services通过UDDI(Universal Description, Discovery and Integration)服务来实现服务注册和服务发现机制。此服务类似于DCOM中的名字服务(name service),具体的机制就不在本文阐述了。
从以上几点可以看出,web services的很多机制和先前的分布组件技术原理上还是有很多相似点的,但web services中面向整个internet的统一的数据格式(xml)以及它使用的internet广泛使用的http传输协议都保证了它是真正开放的,面向web的服务体系,这是先前的体系无法比拟的。事实上,web services这个Internet中间件也应当有一套触发机制(应用程序如何与soap和wsdl交互,应用程序如何调用远程服务等),这些都会在不同的开发环境中体现。下面就介绍一个具体的环境微软的.NET Framework.
3.2 .NET Framework简介:
微软的.NET Framework提供了两种不同的分布变成模型:分布对象和Web services,分别对应的就是.NET Remoting和ASP.NET Web services。其中.NET Remoting就和COM+系统的许多原理有很多的相似点,比如它的远程对象,对象激活,代理对象(Proxy Objects),甚至通道(Channels)的概念(对比于COM+系统的RPC Channel),当然这些方面在细节上会有很多不同之处。总的来说,.NET Remoting和COM+最大(实质)的不同还在于.NET Remoting是能够构建开放的,面向internet的系统(尽管不如Web services更适合),要使用 xml,http和soap,当然它仍然提供了RPC方式,并提供工具与com系统兼容(比如用SOAP Toolkit来包装com组件以使com服务能够面向web)。事实上,用.NET Remoting来构建Web services是不太适合的(客观上说可以),而且存在着争议。
ASP.NET Web services提供的是松耦合的体系结构,它基于将SOAP消息影射到方法调用而为Web services提供简单的API,也因为把SOAP消息交换影射到单个的方法调用上,从而提供了非常简单的编程模型。与.NET Remoting相比,ASP.NET Web services提供的是简单的消息传递机制,而.NET Remoting则提供了复杂的多的功能,比如传递对象的引用,多对象触发,回调和Event机制,以及.NET Remoting还支持效率较高的Binary编码方式等。但是,ASP.NET Web services的松耦合结构,更高的互操作性,以及有效的使用WSDL等方面都使它更适合构建异构环境下的,开放的Web services系统,而.NET Remoting则适合构建同构环境下的分布计算系统。
4.结语:
随着分布计算系统经历了传统RPC系统,面向对象RPC系统,以及web service三代,互联网也正越来越明显的改变着我们的生活方式。我们可以说,开放的,面向web的分布计算系统是大势所趋,但我们也不能否认,先前的一些分布计算系统在构建intranet环境下的,同构环境下的系统时仍然具备着优势。另外,分布计算和其他方面(如数据库,人工智能等)的结合也产生了诸如分布式数据库,智能代理等研究方向的出现和发展。随着新一代的基础设施--网格计算的研究和应用在国际上和我国如火如荼地展开,相信分布计算技术(web service技术,甚至是先前的分布组件技术)与网格技术的结合必会是一个研究的热点(实际已经有了web service和网格结合的研究),分布计算技术将会在我们未来的生活中发挥越来越大的作用。
本文地址:http://com.8s8s.com/it/it36836.htm