WCF深入研究.docx

上传人:b****4 文档编号:6877331 上传时间:2023-05-10 格式:DOCX 页数:16 大小:224.72KB
下载 相关 举报
WCF深入研究.docx_第1页
第1页 / 共16页
WCF深入研究.docx_第2页
第2页 / 共16页
WCF深入研究.docx_第3页
第3页 / 共16页
WCF深入研究.docx_第4页
第4页 / 共16页
WCF深入研究.docx_第5页
第5页 / 共16页
WCF深入研究.docx_第6页
第6页 / 共16页
WCF深入研究.docx_第7页
第7页 / 共16页
WCF深入研究.docx_第8页
第8页 / 共16页
WCF深入研究.docx_第9页
第9页 / 共16页
WCF深入研究.docx_第10页
第10页 / 共16页
WCF深入研究.docx_第11页
第11页 / 共16页
WCF深入研究.docx_第12页
第12页 / 共16页
WCF深入研究.docx_第13页
第13页 / 共16页
WCF深入研究.docx_第14页
第14页 / 共16页
WCF深入研究.docx_第15页
第15页 / 共16页
WCF深入研究.docx_第16页
第16页 / 共16页
亲,该文档总共16页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

WCF深入研究.docx

《WCF深入研究.docx》由会员分享,可在线阅读,更多相关《WCF深入研究.docx(16页珍藏版)》请在冰点文库上搜索。

WCF深入研究.docx

WCF深入研究

1WCF的特性

根据微软官方的解释,WCF是使用托管代码建立和运行面向服务(ServiceOriented)应用程序的统一框架。

它使得开发者能够建立一个跨平台的安全、可信赖、事务性的解决方案,且能与已有系统兼容协作。

它整合了.Net平台下所有的和分布式系统有关的技术,例如.NetRemoting、ASMX、WSE和MSMQ。

以通信(Communiation)范围而论,它可以跨进程、跨机器、跨子网、企业网乃至于Internet;以宿主程序而论,可以以ASP.NET,EXE,WPF,WindowsForms,NTService,COM+作为宿主(Host)。

WCF可以支持的协议包括TCP,HTTP,跨进程以及自定义,安全模式则包括SAML,Kerberos,X509,用户/密码,自定义等多种标准与模式。

也就是说,在WCF框架下,开发基于SOA的分布式系统变得容易了,微软将所有与此相关的技术要素都包含在内,掌握了WCF,就相当于掌握了叩开SOA大门的钥匙。

严格的说,WCF就是专门用于服务定制、发布与运行以及消息传递和处理的一组专门类的集合,也就是所谓的“类库”。

这些类通过一定方式被组织起来,共同协作,并为开发者提供了一个统一的编程模式。

WCF之所以特殊,是在于它所应对的场景与普通的.NET类库不同,它主要用于处理进程间乃至于机器之间消息的传递与处理,同时它引入了SOA的设计思想,以服务的方式公布并运行,以方便客户端跨进程和机器对服务进行调用。

实际上,WCF就是微软对于分布式处理的编程技术的集大成者,它将DCOM、Remoting、WebService、WSE、MSMQ集成在一起,从而降低了分布式系统开发者的学习曲线,并统一了开发标准。

整个.NETFramework(或者说是CLR)就可以认为是一个大的宿主,就像Java的虚拟机一样。

由于WCF对服务有着专门的需求,对于服务端,需要发布和运行服务;对于客户端,则需要调用服务;因而对于开发者,就需要编写定义、发布、运行、调用服务的相关代码。

而服务就只能运行在特定的宿主上,这些宿主可以是控制台应用程序进程、Windows或Web应用程序进程,也可以是Windows服务进程,或者为最常用的IIS宿主。

在宿主内部,则封装了通道堆栈,其中又包含了对协议、编码、消息传输、代理的处理。

而在通道层的顶部,还提供了一个高级运行时,以针对应用程序的开发人员。

