Web 服务和其他远程接口设计指南

eb 服务和其他远程接口设计指南
级别: 初级
André Fachat
IT 架构师, IBM Global Services
2004 年 8 月
交互式组件和服务网络中包括越多的应用程序,就越需要考虑潜在的性能问题,这通常是由分布式体系结构而引起的。某一特定功能或方法的执行时间当然还是很重要的,但就分布式组件对性能问题的影响而言,他们之间的通信时间现在受到了牵连。
Andre Fachat 通过一个购物车实例讨论了分布式设计。该实例非常简单,但是也强有力的证明了什么是好的做法,什么是不好的做法。实例显示了通过减少远程调用的数量来保持通讯的粗粒度是一个很好的办法。它还提出了 ID-Lists模式,把多个远程调用合并为一个。
引言
实现分布式系统通常包括通过网络来集成分布式应用程序,在这个网络中,每个应用程序提供一组特定的服务。这就引出了面向服务的体系结构 (SOA) 的概念,例如,在 [ SOA, SOAD] 中有介绍。假设随着新的远程访问规范的发布,并且各种产品都支持它,和旧的应用程序一样,IT 架构师需要为在单个应用程序中进行远程访问处理大量不同类型的规范。这些服务可以作为远程企业 JavaBean (EJB) 方法调用、Web 服务或 CORBA 调用(这里只列出几个)来执行。本文尽量保持通常的体系结构观点,而不是就任何具体的实现技术而言的。
调用远程服务包括将请求数据打包成在服务请求方可传输的格式,把数据传送给服务,然后在服务响应方将请求解包。对于响应这个过程刚好相反。因此,远程实现功能的感知响应时间不仅仅取决于远程实现的性能,还依赖于:
? 完成一个特定的功能需要单独远程调用的数量
? 建立远程调用的时间
? 打包和解包请求和应答所需的时间
? 将请求传送给服务并返回响应所需的时间(这个时间取决于传输延迟、传输速度以及数据量)
为远程访问设计接口时必须牢记它是否影响整体性能。需要注意的是,完成一个特定的功能可能需要调用多个远程服务。
通常需要重复使用现有的服务。记住,那些服务可能是用本地应用程序设计和开发的,不能用于远程访问。我曾经历过这样一个情况,在企业资源计划 (ERP) 系统中,购物车里条目的价钱逐个地计算。当我们要执行的基于 Web 的商店调用该价格函数时,由于许多远程调用请求该 ERP 系统,性能非常糟糕。我们不得不在 ERP 系统中执行一个封装器,用来计算所有条目的价钱,然后从我们的 Web 商店调用封装器来提高性能。
在下面的部分中,我将介绍前面提到过的那个简单实例,它读取一个购物车并进行分析,找出提高性能的模式。在第 2 部分中,我将提供一些具体的模式。
实例用例
该实例讨论了从远程系统中读取购物车的用例。可以在基于 Web 的商店的上下文中看到该实例,在实例中,客户端应用程序代表用户与分布式系统进行交互,把条目集中放到购物车中,最后购买所选的条目。用例中读取的数据应该用来向用户显示购物车。购物车由消息头(显示送货地址和付款信息)和一列条目组成,每个条目包括一个商品和该商品的数量。
图 1 显示了对象模型。该模型由一个购物车对象 (“ Cart ”) 组成,这个对象包含了购物车消息头信息。 Cart 可以有多个条目, CartItem 对象包含对 Article 对象的引用以及购物车(为了更清楚地说明问题,图中故意省略了属性)中该商品的数量。 Article 对象包含关于商品的通常信息(例如,价格、重量、图片), ArticleDescription 对象包含关于该商品的详细语言描述。为以后扩展该系统还附带了一张 Auction 表。
图 1.购物车对象模型。

