原文引自:
http://www.microsoft.com/china/msdn/library/architecture/architecture/architecturetopic/SCArchDeGuide/Chapter1Introduction.mspx
第 3 章 — 建立连接
发布日期: 8/20/2004 | 更新日期: 8/20/2004
本页内容
按照定义,智能客户端需要连接到其他资源并与这些资源进行通讯,并且构成分布式应用程序的一部分。这些资源可以是客户端进程或组件,也可以是网络资源,如 Web 服务。
本章分析智能客户端与其他资源之间的通讯的性质。本章将考察可用来连接和使用其他进程、组件或远程服务中的资源的不同技术,并且讨论如何对它们进行取舍。最后,本章将分析如何最好地设计您的智能客户端以连接到资源。
松耦合系统和紧耦合系统
客户端应用程序可以用不同的方式连接和使用其他进程(包括本地进程和网络进程)中的组件和服务。按照服务与客户端之间存在多少耦合性对不同的方法进行分类是很有用的。
耦合性是指组件(在分布式系统中)互相依赖的程度。客户端与它们同其进行通讯的服务之间耦合的性质可能影响智能客户端设计的许多方面,包括互操作性、脱机功能、网络通讯性能、部署以及维护注意事项。
紧耦合系统通常提供直接的对象到对象通讯,并且客户端上的对象对远程对象具有详细的了解。这种紧耦合性可以防止对客户端或服务器进行单独更新。因为紧耦合系统涉及直接的对象到对象通讯,所以对象通常比在松耦合系统中更为频繁地交互,这样,如果两个对象位于不同的计算机上并且由网络连接分隔,则可能导致性能和延迟问题。
松耦合系统通常是基于消息的系统,此时客户端和远程服务并不知道对方是如何实现的。客户端和服务之间的通讯由消息的架构支配。只要消息符合协商的架构,则客户端或服务的实现就可以根据需要进行更改,而不必担心会破坏对方。
松耦合通讯机制提供了紧耦合机制所没有的许多优点,并且它们有助于降低客户端和远程服务之间的依赖性。但是,紧耦合性通常可以提供性能好处,便于在客户端和服务之间进行更为紧密的集成(这在存在安全性和事务处理要求时,可能是必需的)。
所有与远程服务或组件通讯的分布式客户端都具有某种程度的耦合性。您需要了解各种松耦合方法和紧耦合方法具有的不同特征,以便为您的应用程序选择合适程度的耦合性。
通讯选项
当您设计智能客户端应用程序时,您可以从多种将其连接到其他资源的方法中进行选择,这些方法包括:
• |
Microsoft_ .NET Enterprise Services。 |
• |
Microsoft .NET remoting。 |
• |
Microsoft Windows_ 消息队列(也称为 MSMQ)。 |
• |
Web 服务。 |
.NET Enterprise Services
您可以使用 .NET Enterprise Services 提供对托管代码组件和应用程序的 COM+ 服务基础结构的访问。.NET 组件依赖 COM+ 为其提供许多组件服务,如:
• |
Transaction support. |
• |
Role-based security. |
• |
Loosely coupled events. |
• |
Object pooling. |
• |
Queued components. |
• |
Just-in-time activation. |
使用 COM+ 服务的 .NET 组件称为服务组件。因为您的服务组件以 COM+应用程序为宿主,所以它们必须可供该应用程序访问。这就为服务组件带来了一些注册和配置要求:
• |
程序集必须从 System.EnterpriseServices 命名空间中的 ServicedComponent 类派生。 |
• |
程序集必须是强命名的。 |
• |
程序集必须在 Microsoft Windows 注册表中注册。 |
• |
必须将程序集的类型库定义注册和安装到特定的 COM+应用程序中。 |
如果程序集包含被配置为进程外应用程序的服务组件,则应该将相应的程序集放到全局程序集缓存中。如果程序集包含被配置为进程内库的服务组件,则不必将其放到全局程序集缓存中,除非它们位于与应用程序不同的目录中。如果您以这种方式部署同一版本服务组件的多个副本,则 COM+ 目录包含该组件的所有实例的全局配置;您无法逐个副本地对它们进行配置。
下面的代码示例显示了一个需要事务的组件,并且提供了一种在该事务内向数据库中写入数据的方法。
using System.EnterpriseServices;
[Transaction( TransactionOption.Required )]
public class CustomerAccount : ServicedComponent
{
[AutoComplete]
public bool UpdateCustomerName( int customerID, string customerName )
{
// Updates the database, no need to call SetComplete.
// Calls SetComplete automatically if no exception is thrown.
}
}
服务组件通常可以在首次运行时动态注册。这种类型的注册称为惰性注册。当托管代码应用程序首次尝试创建服务组件的实例时,公共语言运行库 (CLR) 将注册程序集和类型库,并且配置 COM+ 目录。对于特定版本的程序集,注册只发生一次。通过惰性注册,您可以使用 Xcopy 部署来部署服务组件,并且无须显式注册服务组件就可以在开发周期中使用它们。
惰性注册是注册服务组件的最容易的方法,但它只在运行这些服务组件的进程具有管理特权时才有效。而且,任何被标记为 COM+ 服务器应用程序的程序集都要求显式注册;对于调用托管服务组件的非托管客户端而言,动态注册不起作用。如果使用服务组件的进程不具有动态注册所需的特权,则您需要使用 .NET 框架随附的 Regsvcs.exe 工具显式注册包含该服务组件的程序集。
惰性注册和 Regsvcs.exe 都需要客户计算机上的管理权限,因此如果您的应用程序包含服务组件,则无法使用非接触式部署来部署它。有关详细信息,请参阅第 7 章:部署和更新智能客户端。
可以用多种不同的方式托管和访问服务组件。它们可以由 ASP.NET应用程序托管并通过 HTTP 访问,或者可以通过 SOAP 或 DCOM(默认设置)访问它们。但是,如果 COM+ 服务需要与调用一起流动(例如,如果您需要用户的标识或分布式事务从您的应用程序流动到服务组件),则 DCOM 是唯一可行的解决方案。
注 如果您使用 DCOM 与 COM+ 应用程序通讯,则需要将 interop 程序集部署到客户计算机,就像您部署传统 COM 组件那样。
Enterprise Services 具有许多您可以在智能客户端应用程序中使用的强大组件功能。然而,您通常只应该在单个进程内、在单台客户计算机上或者在服务器上的服务边界内使用这些功能。由于 Enterprise Services 所具有的紧耦合性质,它们通常不是在智能客户端应用程序和位于远程系统上的服务之间进行通讯的最佳选择。如果您的智能客户端应用程序需要在本地使用 COM+ 服务(例如,事务支持、对象池或基于角色的安全性),请使用 Enterprise Services。
有关 Enterprise Services 的详细信息,请参阅 .NET Framework Developer's Guide 中的“Writing Serviced Components”,网址为:http://msdn.microsoft.com/library/en-us/cpguide/html/cpconwritingservicedcomponents.asp?frame=true。
.NET remoting
.NET remoting 提供了灵活且可扩展的远程过程调用 (RPC) 机制,.NET 组件可以通过该机制进行通讯。通过 .NET remoting,您可以使用多种通讯协议(如 HTTP 或 TCP)、数据编码选项(包括 XML、SOAP 和二进制编码)和各种对象激活模型。它可以提供在对象之间进行通讯的快速而有效的手段。
.NET remoting 使您可以通过使用显示为远程对象的代理对象,像调用本地对象一样调用远程对象。.NET remoting 基础结构通过属性和方法调用处理客户端代码和远程对象之间的交互,在此期间对在它们之间传递的数据进行编码,并且管理远程目标对象的创建和删除。
.NET remoting 基础结构要求客户端具有关于远程对象的公共方法和属性的详细知识,以便提供客户端代理。确保客户端具有该知识的一种方法是向客户端分发该远程对象的完整实现。然而,更为有效的方法是将公共方法和属性包括到接口定义中,并且将这些接口编译为它们自己的程序集。然后,客户端可以使用接口程序集来提供适当的代理,而远程对象可以使用接口程序集来实现必要的功能。而且,使用该技术时,您无须将完整的远程对象重新分发到客户端,就能够更新这些远程对象的实现。
您可以用多种方法来管理远程对象的生存期。可以按照需要创建对象以满足单个请求,或者可以通过使用租用机制更细致地控制它们的生存期 — 此时,客户端维护对远程对象的租用,并且只要客户端希望使用远程对象,就必须使远程对象保持活动。.NET remoting 还可以保证对于所有客户端,只存在一个对象实例。您可以根据您对状态管理和可伸缩性的要求,选择应用程序的生存期。
.NET remoting 的可扩展基础结构使您可以创建自定义信道和接收器。自定义信道使您可以定义通过网络传输数据的方式。例如,您可以定义自定义信道以实现自定义有线协议。自定义接收器使您可以截获在对象之间发送的数据,并对其执行操作。例如,您可以定义自定义接收器在传输前后对数据进行加密或压缩。
.NET remoting 具有用于在对象之间进行通讯的强大且可扩展的机制。但是,由于它的紧耦合性质,在某些情形下它可能并不适合。.NET remoting 在客户端和服务器都需要 .NET 实现的对象;因此,对于要求在不同环境之间具有互操作性的情形,它并不适合。对于在客户端和服务器之间采用紧耦合 RPC 风格交互并不适当的情形,.NET remoting 也是不适合的。默认情况下,.NET remoting 不会提供任何内置的加密机制或用于在对象之间传递用户标识或事务的机制。对于这些情形,应该使用 Enterprise Services。
但是,对于在客户计算机上或服务边界内不同进程中的对象之间的通讯而言,以及对于不同应用程序域中的对象而言,.NET remoting 都是一种很好的选择。
有关使用 .NET remoting 的详细信息,请参阅“An Introduction to Microsoft .NET remoting Framework”,网址为:http://msdn.microsoft.com/library/en-us/dndotnet/html/introremoting.asp?frame=true。
有关对 Web 服务和远程处理进行取舍的信息,请参阅“ASP.NET Web Services or Remoting: How to Choose”,网址为:http://msdn.microsoft.com/library/en-us/dnbda/html/bdadotnetarch16.asp?frame=true。
消息队列
借助于 Microsoft Windows 消息队列,您可以很容易地通过发送和接收消息,快速而可靠地与应用程序通讯。消息处理为您提供了有保证的消息传递以及执行许多业务过程的可靠方式。消息队列提供了一种您可以在智能客户端应用程序内使用的松耦合通讯机制。消息队列具有下列功能:
• |
有保证的消息传递。消息队列通过将消息存储在队列中直到其可以传递,保证了即使远程系统失败或不存在,消息也能够传递。因此,与组件之间的直接调用相比,消息受失败的影响的程度要小得多。 |
• |
消息优先级化。更为紧急或重要的消息可以在不太重要的消息之前收到,从而有助于保证为关键应用程序提供足够的响应时间。
注 您只能为非事务性消息设置消息优先级。 |
• |
脱机功能。如果消息因为客户端脱机而无法传递,则会将它们存储在待发队列中,并且在客户端重新联机时自动传递它们。用户在无法访问目标队列时可以继续执行操作。同时,其他操作可以像消息已被处理一样继续执行,因为当网络连接还原时可以保证传递消息。 |
• |
事务性消息处理。您将消息作为事务的一部分发送。这样,您就可以发送多个相关消息,或者将您的应用程序设计为参与分布式事务,并且确保所有消息都按顺序传递并且只传递一次。如果事务内发生任何错误,则整个事务都将被取消,并且不会发送任何消息。 |
• |
安全性。MessageQueue 组件所基于的消息队列技术使用 Windows 安全性来确保访问控制的安全、提供审核以及对您的组件发送和接收的消息进行加密和身份验证。可以在网络上对消息队列消息进行加密,以使其不会被包嗅探器截获。您还可以禁止队列接收未加密的消息。 |
使用消息队列的应用程序可以通过使用 System.Messaging 命名空间中的类来发送消息以及从队列中读取消息。Message 类用于封装要发送到队列的消息,而 MessageQueue 类提供了对特定队列及其属性的访问。
您需要在任何使用消息队列的计算机上安装和配置它。Windows 桌面操作系统和 Microsoft Windows CE .NET 都可以使用消息队列,从而使您可以在移动设备(如 Pocket PC 设备)上使用它。
要与提供基于消息的访问的服务交互,消息队列是一种很好的选择。您可以使用消息队列与其他装有消息队列的系统通讯。尽管您可以使用连接工具包与其他消息处理系统(如 IBM 的 MQSeries)通讯,但与其他系统之间的互操作性是有限的。
有关使用消息队列的详细信息,请参阅 Microsoft Platform SDK 文档资料中的“Message Queuing (MSMQ)”,网址为:http://msdn.microsoft.com/library/en-us/msmq/msmq_overview_4ilh.asp?frame=true。
有关 MSMQ-MQSeries 跨接编程的信息,请参阅“Programming Considerations Using MSMQ-MQSeries Bridge Extensions”,网址为:http://msdn.microsoft.com/library/en-us/his/htm/_sna_programming_considerations_using_msmq_mqseries_bridge_extensions_appl.asp。
Web 服务
Web 服务是具有下列功能的应用程序组件:
• |
通过标准的 Web 服务协议向其他 Web 服务和应用程序公开有用的功能。 |
• |
提供其接口的详细说明,使您可以生成与它通讯的客户端应用程序。说明是在名为 Web 服务描述语言 (WSDL) 文档的 XML 文档中提供的。 |
• |
通过使用 XML 架构说明其消息。 |
Web 服务的基于 SOAP 的 XML 消息可以具有显式(结构化和类型化)部分或宽松定义部分(使用任意 XML)。这意味着 Web 服务既可以是松耦合的,也可以是紧耦合的,并且可用于实现基于消息或 RPC 风格的系统,具体取决于环境的准确性要求。
您可以使用 Web 服务在异类环境中的组织内部以及组织之间生成模块化的应用程序。这些应用程序可以与种类繁多的实现、平台和设备互操作。任何能够通过 HTTP 发送 XML 的系统都可以使用 Web 服务。因为 Web 服务是基于标准的,所以用不同语言编写以及位于不同平台上的系统可以相互使用对方的服务。这通常被称为面向服务的体系结构。
用于 Web 服务的主要标准是 HTTP、SOAP、UDDI 和 WSDL。Web 服务与传输协议无关。但是,HTTP 是最常见的用于传输 SOAP 消息的机制。因此,Web 服务非常适合于横跨网络和企业防火墙的应用程序,如需要通过 Internet 与服务通讯的智能客户端。
许多 Web 服务标准正在出现,以扩展 Web 服务的功能。Microsoft Web Services Enhancements (WSE) 2.0 支持正在出现的 Web 服务标准,如 WS-Security、WS-SecureConversation、WS-Trust、WS-Policy、WS-Addressing、WS-Referrals、WS-Attachments 和 Direct Internet Message Encapsulation (DIME)。WSE 提供了编程模型,以实现它所支持的各种规范。有关详细信息,请参阅“Web Service Enhancements (WSE)”,网址为:http://msdn.microsoft.com/webservices/building/wse/default.aspx。
有关 SOAP 的详细信息,请参阅“Understanding SOAP”,网址为:http://msdn.microsoft.com/library/en-us/dnsoap/html/understandsoap.asp。
有关 WS-Security 的详细信息,请参阅“Web Services Security Specifications Index Page”,网址为:http://msdn.microsoft.com/library/en-us/dnglobspec/html/wssecurspecindex.asp。
Web 服务通讯可以是粗粒度的、独立的和无状态的。但是,与其他形式的通讯相比,Web 服务通常是非常详细的。
Web 服务是生成大多数智能客户端应用程序的最佳方法。高度的互操作性使 Web 服务能够与各种各样的应用程序通讯。使用广泛采用的标准意味着它们通常只须进行最低限度的额外配置(与要求打开专用端口的其他技术比较),就可以通过网络基础结构和防火墙,Microsoft Visual Studio® 开发系统中对于 Web 服务的强大支持意味着您可以在单个开发环境中使用它们。
在性能极高的应用程序中,Web 服务可能并不适当,因为它们太详细,并且与其他消息处理技术(如 .NET remoting 和消息队列)相比,它们包含相当繁重的消息有效负载。
有关使用和生成 Web 服务的详细信息,请参阅 .NET Framework Developer's Guide 中的“XML Web Services Created Using ASP.NET and XML Web Service Clients”,网址为:http://msdn.microsoft.com/library/en-us/cpguide/html/cpconaspnetbuildingwebservicesaspnetwebserviceclients.asp?frame=true。
选择通讯选项
不同的通讯选项适用于不同的场合。表 3.1 概括了用于建立连接的不同选项。
表 3.1 智能客户端选项
Enterprise Services |
提供对 COM+ 服务的访问
使标识能够与调用一起流动 |
要求在客户端安装服务组件
仅适合于同一进程或计算机 |
.NET remoting |
快速
可插接
支持自定义协议 |
要求 .NET 框架运行
专用
无法在不打开 RPC 端口的情况下通过防火墙
无安全性基础结构 |
Message Queuing |
对于与消息处理系统通讯很有用
安全
有保证的消息传递 |
要求在客户端上配置消息队列
不能容易地与其他系统集成 |
Web services |
支持集成
可扩展
强大的行业支持
定义明确的标准
供应商/语言无关
安全 |
详细
性能比 .NET remoting 低 |
如表 3.1 所示,在某些情况下,Enterprise Services、NET remoting 和消息队列可能是用于在智能客户端和连接的资源之间进行通讯的适当技术。但是,在大多数情况下,Web 服务是用于将智能客户端应用程序连接到服务的最佳机制。
围绕 Web 服务通讯生成的体系结构可以在连接的环境和脱机环境中很好地工作,并且支持能够自我描述且独立的粗粒度、无状态消息。对于 Internet 协议的依赖使得客户端能够广泛分发给 Internet 上的每个人。
设计连接的智能客户端应用程序
当您设计您的智能客户端时,您应该考虑一些建议,包括:
• |
使用粗粒度的、封装的消息。 |
• |
避免分布式 ACID 事务。 |
• |
避免在网络中发送数据集。 |
• |
将大型数据集分解。 |
• |
将您的 Web 服务和程序集版本化。 |
使用粗粒度的、封装的消息
分布式网络调用是代价高昂的操作。您不应该使用与设计本地接口相同的细粒度方法来设计您的外部接口。要避免消息之间存在消息依赖性,比较好的做法是将接口方法生成为独立函数。这样做可以使您不必编写复杂的跟踪协调代码来处理依赖于其他消息成功完成的消息的失败。
避免分布式 ACID 事务
分布式 ACID(原子、一致、独立、持久)事务是资源密集型的,伴随大量网络通信以及挂起本地事务上的大量相互依赖的系统锁。如果您的智能客户端或服务正在等待答复,并且在收到该答复之前无法继续工作,则分布式 ACID 事务可能阻止业务过程。
如果您的智能客户端可能不加警告就切换到脱机模式,则分布式 ACID 事务的问题将会恶化。在此情况下,客户端可能对数据加锁,并且在可以在服务器释放该锁之前进入脱机模式。
如果您无法通过将接口分解为单独的不连续消息来避免消息依赖性,则您具有许多处理事务的选项,并且还可以避免分布式 ACID 事务:
• |
将紧耦合消息提交给服务器,并且让事务协调器(如 Microsoft BizTalk® Server)来处理消息依赖性。 |
• |
自己在客户端或服务器上编写事务补偿代码。使用相应的通讯协议,以便服务器可以用来决定何时启动事务,以及如何通知客户端要完整处理的事务成功完成或失败。 |
避免在网络中发送数据集
数据集可能太大、太详细,因而无法用作在多个层之间发送数据的通讯有效负载机制。取而代之,您应该使用数据传输对象 (DTO) 来减少发送到外部接口的消息有效负载。对于数据更改,您应该考虑只发送已更改的数据,而不是发送整个数据集。
有关 DTO 的详细信息,请参阅第 2 章:处理数据。
将大型数据集分解
如果您试图同时显示大型数据集的所有内容,则它们可能在客户端导致性能问题。因此,您应该将它们分解为较小的数据集。以这种方式分解数据称为分页。例如,与显示电话目录的全部内容不同,您可以选择一次显示一页(例如,每屏按字母顺序显示 20 个记录)。如果您将客户端设计为使用分页,则应该确保对用户界面进行相应的设计,以便使用户可以容易地在各个页之间导航。
这一分解大型数据集的概念还适用于通过网络与服务器进行的通讯。如果您可以将数据分解为可管理的数据块,则您随后可以按照需要加载所需的数据,这种技术称为惰性加载。在电话目录示例中,只有当前操作需要的数据将被加载,从而减小了对应用程序和网络的影响,并且可能使二者的响应更为迅速。
要改善用户体验,可以在对即将到来的用户请求进行预测的基础上,使用附加线程执行后台处理以及与服务之间的通讯。
尽管对惰性加载的支持可能是智能客户端应用程序设计的重要方面,但您应该记住应用程序的脱机要求。通过网络传输的惰性加载数据可能会妨碍应用程序像您希望的那样脱机工作。
将您的 Web 服务和程序集版本化
当您将新版本的智能客户端软件发布到客户端或者对该软件进行升级时,应该创建新版本的程序集。如果您使用版本化的程序集,并且如果您将服务器服务设计为支持向后兼容接口,则可以支持多个版本的客户端软件。在发布新版本的 Web 服务时,您应该通过规范的命名约定来区分它们。可以改变各个版本的命名空间,以便它们包含日期信息,从而能够清楚正在与哪个版本的 Web 服务客户端通讯。
有关处理多个版本的程序集的详细信息,请参阅第 7 章:部署和更新智能客户端。
小结
智能客户端需要访问资源(包括本地资源和远程资源)才能正常工作。要成功地设计可靠的并且能够迅速响应用户操作的智能客户端,您如何处理这一通讯可能非常关键。诸如性能、安全性和灵活性之类的要求会影响到哪种连接选择适合于您的环境。使用本章中的指导,您应该能够确定哪些形式的连接适合于您的智能客户端,然后相应地设计您的智能客户端以及它们与之进行通讯的资源。
转到原英文页面