争怎路由网/网站教程/内容

COM+ Web 服务:通过复选框路由到 XML Web Services(3) (微软中国)

网站教程2024-07-15 阅读

SOAP 与 DCOM 的局限性和区别


.NET Remoting 的目的之一是提供丰富的分布式环境,使开发人员能够在此环境中对序列化协议(格式化程序)和网络协议(频道)进行组合与匹配。.NET 框架 1.0 版本中的 COM+ Web 服务仅支持一种格式化程序 (SOAP) 和一种频道 (HTTP)。这并不是说其他频道和格式化程序不能使用 ServicedComponents 或 COM+,而是说没有自动配置为这些备用频道和格式化程序提供客户端和服务器端点。
目前已经有用各种语言编写的大量 COM+ 组件。如果可以使用 COM+ Web 服务将所有这些组件启用为 Web 服务,那就太好了。但正如使用 .NET 框架 1.0 版本一样,并非所有现有的 COM 组件都可以使用 COM+ Web 服务。虽然多数具备类型库的现有组件可以正常工作,但是此版本不支持某些组件,例如 Windows 脚本组件 (WSC) 组件。某些复杂的类型库(其接口具有多重继承级别,或依赖于多个类型库)可能无法正常工作。此外,由于类型库转换的局限性,只有类型库中默认的接口才可以作为 Web 服务。
COM+ Web 服务并不是适用于所有现有非托管 COM+ 组件的完整解决方案。现有非托管 COM+ 组件中有一大部分是使用多种编程语言编写而成的,由于不可能测试所有可能的类型库(由支持 COM+ 的各种编译器生成),因此某些非托管 COM+ 组件不能使用 COM+ Web 服务正确发布。COM+ Web 服务的目的之一就是最大程度减少做出这种评估所需的时间和精力。只需将非托管 COM+ 组件发布为 COM+ Web 服务,开发人员就可以迅速判断是否可以将其用作 Web 服务。如果遇到问题,则可以通过若干替代方法来处理现有的非托管组件。这些替代方法包括编写托管或非托管的包装程序,这些包装程序提供的兼容接口可以发布为 Web 服务。多数情况下,编写这样的包装程序的工作量比重新编写整个组件要少得多。这就尽可能减少了将现有的应用程序应用为 XML Web Services 所需的开发和测试工作。
使用非托管(Visual Basic 6.0 或 Visual C++)服务器时,通常越早绑定托管客户端应用程序和 SOAP,越能更好地工作。在某些情况下,如果将生成的元数据用作后期绑定的跨计算机远程代理程序,它可能无法正常工作。
在通过 HTTP 使用 SOAP 格式化程序的情况下,仍然可以使用许多选项(取决于目标部署环境)。COM+ Web 服务为服务器和 CAO 客户端配置生成基于 XML 的远程配置文件。(WKO 激活的 URL 引用已嵌入生成的客户端代理,因此不需要配置文件。)COM+ Web 服务生成直观的功能性配置文件,可由用户自定义以满足任何通过 HTTP 的直接 SOAP 通信所不能满足的需求。可进行自定义的区域包括用户身份验证,如下例所示:
<?xml version="1.0" encoding="utf-8"?><configuration> <system.runtime.remoting><application> <service><wellknown mode="SingleCall" type="SCTrans.SCTransSQL, SCTrans, Version=0.0.0.0, Culture=neutral, PublicKeyToken=9c6052078b454cee" objectUri="SCTrans.SCTransSQL.soap" /><activated type="SCTrans.SCTransSQL, SCTrans" /> </service></application> </system.runtime.remoting> <identity impersonate="true" /></configuration>