读取购物车的用例包括读取 Cart 和 CartItems ,就象商品信息包括 Article 和 ArticleDescription 对象一样。因此,设计的时候就应该考虑到以后会有交易,而交易会涉及到商品,而且商品信息应该从外部 ERP 系统中读取。
在下面的部分中,我将讨论当用户(由客户端应用程序代表)与远程系统交互时,这个用例的实现的几个方面。第一个实例的实现使用的是最初的设计方法,由于是按标准使用模式提出的,表明它不是最佳的访问模式,因此会引起性能问题。
远程实体 bean
企业 JavaBean 组件广泛用于远程访问数据和服务。实体 EJB 组件的主要目的是远程访问持续数据,这些数据主要存储在关系数据库中。在购物车用例实例中,您必须假设对于每个对象您都有一张表,这些对象是指: Cart 、 CartItem 、 Article 和 ArticleDescription 。对每张表定义一个实体 bean。客户端应用程序通过 Java 命名和目录接口 (Java Naming and Directory Interface,JNDI) 服务来查找 Home 接口,然后在 Home 接口上可以用 finder 方法检索 bean 的实例。有关那四张表的初始 Home 接口请参阅清单 1:
清单 1.对象表的 Home 接口

public interface CartHome extends javax.ejb.EJBHome {

Cart create() throws javax.ejb.CreateException;

Cart findByPrimaryKey(CartId id) throws javax.ejb.FinderException;
}

public interface CartItemHome extends javax.ejb.EJBHome {

CartItem create() throws javax.ejb.CreateException;

CartItem findByPrimaryKey(CartItemId id) throws javax.ejb.FinderException;

Collection findByCart(CartId id) throws javax.ejb.FinderException;
}

public interface ArticleHome extends javax.ejb.EJBHome {

Article create() throws javax.ejb.CreateException;

Article findByPrimaryKey(ArticleId id) throws javax.ejb.FinderException;
}

public interface ArticleDescriptionHome extends javax.ejb.EJBHome {

ArticleDescription create() throws javax.ejb.CreateException;

ArticleDescription findByPrimaryKey(ArticleDescriptionKey id) throws javax.ejb.FinderException;

Collection findByArticle(ArticleId id) throws javax.ejb.FinderException;
}
请注意 CartItemHome 接口有一个 finder 方法,该方法为特定的购物车查找所有的条目。同样地, ArticleDescriptionHome 也有一个 finder 方法,用来查找特定商品的所有描述。
要执行该用例,即读取购物车,通过调用 findByPrimaryKey(CartId) 来调用购物车的 finder 方法。该方法返回一个用于购物车表的列的实体 bean,这个实体 bean 有一个给定的 CartId 。然后调用 CartItemHome.findByCart(CartId) 用给定的 CartId 为属于购物车的条目检索 CartItem bean。每个 CartItem 包含数量和一个 ArticleId 。要读取该商品数据,必需 ArticleHome 接口,并且为购物车中的每个商品调用该接口的 findByPrimaryKey() 方法。检索到的 bean 中包含显示购物车所必需的信息。
但是,为什么这样使用实体 bean 不是一个好方法?这是有原因的:在 bean 实例上对任何方法的调用都是使用远程调用,从服务器上检索数据,或把数据写到服务器上。显然,这些远程调用在性能上需要很大的代价,因此,通常都雇用其他的机制。我们的实例使用的是传输值对象的会话层 (用 JavaBean 组件来传送表中的数据,[ TVO]),而不是直接调用实体 bean,应用程序调用一个会话层 bean [ TopJ2EE],该 bean 从数据库中读取数据,用读取的值填充 JavaBean 组件,然后把组件返回给调用方。写入数据库时情形是类似的,在本实例中,调用方用将要写入数据库的数据填充传输值对象,在会话 bean 上调用 write 方法,然后执行 write 功能。例如,IBM 在它的 AccessBeans 组件中压缩了这个模式,而 WebSphere? Studio 系列产品 [ AB] 都用到了 AccessBeans 组件。现在,使用各种访问 bean 模式被认为是一种艺术,我假设这个模式适用于所有的后继实例。因此,我只关注检索传输对象的方法。
一点理论
这个基于 EJB 的实例显示了一个当访问远程组件和服务时提高性能的重要模式,即减少远程调用的数量,但是为什么远程调用需要这么高的代价呢?在某种程度上理解这一点可以帮助避免性能问题。
在下面的部分中,我将研究从服务请求方发送消息到服务响应方。假设该消息由信息头部分和一些条目组成,这些条目大小相同,但数量不定。这个方法在算术上最接近大小不定的消息(请原谅,我将尽量使它简短)。
图 2:远程调用的上半时段