WCF并不能脱离.NET框架而单独存在(但非WCF客户端可以调用WCF服务),即如(java可以调用WCF服务,但是java不能发布WCF服务。

)WCF的组成如下图。

2WCF是怎么运行的?

如果从宏观的角度来分析WCF的运行机制,它的实现并不复杂。

WCF的体系架构是基于一种拦截机制来实现的,负责传递和拦截消息的组件为通道,在客户端发出对服务端服务的调用时,首先会通过一个服务代理对象,将调用方提供的对象序列化到消息中,然后该消息则通过通道进行传递。

通道不只是包括一个,而是多个通道对消息进行处理,包括传输、消息编码、管理会话、传播事务等,但最底层的通道总是传输通道。

这些通道的构成形成了一个通道堆栈。

由于对象已经被序列化,因而此时通道传递的消息可以跨进程或机器进行传递,利用传输通道传递到服务端。

服务端的构成与客户端基本相似,仍然是通过通道栈中最底层的传输通道接收消息,然后解析消息编码,并一层层地往上传输。

在服务端的通道栈之上,则是一个分发器(Dispatcher,或者说是调度器),它会首先对消息进行检查,然后选择一个客户端要调用的操作。

在这个过程中,消息会被反序列化。

下图说明了WCF的整个运行过程:

由于WCF通过通道的方式传递消息,整个通道同时担当了侦听器和拦截器的功能,它可以根据服务的定义,在方法执行的前或后执行不同的操作,例如事务、会话管理、安全等。

这些操作在WCF中,大多数都可以以Attribute的方式应用到服务契约上,这样的实现方式,就类似于采用了AOP(面向服务编程)的方法为服务提供了大量的基础功能,有助于简化服务开发者的工作。

3为什么选用WCF?

WCF既支持具有互操作性的Web服务,也能够实现.NET客户端与.NET服务端的通信,提供了分布式事务的支持,同时在安全性上,它完全遵循了WS-*的标准,此外,它还支持队列服务,可以非常方便地利用消息队列完成异步操作与脱机调用。

而这些功能,以前的技术都只是部分的实现。

如下表所示:

WCF同时也使得面向服务编程更加简单而统一了。

如果采用旧有的技术,由于各种技术的编程模型完全不一致,使得程序的迁移非常的困难。

例如,最初采用.NETRemoting技术开发的分布式系统,由于业务需求的变化,要求发布具有互操作性的Web服务,就需要重新定义服务。

并且,客户端的调用方式也发生了变化,需要添加Web引用,通过UDDI去发现服务。

采用WCF则不然。

WCF引入了用通道,它封装了消息的通信细节,例如编码、事务处理、安全等,然后又通过引入绑定的概念,封装了通道的组成顺序与处理细节。

最后,引入了独有的Endpoint元素,集成了地址、绑定和契约之间的“三位一体”,以最简单的方式定义和发布服务。

每种绑定对应不同的传输协议、消息编码格式和版本以及安全、可靠性和事务模式。

WCF也提供了扩展绑定的方式,例如通过CustomBinding或者定义派生与Binding的类。

WCF的契约包括服务契约、数据契约和消息契约(特别的,还包括了错误契约,用于异常的处理)。

其中服务契约为面向服务应用程序的核心,通过它可以定义服务。

数据契约则为服务所要传递的数据。

由于服务的调用需要跨进程或机器进行通信,就需要服务数据必须能够被序列化和反序列化。

虽然.NET本身提供了数据的序列化功能,但WCF的数据契约更加符合服务数据的定义习惯。

至于消息契约,则可以将服务数据定义为消息,包括XML文本格式、MTOM(消息传输优化机制)格式和二进制格式。

绑定(Binding)、契约(Contract)与服务的地址(Address)组合在一起,则形成了终结点(Endpoint),如下图所示:

Address是Endpoint的网络地址,它标记了消息发送的目的地。

Binding描述的是如何发送消息,例如消息发送的传输协议(如TCP,HTTP),安全(如SSL,SOAP消息安全)。