上例中添加的突出显示的行可以在激活 COM+ 组件(通过 SOAP 调用)时使用用户的身份标识。(默认情况下,IIS 虚拟根使用标准的 IIS 身份验证。)这样在使用 SOAP 时可以实现 COM+ 的分区(一种 COM+ Windows .NET Server 功能),从而可根据用户的身份标识来实际调用不同的组件。
另一个可以自定义的区域包括客户端激活对象的生存期管理,如下例所示:
<?xml version="1.0" encoding="utf-8"?><configuration> <system.runtime.remoting><application> <service><wellknown mode="SingleCall" type="SCTrans.SCTransSQL, SCTrans, Version=0.0.0.0, Culture=neutral, PublicKeyToken=9c6052078b454cee" objectUri="SCTrans.SCTransSQL.soap" /><activated type="SCTrans.SCTransSQL, SCTrans" /> </service> <lifetime leaseTime="30S" renewOnCallTime="30S" /></application> </system.runtime.remoting></configuration>

在 web.config 文件中添加的突出显示的行,将此 IIS VRoot 中的客户端激活对象的生存期从 6 分钟更改为 30 秒。如果把 wellknown 元素的 SingleCall 属性更改为 Singleton,则激活行为会更改为将所有传入的方法调用都路由到一个组件,而不是原来的对于每个方法调用都激活一个新组件。
.NET Remoting(类似 .NET 框架的其余部分)支持垃圾回收,而不支持引用计数。这意味着在某些情况下,使用 COM+ Web 服务和 DCOM 时,非托管事务 COM+ 组件的行为方式将有所不同。对于通过 WKO 单一调用发布的事务方法,调用 SetComplete 或选择自动完成(通过选择组件方法属性页的“返回此方法时自动停用该对象”复选框)是极其重要的,这是因为组件在进行垃圾回收前不能被释放。使用 DCOM 时,引用计数通常会导致在释放组件时提交或放弃事务,即使此法则被忽略。移动到 COM+ Web 服务环境时,在垃圾回收环境中,事务超时之前这是不能保证的。如果调用 SetComplete 失败或将方法配置为自动完成失败,则证明其自身的间歇无法提交事务,因为组件被作为垃圾回收之前事务已超时。

设计时应注意的事项


在 COM+ Web 服务中,如果选择了 Uses SOAP 复选框(使用组件服务管理工具),将在 IIS 虚拟根上提供两种不同的激活模型:WKO 和 CAO。哪一种模型更好?用户应该使用哪一种呢?
WKO 单一调用激活模型看起来似乎颇为费事。每种方法调用都需要创建一个新组件,完成方法调用后,再将组件发送到内存回收器。但是,如果特别注重性能并且只能使用 WKO 处理业务时,缓冲的 ServicedComponents 或缓冲的非托管 C++ 组件可以大大缓解单一调用激活的过程。使用缓冲的组件时,WKO 激活将从缓冲池中检索对象,完成调用,然后将对象返回到缓冲池。此协议的无状态性质和缓冲池的使用提高了增加扩展性的可能。在不缓冲对象的 WKO 单一调用中,对象的生命期仅限于调用过程。
另一方面,CAO 提供了服务器上单一激活的性能优势,还可以与某个组件的单一实例继续进行通信。通过从客户端向服务器进行多方法调用可以避免激活的缺点。如果服务器组件(ServicedComponent 或非托管 C++ 组件)被缓冲,则将从缓冲池中检索对象,然后在完成方法调用时将对象返回到缓冲池。如果对象没有被缓冲,则对象生命期取决于 web.config 文件中指定的租用生命期,或由组件自身编程设置。生命期是很重要的,因为直到生命期到期时垃圾回收器才会为组件释放内存。在高容量的 CAO 配置中,这会影响开发人员的某些设计决定。

更进一步


如果您只是希望发布或使用应用了 COM+ Web 服务的 Web 服务,您可以到此为止。但是,如果您希望自定义、扩展或简单了解使用的流程,请继续阅读下面的内容。下面的信息不是使用此项功能所必需的,但是如果您希望手动扩展一些功能,这些信息可能会非常有用。COM+ Web 服务是一个简单的包装程序,通过由 .NET Remoting 提供的一套相当丰富的服务,开发人员或管理员可以轻松地对其进行扩展。

服务器 IIS 虚拟根