图 2 显示了发送请求信息到远程服务的不同阶段:
1. 构建远程调用(例如查找 Home 接口,构建编组程序(marshaller)等。)
2. 将请求数据打包,即把请求转化成适合在网络上传输的格式(例如,采用 Java 技术将请求转化为用于 J2EE SOAP 的 XML,用于 IIOP 的 Java 二进制对象)。
3. 将打包后的数据传输到远程终端。
4. 构建接收端(构建分组程序(unmarshaller),例如,XML 解析器等。)
5. 将请求解包成对象,用来调用远程服务实现。
请注意上图中只显示了一些必需的阶段,这些阶段中不包括本地调用。
上图显示了进程中的有些阶段依赖于条目的数量,也就是说,依赖于消息的大小,而其他的阶段则不依赖于条目数量:
T_setupTx
在上面的实例中,设置发送器的时间不依赖于条目的数量。
T_marshall = T_marshall_hdr + N * T_marshall_item
在上面的实例中,打包请求的时间依赖于条目的数量。
T_transport = T_latency + T_transport_hdr + N * T_transport_item
T_transport_hdr 和 T_transport_item 间的时间间隔依赖于网络带宽(字节/秒)和各自数据的大小(#字节)。 T_latency 是把发送方的第一个字节放在传输媒体上和在接收方接收该字节所消耗的时间。
T_setupRx
在上面的实例中,设置接收器的时间不依赖于条目的数量。
T_unmarshall = T_unmarshall_hdr + N * T_unmarshall_item
解包请求的时间再次依赖于条目的数量。
稍稍重新分解一下公式,调用所需要的总时间 T_total 变为:

T_total = T_setupTx + T_marshall_hdr + T_latency
+ T_transport_hdr
+ T_setupRx + T_unmarshall_hdr
+ N * (T_marshall_item + T_transport_item
+ T_unmarshall_item)
该表达式也可以写为:

T_total = T_fixed + N * T_item
将固定部分合并:

T_fixed = T_setupTx + T_marshall_hdr + T_latency
+ T_transport_hdr + T_setupRx + T_unmarshall_hdr
将不定部分合并:

T_item = T_marshall_item + T_transport_item + T_unmarshall_item.
值得注意的是远程调用的总时间依赖于大量不同部分。当估算远程调用的时间时,例如,用跟踪语句,了解每一部分从哪里开始以及到哪里结束非常重要,因为这样才可以在适当的位置设置跟踪语句。用不同的消息大小来测算远程调用也很重要,这样可以检测性能问题是由固定部分引起的还是由依赖于消息大小的不定部分引起的(消息大小指的是条目的数量)。
高速缓存 JDBC 连接(当然,远程数据库调用也是一种远程服务)就是一个实例,在这个例子中发现了上面那样的问题并得到了解决。高速缓存连接通过避免与数据库连接的时间(除了第一次)减少了设置时间。基于相同的道理,从 JNDI 检索到的 EJB Home 接口也被高速缓存了。
公式也显示了减少远程调用数量的主要原因。用 n个远程调用传输相同数量的条目时,需要花费的时间为:

T_multi = n * T_fixed + n * T_item
但是在一个调用中传输相同数量的条目需要花费的时间为:

T_single = T_fixed + n * T_item.
两种传输的差别在于 (n-1)*T_fixed 。由于 T_fixed 包含网络延迟,而网络延迟通常只有用新硬件才可以优化(如果是从根本上进行优化的话),您会发现把多个调用合并为一个调用 [ FLDD] 很容易减少远程调用的数量。
适当的指导
在本文中的基于 Web 的商店同时也是基于 EJB 的实例中,我找出了影响分布式远程调用性能的相关因素。在这个由固定和不定因素组成的方程中有三个主要影响方面:打包、传输和解包过程中的数据。在应用程序发送方和接收方上的初始化过程和网络上的延迟进一步影响了这些方面。这一部分讲述了一些原理,第 2 部分我将举一些实例。我还要用到这里描述的样本用例,通过减少远程调用的数量优化实例的性能。在这个过程中,我将讨论远程访问模式和分离相关因素以及高速缓存,最后就如何进行好的分布式应用程序设计提供适当的指导。
致谢
感谢 Stefan Peuser, Olaf Zimmermann, Witold Szczeponik 以及 Frank Müller 为本文提出宝贵的修改意见。
参考资料
? 您可以参阅本文在 developerWorks 全球站点上的 英文原文.
? [ SOA] Mark Colan,“ 面向服务的体系结构扩展了 Web 服务,第 1 部分 - 面向服务体系结构的特点” ( developerWorks,2004 年 4 月)
? [ SOAD] Olaf Zimmermann,Pal Krogdahl,Clive Gee,“ 面向服务分析与设计原理 - 用于 SOA 解决方案的各学科间的建模方法”( developerWorks,2004 年 6 月)
? [ TopJ2EE] Kyle Brown,Keys Botzum,Ruth Willenborg,“ 开发者技术期刊:10 个(或多或少)J2EE 最佳实践”( developerWorks,2004 年 5 月)
? [ DP] Erich Gamma,Richard Helm,Ralph Johnson 和 John Vlissides, 设计模式:可复用面向对象软件原理 ,ISBN 0201633612,Addison-Wesley Pub Co。
? [ SoC1] Edsger W. Dijkstra,“ Separation of Concerns”

企业应用开发, CORBA 和 EJB 有着明显的优势,并且 CORBA 和 EJB 所依赖 Java 技术可以很好的互补。 CORBA 处理网络透明性, EJB 处理实现透明性。由此看来, CORBA 和 EJB 技术紧密结合是今后多层分布式系统发展的一大趋势。
参考文献:
1 童恒庆 ,聂会琴,李锡喆.CORBA/COM/EJB三种组件模型的分析与比较[ J ]. 计算机应用研究,2004,4;66-67.
2 萨默维尔 .软件工程[ M ]. 北京: 机械工业出版社,2003.1.
3 李纪云 ,董小社,童瑞.分布式对象中间件技术研究[J].计算机工程与设计,2004,2;170-173.
4 邱岩 .组件技术及其分析比较[J]. 计算机工程与设计,2003,7;13-17.
5 巴姆巴拉 .J2EE技术内幕[ M ]. 北京: 机械工业出版社,2002.
基于.Net Framework的N层分布式应用开发


一、分布式处理概述

分布式处理是将应用程序逻辑分布到2台或者更多台计算机上,在物理上或逻辑上分离的单元中。这一概念并不是新生事物,在大型工程已经得到广泛使用。只不过,Internet的出现为分布式处理赋予了新的特征,Internet内部连接的特性可以让成百上千的计算机为一个任务工作,使得在更大规模上实施分布式处理成为可能,并跨越了传统的B/S(客户机/服务器)模型。

分布式处理思想经历了很长的过程,不同IT时代的开发人员、各级供应商做了大量的工作,使得支持分布式处理的协议极为丰富。

1、 DCOM/CORBA

在.Net Framework之前,基于组件的分布式计算的主要协议是CORBA(Common Object Request Broker Architecture,通用对象请求代理结构),它来自Object Management Group(对象管理组),还有Microsoft的DCOM(Distributed Component Object Model,分布式组件对象模型)。

DCOM是面向连接的。DCOM客户机持有对DCOM服务器的连接。这种连接方式导致了技术问题存在。例如,客户机可能持有引用信息,只有在用户单击按钮时生成调用。时间一长,服务器就会因等待客户机的请求而空闲。当客户机崩溃而无法请求服务器时,就会产生严重的后果。另外,在Internet上,DCOM或者CORBA服务器由数千台客户机使用,由于每一台客户机都有一个与服务器的连接,对于很少使用服务器或者根本不再使用服务器的客户机,应该保护宝贵的服务器资源。

尽管DCOM有办法处理这些问题,但是增加了许多复杂性,这也是Web服务试图解决的问题之一。

2、Web 服务


随着Microsoft .Net Framewwork的推出,实现分布式处理有了新的技术,即Web Service(Web服务)。Web服务能够为另一个应用程序而不仅仅是浏览器提供数据,并通过外置数据以允许其他的客户机使用在同样的端口和传输层都起作用的标准协议(如HTTP)来执行操作。

二、Web Service-.Net Framework下的分布式处理技术

在.Net Framework中,Web服务指是以独立于平台的方式,通过标准的Web协议,可以由程序访问的应用程序逻辑单元。

.Net Framework的开发者们将Web服务定位于基于开放的标准,能够用于任何平台。使它拥有作为跨平台和跨供应商的集成技术的潜力。实现了Web服务和Web服务构架后,用户就可以利用Internet上许多现有技术。Web服务成功的关键在于它基于开放的标准,诸如Microsoft、IBM和Sun等主要供应商都支持这些标准。

1、DCOM/CORBA面临困难之解决方案--Web服务


DCOM和CORBA在使用运行于相同平台的软件和紧密管理的局域网创建企业应用程序时非常优秀。但是,他们在创建跨平台 、跨Internet、适应Internet的可伸缩性的应用程序时力不从心。他们不是为完成这些目标而设计的。

大多数公司面临的现实情况是他们拥有来自多个供应商的多种平台。运行于不同平台上的应用程序系统间通信困难。在与商务伙伴合作时,基于传统分布式的架构合作困难。

DCOM和CORBA的问题是用户基本上要依赖一个供应商。如果要使用DCOM,就必须使用Microsoft Windows来运行服务器和客户机。尽管有其他平台上的DCOM实现方式,但是他们未被广泛采纳。虽然CORBA是由多个供应商实现的规范,互操作性仍只能以简单的方式完成,至于DCOM和CORBA间的集成就不必说了。

从技术方面看,Web服务试图解决使用诸如CORBA和DCOM这样紧密捆绑的技术时遇到的问题。这些问题包括如何通过防火墙,协议的复杂性,异类平台的集成等。

2、Web服务在分布式处理中的应用


Web服务是一种优秀的分布式处理技术。

下图演示了在.Net Framework下进行分布式处理的一般情形。作为客户端应用程序可以是传统的Windows Form应用程序、基于Web的Asp.net应用程序、蜂窝式移动应用程序等,还可以是另外的Web服务程序。这些客户端应用程序构成N层模型中的表示层(图中左列)用于数据显示。中间列是中间层,处理商务逻辑;右列是数据层,处理数据存储。

随着一个基于xml的名为简单对象访问协议SOAP(Simple Object Access Protocol)的不断标准化,web服务正成为一个可以和其他服务器和应用程序交互、可行的方法。

3、N层模型下客户机消费Web服务

下图演示了客户机消费Web服务的情形。客户机可以是一个Web应用程序、另一个Web服务、诸如Microsoft Word的字处理程序等。

Web服务的消费者调用名为Method()的Web服务上的方法。实际调用向下层传播,作为Soap消息通过网络,并向上层传播到Web服务。Web服务执行并响应(如果有的话)。

实现Web服务与客户机之间的双向通知或者发布/订阅功能是可能的,但是必须手工完成。客户机可以实现自己的Web服务并在对服务器的调用中传递该Web服务的引用。服务器可以保存引用,然后回调给客户机。

三、基于.Net Framework的N层构架设计

面向对象的、基于模块化的组件设计需要能够方便地修改应用程序的各个部分。完成这一目标的一种好方法就是在层上工作,将一个应用程序的主要功能分离到不同的层或者级中。.Net Framework为创建可维护、可扩展的层模式提供了丰富的支持,使得N层够架取代传统的客户机/服务器模式而与Internet紧密结合。

1、分层模型


从本质上讲,层代表了一个应用程序主要的功能。一般地,我们将应用程序功能分为三个方面,对应3层架构模式。它们是数据层(data layer)、商务层(business layer)和表示层(presentation layer)。

数据层:包含数据存储和与它交互的组件或服务。这些组件和服务在功能上和中间层相互独立(尽管在物理上不必一定相互独立--它们可以在同一台服务器上)。

中间层:包括一个或者多个组件服务,它们应用商务规则、实现应用程序逻辑并完成应用程序运行所需要的数据处理。作为这个过程的一部分,中间层负责处理来自数据存储或者发送给数据存储的数据。

表示层:从中间层获得信息并显示给用户。该层同时也负责和用户进行交互,比较返回的信息并将信息回送给中间层进行处理。

可见,数据层从数据库中获得较为原始的数据,商务层把数据转换成符合商务规则的有意义的信息,表示层把信息转换成对于用户有意义的内容。

这种分层设计方式很有用,因为每一层都可以独立地修改。我们可以修改商务层,不断地从数据层接受相同的数据,并把这些数据传递到表示层,而不用担心出现歧义。我们也可以修改表示层,使得对于站点外观的修改不必改动下面的商务层逻辑。

2、常用的N层模型设计

已经知道,一个N层应用程序中的层不是由运行应用程序的物理结构(硬件)定义的。层是应用程序运行的一个逻辑方面的功能,并定义应用程序将执行的不同的任务阶段。这里的N层设计与经典的客户机/服务器架构截然不同。

1)、设计一个简单的3层