Contract则描述的是消息所包含的内容,以及消息的组织和操作方式,例如是单向,双向还是请求/响应方式。

引入终结点可以说是WCF的一个伟大创举,通过它使得我们能够更加容易的发布和管理服务,尤其是发布和管理多个服务。

每个服务必须至少拥有一个终结点,而客户端正是通过终结点知道服务的相关信息,例如地址、消息编码格式、传输协议以及服务的内容,然后在进行正确的调用。

最特别的是,同一个服务可以定义多个终结点,每个终结点可以是不同的地址、不同的绑定方式,以便于满足多个客户端的不同需要。

而对于服务的发布者而言,我们只需要管理终结点的配置,就可以完成对服务的管理,这也为服务的托管提供了便利。

4WCF包括什么?

Juval的《ProgrammingWCFServices》一书基本已经涵盖了WCF技术的方方面面。

概括来讲,主要包括绑定、契约、消息传递、实例模式、并发处理、事务处理、安全以及队列服务等。

1.绑定属于WCF基本的技术要素,是WCF进行通信处理的基础。

了解绑定的相关知识,有助于开发WCF应用程序。

因为在不同的业务需求下,可能对通信方式、协议、消息编码等多个方面会有不同的要求。

在配制、发布和运行服务时,都需要对绑定进行操作。

因而,我们必须掌握WCF内置绑定的相关属性,熟悉绑定元素的相关配置。

Binding是可以自定义实现的,可WCF框架已经为我们实现了足够多的Binding,供我们来选择,如下表所示:

例外,《ProgrammingWCFServices》有一幅图也能说明各自的特征:

下面的图给出了我们选择Binding的方式

2.契约

在WCF中,契约分为四种,它们分别为:

用于定义服务操作的服务契约:

ServiceContract

这种级别的契约又包括两种:

ServiceContract和OperationContract

ServiceContract用于类或者结构上,用于指示WCF此类或者结构能够被远程调用,而OperationContract用于类中的方法(Method)上,用于指示WCF该方法可被远程调用。

用于自定义数据结构的数据契约:

DataContract

数据契约也分为两种:

DataContract和DataMember.DataContract用于类或者结构上,指示WCF此类或者结构能够被序列化并传输,而DataMember只能用在类或者结构的属性(Property)或者字段(Field)上,指示WCF该属性或者字段能够被序列化传输。

用于自定错误异常的异常契约:

FaultContract

FaultContract用于自定义错误异常的处理方式,默认情况下,当服务端抛出异常的时候,客户端能接收到异常信息的描述,但这些描述往往格式统一,有时比较难以从中获取有用的信息,此时,我们可以自定义异常消息的格式,将我们关心的消息放到错误消息中传递给客户端,此时需要在方法上添加自定义一个错误消息的类,然后在要处理异常的函数上加上FaultContract,并将异常信息指示返回为自定义格式。

用于控制消息格式的消息契约:

MessageContract

简单的说,它能自定义消息格式,包括消息头,消息体,还能指示是否对消息内容进行加密和签名

WCF作为一种能够跨平台的体系框架,其应用肯定会有异构,异网的情况发生,那么作为通讯依据的契约能否自动适用于上述情况呢?

答案是肯定的,契约是独立于平台之外的,它只约束通讯的双方应该遵守什么样的规则,而丝毫不管双方各自采用的是什么样的技术和什么样的操作系统,也只有这样,WCF才能有真正的生命力。

如果非要拿契约和以往的技术相比较的话,契约和xmlwebservice的声明性编程模型甚是相似,比如在webservice中在类上标记WebServiceAttribute便可以将此类用于远程调用,而将方法添加WebMethondAttribute也可以将其暴露给远程客户端,这和WCF中的ServiceContract和OperationContract简直如出一辙,但不同的是,WCF中的契约要比XmlWebService中的要详尽的多,比如ServiceContract和OperationContract可以直接使用在接口上面,而实现该接口的类就继承了这种契约声明,自动拥有契约所规范的动作和行为,这就使得程序员更方便的使用面向接口的编程方式,可以使同一服务拥有不同的实现,在新旧版本升级的同时,能够使新老版本共同运行