为使用此功能,并没有在 .NET Remoting 中添加隐藏挂钩,而是编写了 COM+ 代码以进行必要配置,将 COM+ 端点发布为 IIS 虚拟根。在服务器上,这包括向服务器创建物理目录作为虚拟根,以及生成 web.config 文件,以便通过 Remoting 来访问组件。如果是非托管组件(Visual C++ 或 Visual Basic 6.0),也会生成代理元数据,以便 Remoting 可以访问组件。如果 Windows XP 系统目录是 c:\windows,则服务器配置文件和生成的所有元数据都将存储在以下目录树中:
C:\windows\system32\com\SoapVRoots\vrootname当在服务器上发布 SOAP 端点时,以下生成的文件将被放入此目录中:
上述所有文件都是默认生成的。如果您希望删除其中某些功能,只需编辑或删除相应的文件。(但是,如果删除了 web.config 文件,来自 IIS 虚拟根的所有 SOAP 发布都会停止。)
所有生成的元数据都被放入以下目录以及 GAC 中:
C:\windows\system32\com\SoapVRoots\vrootname\bin
在 .NET Remoting 中,bin 目录是一个很特殊的位置。当 HTTP 请求进入 IIS 时,将在此目录中搜索程序集,因此在许多情况下,bin 目录中的发布是唯一必要的步骤。但是,在发布 SOAP 端点时,生成的程序集也被放入 GAC,这是因为虚拟根的程序集解决方案的范围仅限于 bin 目录和 GAC。如果您的代码在同一台计算机上从一个虚拟根向另一个传递引用,除非程序集在 GAC 中,否则目标虚拟根中的引用解决方案将会失败。如果您正在使用所生成的用于非托管 Visual Basic 6.0 或 Visual C++ 组件的元数据,如果没有传递引用,则可以从 GAC 中删除所生成的程序集。
此版本的 .NET 框架需要特别注意的一点是:如果加载了程序集,并且使用 System.Reflection 来访问程序集文件,则文件将在内存中锁定,直到进程结束。动态生成 WSDL 以便生成代理时,将使用反射,因此对于将由客户端进程访问的活动 IIS 虚拟根来说,可以锁定程序集文件。这在运营环境中不会产生问题,但是对于经常更改组件的开发人员来说,应该牢记这一点。
如果您正在使用带有 COM+ Web 服务的 ServicedComponents,此时也需要将程序集放在 GAC 中,除非您最初将程序集放在了 bin 目录中,并且运行了针对该目录中程序集的 regsvcs.exe。如果已经加载 Microsoft .NET 框架 SDK,您可以使用 gacutil.exe 命令行实用程序,将 ServicedComponent 放入 GAC 中;如果安装了内置 .NET 框架的 Windows .NET Server,或者在 Windows XP 计算机上加载了可重新分发的 .NET 框架,可以使用 Microsoft .NET 框架配置用户界面(可从 Administrative Tools 菜单访问),将程序集添加到 GAC 中。
此外,使用 Windows XP 或 Windows .NET Server 时,请确保已安装并配置了 IIS,以提供 ASP.NET 应用程序服务。这些设置对于提供使用 SOAP 所必需的动态内容是必需的。

生成的代理程序集缓存