最简单的N层模型就是3层。这里,我们已经有一个被网络分隔开的服务器和客户机。服务器中含有数据存储和组成数据层的数据访问组件,已经组成中间层的商务逻辑。客户机作为表示层只需要给应用程序提供界面即可。

在这个最简单的情况中我们或许有一个关系数据库或者一组访问数据的组件或者存储过程。然后我们应当有一个访问组件或者存储过程的asp.net页面来提取信息,处理和格式化信息使之适合于特定的客户机,然后通过网络将信息传送给客户机。客户机所要做的事情就是显示信息、收集用户的输入和将信息回送给中间层。

2)、设计一个更接近现实的3层

然而前面的示例只是非常小的应用程序的一般情况,现实世界中很难碰到。数据存储通常位于专门选择和经过专门设置的硬件上。它也许是在运行SQL Server的基于Windows的一组服务器上,但是也可能是运行非Windows平台或Oracle或者其他的数据库服务器上。

在这种情况下,数据层和中间层之间的分离就更加显而易见--它们之间通过网络连接。并且,商务逻辑被限制在执行所有中间层数据处理的服务器上。

3)、设计N层

很明显,上面的情况都假定了两件事:一是客户机为一个低端设备(因此不参与应用程序中所需的实际数据处理);另外就是只有一组商务规则。