3.WCF定义了三种消息交换方式,分别为:

One-WayCalls、Request/Reply、Duplex

One-WayCalls

在几种消息交换模式中,one-waycalls是最没良心的,对于客户端,one-waycalls就如肉包子打狗,有去无回。

下面的图示给出这种交换模型的特征:

在这种交换模式中,存在着如下的特征

∙没有返回值,返回类型只能为void

∙不能包含ref或者out类型的参数

∙只有客户端发起请求,服务端并不会对请求进行回复。

通过设置OperationContract的IsOneWay=True可以将满足要求的方法设置为这种消息交换模式,方法如下:

[OperationContract(IsOneWay=true)]

voidTest(intintVal);

上面的代码,就是将方法Test设置成为了one-waycall的消息交换模式,注意如果Test方法的返回类型不是void或者带有ref或者out类型的参数,都会抛出异常InvalidOperationException,如下面列表中的方法均不能被声明为one-way模式

intTest(intintVal);

intTest();

intTest();

voidTest(refintintVal);

voidTest(outintintVal);

 

Request/Reply

request/reply比起one-way来说,就更懂得礼尚往来,它是缺省的消息交换模式,类似于http协议中的请求/响应模型。

下面的图示给出这种交换模式的特征:

这种交换模式是使用最多的一中,它有如下特征:

∙调用服务方法后需要等待服务的消息返回,即便该方法返回void类型

∙相比Duplex来讲,这种模式强调的是客户端的被动接受,也就是说客户端接受到响应后,消息交换就结束了。

∙在这种模式下,服务端永远是服务端,客户端就是客户端,职责分明。

它是缺省的消息交换模式,设置OperationContract便可以设置为此种消息交换模式

[OperationContrac]

voidTest(intintVal);

注意,尽管Test方法返回为void,但Server也会生成reply响应并发送给client.有来有往是这种模式的特征。

 

Duplex

这种交换模式比起上面两种,比较复杂,它和request/reply模式类似,也是有来有往,但处理过程却比request/reply要复杂,因为它可以在处理完请求之后,通过请求客户端中的回调进行响应操作,这种模式的图示为:

注意,这种方式和request/reply方式的图示也很类似,当二者存在着至关重要的不同,它在客户端也有监听节点,在callback的时候,服务器和客户端的角色会进行交换,服务端此时成了严格意义上的客户端,而客户端此时能接受服务端的callback请求,所以成为了服务端。

呵呵,辩证法,都拗口死了,当事实就是这种,就像对与错一样,会相互转换,失败是成功之母,而成功是失败之源。

废话少说,Duplex的特征主要包括

∙消息交换过程中,服务端和客户端角色会发生调换

∙服务端处理完请求后,返回给客户端的不是reply,而是callback请求

五WCF中的3中对象实例模式

PerCall

PerCall模式工作流程如下

∙客户端创建代理对象(Proxy)

∙客户端调用代理对象的一个契约操作,代理对象将其传递给服务宿主程序。

∙宿主应用程序创建一新的服务契约对象,并且执行请求操作

∙在执行完请求操作后,如果要求有应答,那么服务契约会给代理对象一个应答,然后销毁自己(如果实现了IDisposable,则调用Dispose())。

PerSession

PerSession模式工作的流程如下:

∙客户端创建代理对象(Proxy)

∙客户端第一次调用代理对象的一个契约操作,代理对象将其调用请求传递给服务宿主

∙宿主程序创建新的服务对象,并执行请求操作,如果有必要,返回客户端应答

∙客户端再次发出调用操作的请求,宿主会先判断是否已有建立好的会话,如果存在,则不需要再创建新的服务对象,直接使用老对象即可。