对于要通过 .NET Remoting 发布为 SOAP 端点的非托管 COM+ 组件,需要生成代理,使非托管组件可用于 .NET 框架。这可以通过编程执行与 tlbimp.exe(用于将非托管 COM+ 类型库转换为代理元数据程序集的 .NET 框架 SDK 工具)相同的步骤来完成。但是,要通过 SOAP 成功激活客户端,客户端和服务器计算机必须共享相同加强名称的签名元数据代理。因此,当生成用于非托管 COM+ 组件的托管代理程序集时,还会生成加强名称关键字,并用于签名代理程序集。
加强名称关键字只能生成一次,并且在非托管 COM+ 组件中没有加强名称关键字的概念。也就是说,如果多次生成代理,则可以创建不同的加强名称关键字。这会为同一非托管 COM+ 组件创建不同的托管标识,要避免这种情况,请将所有为非托管 COM+ 组件生成的代理程序集写入以下 SoapCache 目录中:
C:\windows\system32\com\SoapCache\componentdirectory\proxymetdata.dll
其中 componentdirectory 的格式应为:
ATLTrans.dll_40960_2001_6_27_15_4_16
目录名是根据文件名、文件大小以及上次编译的日期和时间创建的。此方案基于以下假设:如果重新编译非托管 COM+ 组件,则需要生成新的代理。而这又是基于以下假设:如果要对代码做出更改,只能在运营环境中重新编译代码。
由于存在 SoapCache 目录,所以如果在同一计算机的不同虚拟根发布了相同的非托管组件,而不是生成代理程序集,则位于缓存中的非托管组件将被重新使用。这是为了确保组件的加强名称签名(以及由此生成的标识)可以通过虚拟根共享。
如果将 SOAP 启用的非托管 COM+ 组件作为服务器应用程序导出,然后导入到其他服务器,缓存的代理元数据将被一起带走,因此不同的服务器可以共享相同的非托管程序集的同一托管标识。此外,如果用户要生成或编写并签名自己的代理,只需将元数据放入相应的缓存目录中,当服务器上发生 SOAP 发布时就会使用此元数据。这里应用的基本规则是,为避免不必要地扩散用于同一非托管组件的已签名的代理,如果缓存中存在可替代的文件则不生成程序集。

客户端配置


客户端的配置工作也是必需的,最简单的情况(至少从用户的工作量来说)就是本文给出的第一个程序示例:
set SoapObj =GetObject("soap:wsdl=http://www.xmethods.net/sd /TemperatureService.wsdl")WScript.Echo "Fairbanks气温 = " & SoapObj.getTemp("99707")

当处理 WSDL 名字对象时,将会引发以下步骤:
  1. 进行检查,查看是否存在以前为此 URL 生成的代理。如果存在,则再次使用。(跳到步骤 4。)
  2. 如果不存在,则从 URL 检索 WSDL 并生成 C# 代理程序。这实质上与 soapsuds.exe 命令行实用程序(.NET 框架 SDK 所附带的)使用的逻辑相同。
  3. C# 程序被编译为 DLL 并以与 URL 相匹配的名称命名(非法字符转换为文件名中可接受的字符)。
  4. 然后,生成的代理用于通过 .NET Remoting (WKO) 与 WSDL 中指定的远程服务器通信。

这些代理生成并保存在以下文件夹中:
C:\windows\system32\com\SoapAssembly在客户端激活的情况中,客户端代理导入客户端计算机上所必需的已导出的 COM+ 应用程序。此应用程序的导出/导入将从服务器带来客户端激活所必需的已签名的元数据程序集。导入过程还生成配置文件,并放入 SoapAssembly 目录中。通常客户端配置文件采用以下格式:
<configuration> <system.runtime.remoting><application> <client url="http://MyServer/VB6Soap"><activated type="VB6SoapSoapLib.CalcClass, VB6SoapSoapLib"/> </client></application> </system.runtime.remoting></configuration>

COM+ Web 服务在激活组件前读取此配置文件,这样便可以通过修改或替换此配置文件,在客户端计算机上潜在更改激活模型。

一切才刚刚开始


COM+ Web 服务的设计目的是简化结合 .NET Remoting 和 COM+ 服务(Windows XP 和 Windows .NET Server 系列均包含此服务)的过程。它只是为了简化常见的任务,并非包含所有的选项或涵盖用户可能遇到的各种情况。与使用向导在 Visual Studio .NET 中创建程序类似,某些高级的任务留给用户自行解决。为了使用户可以扩展,生成的项目很少被完全删除。此外,XML 类用于编辑生成的配置文件,如果已经存在配置文件,则会在该文件中添加或删除节点,以反映来自组件服务管理工具或 Microsoft COM+ 管理 SDK 的更改。COM+ Web 服务的设计使用户可以轻松地扩展或自定义已经生成的内容。
总之,COM+ Web 服务为现有的 Visual Basic 和 Visual C++ COM+ 组件,以及在 Visual Basic .NET 和 C# 中编写的新托管的 ServicedComponents,提供了一条实现 XML Web Services 和 SOAP 的简单途径

……

相关阅读