然而,这些假设并不符合实际的应用程序。例如,我们通常期望商务规则在其他某个地方而非在中间层中。在提取数据过程的前期实现某个商务逻辑比较恰当,当然我们也可以在访问数据存储的组件中实现商务逻辑。这个商务逻辑"包"因此能和数据存储在同一个服务器上,或者甚至(在一个分组的环境中)在另外一个中间路由服务器上。

另外,为了充分利用"胖客户机"的一些性能,以便减少网络负载和因访问路径循环而导致的迟滞,我们可以将一些商务逻辑放在客户机上。

4)、设计一个更加现实的N层

一般地,我们使用一个或者多个分离的服务器来维持我们正在使用的数据存储,这时,商务逻辑的分布更为分散。下图显示了由两个网络分离的三个机器。可以看出,现在的商务逻辑被分为三个区:一些将和数据存储运行在同一台服务器上,另一些将在中间层服务器上运行,还有一些将在客户机上运行。

由此可以看到,准确定义各个层并不容易。"中间层"的真正意思是商务逻辑本身,并且,商务逻辑的不同元素可以无可非议地存在于不同的服务器中。

3、.Net Framework下的层间(远程)传输对象及技术

.Net Framework实现了许多新的技术以支持多层分布式处理,它提供了丰富的类库、对象及方法使得在不同层(物理上分离或仅仅是逻辑上分离)间的数据传输更为简单。