∙在时间达到指定要求或者因一些特殊原因,会话会过期,此时服务对象销毁。

Single

Single模式工作流程如下:

∙服务端启动,同时创建服务对象

∙客户端通过代理调用契约操作

∙第一步中创建的服务对象接受请求,并执行操作,进行必要的应答

∙第一步创建的服务对象将一直保留

∙服务关闭,第一步创建的对象销毁

各种实例模式的应用场合?

PerCall

在传统模式C/S模式的应用程序中,通常情况下存在这样的问题:

客户端请求服务端之后,服务端并不是马上对处理客户端请求时需要的资源进行释放,服务端往往自作多情的认为客户端一定是个老主顾,会时不时来消费一番。

可他却没想到,有的时候,客户端是个昧良心的家伙,就算服务端再怎么献殷勤,客户端也不买账。

而对于一些非常珍贵的资源,比如数据库连接,文件,图像,通讯端口等。

服务这种做法往往会使这些资源长期被不来消费的客户端空闲占用,当有新的请求真正要用使用他们的时候,却因为资源耗尽而无法处理。

这样对服务端就得不偿失了,而PerCall就是对上面提到问题的一种解决方案。

它采用类似快餐式的经营方式,当一个请求操作来到的时候,再创建服务对象,申请必要资源,而当操作完毕之后,立即销毁对象并释放资源,留给下一个请求。

这就可能大大提高服务端的吞吐能力。

而且WCF中默认的实例创建模式就是这种。

PerSession

正如上面对PerCall的描述所说,PerSession与传统的C/S模式应用程序非常相似,它能在服务端和客户端维护状态,当一个服务对象创建之后不会马上销毁,而是等待客户端再次来消费它,那这种的坏处也说过了,可能会浪费宝贵的服务资源,可它也是有好处的。

比如它能够保持连接和维护状态,这在要求有回调的情况下特别重要,因为如果服务端连哪个家伙点的菜都忘记了怎么为客人上菜呢?

还有一种情况,服务端操作不需要比较多的资源或者占用的资源也不宝贵的情况下,而却与客户端在不同的网络中,它们之间进行一次连接可费了老劲,这时也适用于此种实例模式。

Single

大家经常去理发吧?

去那大的理发店,里面的理发师这家伙这个多,你随便找个就能帮你料理了,可兄弟我比较穷酸,每次都去小区理发店,里面连洗头,在理发就1位师傅,小区人可不少,僧多饭少,你说咱进去得排队吧。

人家理发的时候,咱就得边上看着,得人家都整完了,嘿,咱就洗头,理发,吹风来个一条龙。

Single模式就像上面提到的小区理发店,人家从早晨一开业,理发师就给你准备好了,您也甭挑蹦捡。

伺候完你,他再伺候别人,为何要这么做?

其实道理也很简单,如果理发师不喝水,不吃饭,不用管食宿,不用工钱,不会唧唧歪歪,那理发店老板娘肯定请1万个过来。

可现实不是那样子的,是这些理发师都要吃喝拉撒睡,还要拿俸禄,就一个几十平米的小理发店,估计给老板娘卖了也不够他们的呢。

使用不同的实例模式,需要注意的有哪些?

∙对于PerCall模式,一定要记住,如果服务对象中的数据没有固化,并且不是静态变量,那它每次操作都会被重新初始化。

∙对于PerSession模式,第一要清楚有些Binding是不能用于此种模式的,具体什么可用,什么不能用,可以查阅。

另外,PerSession模式并不是代表状态会自动维护,那些被设置了IsTerminating=True的操作完成的时候,也会释放资源和销毁对象。

即使不是Ture,那如果客户端长时间不与服务端联系,达到服务端最大忍耐限度,服务端也会变心。

∙对于Single模式,既然例外就它老哥一个,就简单得多了,它能保持服务对象中的非静态全局变量。

但是特别要注意的是,如果在这种模式下的话,要特别注意线程安全的问题,让10个人同时让一个理发师傅来服务