1)、支持远程数据传送的对象:

l ADO.NET DataSet对象

l ADO.NET DataTable对象

l XmlDocument对象

l XmlDataDocument对象

2)、支持远程数据传送的类/方法:

l Serialization类

Serialization类描述了一个将数据转换为一种能复制到另一个过程的格式的对象的过程。前面提及的可远程传输的对象具有串行化整个内容的能力,以便它可以通过一个通道来传送。这个通道可以直接通过TCP/IP,或者通过HTTP。当然,它们也可以在另一端解除串行化,因此客户机就得到一个原对象的完整副本。

l System.Runtime.Remoting类

System.Runtime.Remoting命名空间提供的对象可用来为对象创建代理以实现远程数据传送。在这种情形下,对象保留在服务器上,并且客户机只收到一个代理对象的引用。这个代理对象表示原来的基于服务器的对象(这就是我们怎样远程使用一个DataReader的方法),示意如下图:

对于客户机,这个代理提供了与原始对象相同的方法和属性。然而,当客户机与代理对象相互作用时,调用被自动串行化,并通过通道(网络)传送给服务器上的对象。然后,任何响应和结果通过通道被传送回客户机。

这两个远程技术都允许客户机使用原来在服务器上创建的对象。我们能够串行化一个DataSet对象或者Xml文档,同时我们也能串行化其它的如集合这样的对象--比如一个哈希表(Hashtable)或数组(Array)。

4、N层模型中的数据处理及对象选择

首先需要考虑的是希望从数据存储中提取出来的数据做些什么?这个问题的答案对我们所使用对象的基本选择的影响将比其他任何事情都要大,甚至在某种程度上定义了我们希望完成任务的性能的种类。

1)、只用于显示的数据

如果只是想以一种固定格式为终端用户显示数据的话,一般来说根本就没有必要远程传输数据。我们没有必要在线上将所有的数据传送给客户机--我们只能传给它们客户设备能接受的任何格式的最终显示信息。

在这种情形中,"Reader"对象提供了一种只读的、仅向前的理想且性能最优的技术。当与能实现服务器端数据绑定的服务器控件一起使用时,我们可以获得一个显示数据的高效方法。

2)、需要远程传输的数据

然而,如果我们需要远程传输数据的话则存在一个问题。这些快速而高效的"Reader"对象只在作为一个引用时才能被远程传输。将一个DataReader作为引用传送给一个客户机时,DataReader仍还在服务器上,不过客户机的应用程序也可以使用它。在这种情况下,我们实际上并没有远程传输数据,而是使用了一个远程传输对象。在很多情况下都存在这种情况。

要实现数据的远程传送,应该将数据寄存到一个能够存储(或保持)数据的对象中。并允许代码不需进入数据存储的额外行程就可以根据需要提取数据,并且多次读取。在ADO.NET中,这个对象就是DataSet对象(或者DataTable对象)。当使用xml时,也有几个对象供选择。我们能够远程传输XmlDocument和XmlDataDocument对象。这两个对象都有保持内容的能力,并且可以在一个应用程序的层之间进行传送。

四、N层分布式数据处理架构模型

要进一步理解怎样在应用程序中划分不同的层,需要确定数据如何显示以及是否需要更新数据和向服务器及时返回更新。

1、全部在服务器上完成显示

在客户机上显示数据,最常见的情形是在一组或者多组服务器上执行所有的数据处理。数据层和中间层限于服务器,客户机只提供显示接口。对于一个web浏览器来说,通常的格式为html,对于一个蜂窝式电话或类似设备来说,可能是以wml格式表示,等等。

使用一个存储过程或SQL语句来提取所需要的数据,然后用asp.net进行处理,或者执行一个web服务。另外,这里也用xml片段的形式从数据存储中提取数据,然后对数据进行处理并提供给客户机。

如果以xml文档形式存储数据,或者以这样一种格式存储数据:数据作为xml外置数据层,那么我们就有一些其他的选择。

显示了怎样提取和处理xml数据以便传送给客户机使用。此外,数据的提取其实就是借助一个"Reader"对象,并且可以使用不同的技术来处理数据并将数据提供给客户机。

2、扩展中间层


虽然数据的提取和处理经常在一个对象里发生,比如一个Asp.Net页面,但是为了有效利用由于使用基于组件的设计而提供的好处,通常需要提供更为精细的架构。我们应该有在显示数据或者将其传送给客户机之前应用于数据的商务规则。换句话说,它可能是因为安全的原因,也可能是为了实现分布式处理,或者只是提供可重用性和使应用程序的维护更加容易。

例如,应该有访问一个数据存储并提取一系列消费者的多个页面。通过在一个独立于asp.net页面或其他提供数据给客户机的对象的组件中建立这个过程,我们能够提供一个提取数据的层。然后,我们在将来需要在某些方面改变数据存储或者数据结构,或者改变访问它的规则,我们只要用一个新的版本替换组件即可。

只要组件的接口仍然未变,所有使用这个接口的应用程序将看到来自组件的相同输出并和以前一样继续运行。然而,组件在内部用来提取和处理来自数据存储的数据的方法可以根据需要进行相应修改。
显然,该过程可以使用多个组件。如果数据的提取相当复杂,或者同一数据运用在多个地方的话,进一步分解数据处理(分解为更多组件层)就很有意义。例如,可用一个组件将数据当作一系列包含所有必须列的行(以关键字顺序排列),这个组件就可以成为其他以不同顺序存储数据的组件,或者仅外置数据的某些列的组件的数据源。

3、移动数据处理到客户机