根据不同的需求,WCF将实例模式分为PerCall,Single和PerSession三种方式。

通过设置服务行为的InstanceContextMode属性,来管理服务实例的生存周期,可以简化开发人员的工作。

我们只需要了解这三种实例模式的特性即可。

通常情况下,我建议服务采用PerCall模式,如果需要维持服务与客户端之间的会话,则可以采用PerSession模式。

只有在对性能和可伸缩性没有太大要求的情况下,才可以采用Single模式。

六WCF中的事务处理

如何在WCF中实现事务?

事务原本是一件难于实现的事情,可WCF总是能化腐朽为神奇,它能够通过简单的声明式编程方式,便可以实现分布式的事务,下面就来看下实现此目标的功臣:

 

1) TransactionFlowAttribute:

操作契约(OperationContractAttribute)的一个属性,它能够指示所属操作(Operation)的事务选项(TransactionFlowOption)。

2) TransactionFlowOption:

它是TransactionFlowAttribute构造函数中的参数,是一个枚举(enum),包括三个枚举项NotAllowed:

不允许事务,是缺省值;Allowed:

允许事务,意味着事务可有可无;Mandatory:

强制事务,表示事务是必须的。

3)TransactionAutoCompleteOnSessionClose:

它是操作行为(OperationBehaviorAttribute)的一个属性,用于标注事务完成之后,服务端实例是否自动释放,这个属性和服务对象实例模式紧密相关,使用的时候,应该着重小心,下面也会有说明。

4)TransactionIsolationLevel:

也是操作行为(OperationBehaviorAttribute)的一个属性,用于指示事务隔离方式(isolationlevel).包括5中选项:

Any,ReadUncommitted,ReadCommitted,RepeatableRead,Serializable,事务的隔离方式相关知识比较复杂,留作文章的第二点中将具体阐述

5)TransactionTimeout:

也是操作行为(OperationBehaviorAttribute)的一个属性,用于指示事务的超时时间,默认为TimeSpan.Zero,表示不会受超时时间的限制..:

:

OperationBehaviorAttribute:

也是操作行为(OperationBehaviorAttribute)的一个属性,用于指示分布式事务选项,如果设置为true,那么必须在事务范围(TransactionScorp)内。

 

通过上面几个属性的使用,我们便能够轻松的在WCF中实现事务以及分布式事务。

具体实现方式可以参考代码范例

谈谈事务隔离方式的相关知识

单纯的事务存在着下面三个问题

1)脏读:

简单的说就是事务一在某一时刻更改了数据,恰恰这个更改的数据被事务二读取,而事务一却最终失败,导致数据回滚,那事务二就是一个受骗者

2)非可重复性读取:

同一数据每次读取的结果都不一样就是非可重复读取。

比如事务一要读取的数据务二改变,这就是非可重复性读取

3)幻读:

很简单,比如事务一在查询数据中,事务二却插入了一个符合查询条件的数据,这样就造成新插入数据的幻读。

三种问题的解释可能比较难于理解,其实简单的说,脏读是读了别人正在更改的数据,而可重复读取是更改了别人正在读的数据,而幻读呢则是读了别人还未来得及插入,更改或者删除的数据,我想这样理解就简单多了。

针对上面不同的问题,可以设置事务的不同隔离方式来防止问题的发生,事务的隔离方式又包括

1) Any:

组件的隔离级别是从调用组件的隔离级别获得的。

如果组件是根组件,则隔离级别用于Serializable中。

2) ReadUncommitted:

读取未提交数据,该方式在读取数据时保持共享锁定以避免读取已修改的数据,但在事务结束前可以更改这些数据,这导致非可重复读取或幻读。

3)ReadCommitted:

读取提交数据,发出共享锁定并允许非独占方式的锁定。

该方式与读取未提交数据相相似,这种方式看似和读取未提交数据相似,但有一个区别,事务的只读锁在移到下一行的时候,会解锁,而

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > IT计算机 > 电脑基础知识

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2