一般地,要获得发送给客户机的数据,我们将利用客户端脚本(JavaScript或 VBScript以及 WMLScript)、用Java或者一个特定平台的语言书写的客户端组件,或者用诸如Visual Basic 6.0、C++、Delphi等语言书写的客户端可执行程序等等。当然,所有我们需要的功能都是.Net Framework的一部分。(用户可通过下载和安装可重新分配的Framework(大约5MB)在客户机上使用Framework)。

4、将更新回送给服务器

在许多情况下,如果我们的要求就是以一种尽可能快速和高效的方式获得发送给客户机的依据,那么,上面的示例能很好地完成任务。然而,许多应用程序要求客户机将数据回送以更新数据存储等操作时,就需要寻找更合理的模式。

至少有三种方法用于向服务器端回送数据。一是回送Html表单和查询字符串(实现方式与以前的ASP类似);另一是客户端组件(例如IE5及以上版本的XMLHTTP组件);还有就是客户端可执行的Windows表单应用程序和服务等。

因此,应该有这样一种情况:客户机仅仅要求我们发送一些数据,并且我们让客户机完成所有的数据处理。也就是说,客户机充当某种类型的服务,它将应用程序的数据作为自己的源数据来使用,然后在它的客户机已经处理数据后将更改提交回来。

一旦客户端完成了数据更新,或者已经收集了用户输入的新数据,客户机应用程序就以一种合适的格式打包数据(或者用正确的技术整理数据),并将它提交给服务器进行处理和存储。

利用"胖客户机"来实现这种架构的方法,其中数据在客户机上进行处理,然后经整理后返回给服务器来更新原始的数据存储。 仍然地,这不是一个包含所有可能性的图表。回送数据的方法或许和发送数据的方法没有什么联系。你应该根据应用程序的实际需求设计合适的模型。

五、结束语

建立可维护、可扩展的站点,开发高效率、高伸缩性的应用程序、实现跨平台、跨Internet的应用集成、创建N层分布式应用程序是摆在无数开发者面前的任务。传统开发方式及技术面临了困难。

.Net Framework推出的许多新技术为这些任务的实现提供了相对简单的解决方案。其中,基于SOAP的Web Service在处理分布式应用时具有比传统的DCOM/CORBA明显的优点,结合基于Web的ASP.NET页面开发技术和SQLServer数据存储技术(或Xml文档),在.Net下开发N层应用程序也不再困难。

要很好地完成以上任务,你需要根据实际情况设计合理的应用程序架构模型。本文正是为了在这方面为你提供参考。
多层结构、非分布式、分布式


多层结构

是指将应用程序逻辑分为3个基本层(当然,您可以根据实际情况把这3个基本层切分得更加薄一些,成为更多的层次。)

理解layout(逻辑概念)和tier(物理概念)


非分布式

是指应用系统的所有部件包括数据库均部署在企业内部网络的服务器上(Intranet或LAN的部署),由单个服务器(单计算机部署)或者网络场(多计算机部署)来完成应用系统的处理工作。
? 传统B/S模式(两层)
? 传统C/S模式(两层)
? 基于B/S模式的多层结构
? 基于C/S模式的多层结构
在Windows的开发体系里面对B/S或C/S的多层结构(一般来说企业应用不会考虑采用两层结构)采用非分布式方式的系统部署方案有如下三种。
? 单计算机部署
? 旧式Interop 部署(网络场)
? ISA Server 部署(网络场)

分布式

是指由于应用系统的事务跨越广域网(WAN),要对广域网上的服务器进行诸如数据读取的操作,而采用的一种系统部署方式。
采用分布式方式的部署方案均采用多层结构,因此也称作多层分布式结构。
在Windows的开发体系里面实现分布式方式系统部署方案的技术有三种。
? DCOM [DCOM(NDR)]
? .NET Remoting [HTTP(二进制)/HTTP(SOAP)/TCP(二进制)]
? Web Services [SOAP]
采用分布式方式的系统部署方案有如下三种。
? Web 外部宿主/周边网络
? .NET 到旧式集成
? 旧式Interop
相关技术 [以前的分布式结构:Microsoft Windows DNA (Distributed Internet Application Architecture)]

posted on 2006-03-04 16:26  Sanle  阅读(419)  评论(0编辑  收藏  举报

导航