• WCF基础知识问与答


    学习WCF已有近两年的时间,其间又翻译了Juval的大作《Programming WCF Services》,我仍然觉得WCF还有更多的内容值得探索与挖掘。学得越多,反而越发觉得自己所知太少,直到现在,我也认为自己不过是初窥WCF的门径而已。

      “学以致用”,如果仅仅是希望能够在项目中合理地应用WCF,那么对于程序员而言,可以有两种选择,一种是“知其然而不知其所以然”,只要掌握了WCF的基础知识,那么对于一般的应用就足够了。要做到这一点就很容易了,微软秉承了一贯的方式,将WCF这门技术优雅地呈现给开发者,封装了复杂的实现逻辑,提供了易于调用的类库和相关的工具,使得开发者能够快速地完成WCF程序的开发。另外一种方式自然就是深度挖掘WCF的内部实现了,这是对WCF专家提出的要求。如果我们要应用WCF实现SOA解决方案,就会遭遇许多WCF的高级应用,如何合理、有效地应用WCF,并根据项目实际情况对WCF进行扩展,就成为了WCF专家必须解决的难题。

      因此,如果要学习WCF,你必须找准自己学习的动机与目标,然后合理地安排自己的学习进度表,这才是正确的学习方式。本文试图对WCF的一些基础概念作一些试探性的阐述与分析,并以问答的方式组织,希望能够部分解答一些希望学习WCF,但犹自徘徊在门外的开发者。

    1、WCF是什么?

      从WCF所处的位置来看,它是包含在.NET 3.0(也包括.NET 3.5)之中的。我们注意比较.NET 3.0与.NET 2.0,其实唯一的区别就是.NET 3.0包含了WCF、WPF、WF(或者还有CardSpace)而已。因此,我们认为WCF是.NET框架的一部分,似乎并不为过。尤为关键的是,WCF并不能脱离.NET框架而单独存在(但非WCF客户端可以调用WCF服务),因此,虽然WCF是微软用以应对SOA解决方案的开发需求而专门推出的,但它并不是例如Spring、Struts那样的框架,也不是像EJB那样的容器或者服务器。微软真正符合SOA企业应用服务器角色的,我想应该是Biztalk Server。

      严格的说,WCF就是专门用于服务定制、发布与运行以及消息传递和处理的一组专门类的集合,也就是所谓的“类库”。这些类通过一定方式被组织起来,共同协作,并为开发者提供了一个统一的编程模式。WCF之所以特殊,是在于它所应对的场景与普通的.NET类库不同,它主要用于处理进程间乃至于机器之间消息的传递与处理,同时它引入了SOA的设计思想,以服务的方式公布并运行,以方便客户端跨进程和机器对服务进行调用。实际上,WCF就是微软对于分布式处理的编程技术的集大成者,它将DCOM、Remoting、Web Service、WSE、MSMQ集成在一起,从而降低了分布式系统开发者的学习曲线,并统一了开发标准。

      WCF与其它类库还有不同的地方,则在于WCF充分地体现了运行时环境的概念。对于早期使用WCF的开发人员而言,就可能知道如果在.NET 2.0下要开发WCF,还需要专门下载一个Runtime Component 3.0版,其中就包含了WCF、WF等内容。在.NET中一贯存在所谓“宿主”的概念,整个.NET Framework(或者说是CLR)就可以认为是一个大的宿主,就像Java的虚拟机一样。由于WCF对服务有着专门的需求,对于服务端,需要发布和运行服务;对于客户端,则需要调用服务;因而对于开发者,就需要编写定义、发布、运行、调用服务的相关代码。而服务就只能运行在特定的宿主上,这些宿主可以是控制台应用程序进程、Windows或Web应用程序进程,也可以是Windows服务进程,或者为最常用的IIS宿主。在宿主内部,则封装了通道堆栈,其中又包含了对协议、编码、消息传输、代理的处理。而在通道层的顶部,还提供了一个高级运行时,以针对应用程序的开发人员。

      因而,我们可以这样认为,WCF是.NET Framework 3.x的一部分,它包含了用于服务定制、发布与运行以及消息传递和处理的运行时环境以及相关类的集合,它提供了在Windows平台下开发和部署服务的SDK。大致组成如下图所示:

    wcfbasic01.gif 


    2、WCF是怎样运行的?

      如果从宏观的角度来分析WCF的运行机制,它的实现并不复杂。WCF的体系架构是基于一种拦截机制来实现的,负责传递和拦截消息的组件为通道,在客户端发出对服务端服务的调用时,首先会通过一个服务代理对象,将调用方提供的对象序列化到消息中,然后该消息则通过通道进行传递。通道不只是包括一个,而是多个通道对消息进行处理,包括传输、消息编码、管理会话、传播事务等,但最底层的通道总是传输通道。这些通道的构成形成了一个通道堆栈。由于对象已经被序列化,因而此时通道传递的消息可以跨进程或机器进行传递,利用传输通道传递到服务端。服务端的构成与客户端基本相似,仍然是通过通道栈中最底层的传输通道接收消息,然后解析消息编码,并一层层地往上传输。在服务端的通道栈之上,则是一个分发器(Dispatcher,或者说是调度器),它会首先对消息进行检查,然后选择一个客户端要调用的操作。在这个过程中,消息会被反序列化。

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

    wcfbasic02.gif 


      由于WCF通过通道的方式传递消息,整个通道同时担当了侦听器和拦截器的功能,它可以根据服务的定义,在方法执行的前或后执行不同的操作,例如事务、会话管理、安全等。这些操作在WCF中,大多数都可以以Attribute的方式应用到服务契约上,这样的实现方式,就类似于采用了AOP(面向服务编程)的方法为服务提供了大量的基础功能,有助于简化服务开发者的工作。

    3、为什么我们要选用WCF?
      在Windows平台下,尤其是在.NET平台下开发面向服务的应用程序,或者开发分布式系统,最佳选择就是WCF。为什么呢?原因就在于WCF涵盖了之前微软推出的所有用于分布式开发的技术,包括Remoting、Web Services、WSE、MSMQ等,并以一种统一的编程模式来实现。

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

    特性

    Web Service

    .NET Remoting

    Enterprise Services

    WSE

    MSMQ

    WCF

    具有互操作性的Web服务

    支持

     

     

     

     

    支持

    .NET.NET的通信

     

    支持

     

     

     

    支持

    分布式事务

     

     

    支持

     

     

    支持

    支持WS标准

     

     

     

    支持

     

    支持

    消息队列

     

     

     

     

    支持

    支持



      WCF同时也使得面向服务编程更加简单而统一了。如果采用旧有的技术,由于各种技术的编程模型完全不一致,使得程序的迁移非常的困难。例如,最初采用.NET Remoting技术开发的分布式系统,由于业务需求的变化,要求发布具有互操作性的Web服务,就需要重新定义服务。并且,客户端的调用方式也发生了变化,需要添加Web引用,通过UDDI去发现服务。

      采用WCF则不然。WCF引入了用通道,它封装了消息的通信细节,例如编码、事务处理、安全等,然后又通过引入绑定的概念,封装了通道的组成顺序与处理细节。最后,引入了独有的Endpoint元素,集成了地址、绑定和契约之间的“三位一体”,以最简单的方式定义和发布服务。

    4、WCF基础的技术要素有哪些?

      WCF的大部分功能都放在一个单独的程序集System.ServiceModel.dll中。WCF的几个最重要的技术元素包括:绑定、契约、端点。

      如前所述,绑定封装了通道的组成顺序与处理细节,它直接决定了WCF的通信方式,消息的编码方式,通道的协议,消息传递的可靠性以及安全等内容。通过使用绑定,我们就无需了解消息在WCF通道中的实现细节,从而简化程序员的开发。正是因为此,WCF为开发人员提供了多个内置绑定,基本上涵盖了WCF应用的大部分场景。以下是Aaron Skonnard在《WCF深度绑定》一文中列举的内置绑定:

    绑定类名称

    传输

    消息编码

    消息版本

    安全模式

    可靠消息传送

    事务流(默认情况下禁用)

    BasicHttpBinding

    HTTP

    文本

    SOAP 1.1

    不支持

    不支持

    WSHttpBinding

    HTTP

    文本

    SOAP 1.2 WS-Addressing 1.0

    消息

    禁用

    WS-AtomicTransactions

    WSDualHttpBinding

    HTTP

    文本

    SOAP 1.2 WS-Addressing 1.0

    消息

    启用

    WS-AtomicTransactions

    WSFederationHttpBinding

    HTTP

    文本

    SOAP 1.2 WS-Addressing 1.0

    消息

    禁用

    WS-AtomicTransactions

    NetTcpBinding

    TCP

    二进制

    SOAP 1.2

    传输

    禁用

    OleTransactions

    NetPeerTcpBinding

    P2P

    二进制

    SOAP 1.2

    传输

    不支持

    不支持

    NetNamedPipesBinding

    命名管道

    二进制

    SOAP 1.2

    传输

    不支持

    OleTransactions

    NetMsmqBinding

    MSMQ

    二进制

    SOAP 1.2

    消息

    不支持

    不支持

    MsmqIntegrationBinding

    MSMQ

    不支持(使用 WCF 之前的序列化格式)

    不支持

    传输

    不支持

    不支持

    CustomBinding

    您决定

    您决定

    您决定

    您决定

    您决定

    您决定


      每种绑定对应不同的传输协议、消息编码格式和版本以及安全、可靠性和事务模式。WCF也提供了扩展绑定的方式,例如通过CustomBinding或者定义派生与Binding的类。

      WCF的契约包括服务契约、数据契约和消息契约(特别的,还包括了错误契约,用于异常的处理)。其中服务契约为面向服务应用程序的核心,通过它可以定义服务。数据契约则为服务所要传递的数据。由于服务的调用需要跨进程或机器进行通信,就需要服务数据必须能够被序列化和反序列化。虽然.NET本身提供了数据的序列化功能,但WCF的数据契约更加符合服务数据的定义习惯。至于消息契约,则可以将服务数据定义为消息,包括XML文本格式、MTOM(消息传输优化机制)格式和二进制格式。

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

    figure-1.5.gif 


      Address是Endpoint的网络地址,它标记了消息发送的目的地。Binding描述的是如何发送消息,例如消息发送的传输协议(如TCP,HTTP),安全(如SSL,SOAP消息安全)。Contract则描述的是消息所包含的内容,以及消息的组织和操作方式,例如是单向,双向还是请求/响应方式。

      引入终结点可以说是WCF的一个伟大创举,通过它使得我们能够更加容易的发布和管理服务,尤其是发布和管理多个服务。每个服务必须至少拥有一个终结点,而客户端正是通过终结点知道服务的相关信息,例如地址、消息编码格式、传输协议以及服务的内容,然后在进行正确的调用。最特别的是,同一个服务可以定义多个终结点,每个终结点可以是不同的地址、不同的绑定方式,以便于满足多个客户端的不同需要。而对于服务的发布者而言,我们只需要管理终结点的配置,就可以完成对服务的管理,这也为服务的托管提供了便利。

    5、WCF主要包含哪些内容?

      Juval的《Programming WCF Services》一书基本已经涵盖了WCF技术的方方面面。概括来讲,主要包括绑定、服务契约、数据契约、消息传递、异常处理、实例模式、并发处理、事务处理、安全以及队列服务等。

      绑定属于WCF基本的技术要素,是WCF进行通信处理的基础。了解绑定的相关知识,有助于开发WCF应用程序。因为在不同的业务需求下,可能对通信方式、协议、消息编码等多个方面会有不同的要求。在配制、发布和运行服务时,都需要对绑定进行操作。因而,我们必须掌握WCF内置绑定的相关属性,熟悉绑定元素的相关配置。此外,在一些高级应用上,我们还要掌握自定义绑定的方式,了解在自定义绑定时,添加绑定元素的方式与顺序,了解Binding基类的相关属性和方法。以及与绑定配置相关的类。

      服务契约是WCF的主要处理对象,服务的定义和设置正是通过服务契约实现的。除了了解ServiceContract和OperationContract的基础应用之外,还需要比较WCF服务编程与普通的.NET编程之间的区别,例如服务的继承与多态是怎样实现的。最重要的是如何根据SOA的思想划分服务的边界,确定服务的粒度大小,这需要从系统的易用性、可扩展性、性能等多个方面进行权衡。

      服务契约中关于操作的定义要受到很多约束,其中最重要的就是对数据的处理,这也是WCF引入数据契约的目的。由于WCF的特殊性,因而我们需要了解一些特殊数据类型的序列化方式,例如泛型类型、集合、DataSet等。

      约束服务操作定义的还包括对异常的处理,WCF对异常有一套特殊的处理方式,可以根据实际的情况,确定异常消息是否需要进行通信,以及出现异常时,是否要求停止服务实例,或继续维持会话。

      WCF为消息传递提供了非常大的灵活性。它提供了专门的Message类以及相关的读写器,例如XmlDictionaryReader和XmlDictionaryWriter等对消息进行读写,这其中包含了对消息版本、编码格式、消息标头和正文等的操作。同时,WCF还提供了消息与方法之间的映射。在提供系统的互操作性时,了解WCF的消息传递方式很有必要。

      根据不同的需求,WCF将实例模式分为PerCall,Single和PerSession三种方式。通过设置服务行为的InstanceContextMode属性,来管理服务实例的生存周期,可以简化开发人员的工作。我们只需要了解这三种实例模式的特性即可。通常情况下,我建议服务采用PerCall模式,如果需要维持服务与客户端之间的会话,则可以采用PerSession模式。只有在对性能和可伸缩性没有太大要求的情况下,才可以采用Single模式。

      关于事务处理、并发处理以及安全,主要都是通过相关的服务行为进行设置和管理。这些内容都是WCF高级应用所必需掌握的内容,尤其对于开发企业级应用系统而言。至于队列服务,主要是利用了消息队列,以实现系统可以脱机访问服务,并保持服务状态的同步。

    6、WCF主用适用于哪些应用场景?

      WCF本身就是微软为了应对SOA战略所推出的一套基于.NET Framework下的SDK。当我们在Windows平台下,基于.NET框架开发一套系统,同时要求这套系统需要与其它平台例如WebLogic、WebSphere或者JBoss进行交互时,就需要采用WCF技术了。这是因为WCF的互操作性所决定的。

      目前来看,WCF在企业应用中还没有得到大量的应用,但随着开发者对.NET 3.x的深入了解,WCF会逐渐深入人心。由于WCF集成了.NET编程开发的习惯,对于.NET开发人员而言,就大大地降低了学习曲线,此外,WCF保留了对旧有技术包括Web Service、.NET Remoting、MSMQ、WSE的支持,同时对于旧有技术到WCF的迁移也提供了非常好的解决方案。因而,如果.NET人员若要应用SOA的解决方案,那么WCF无疑就是最佳选择。单以开发而论,利用WCF定义服务、公开服务以及运行服务,利用WF实现工作流的设计、运行与管理、利用WPF作为具有丰富表现的富客户端,或者通过AJAX+SliverLight开发调用WCF服务的客户端,以及通过CardSpace完成对服务安全的设置与管理,就足以实施一整套的SOA解决方案。同时,WCF还可以结合Biztalk以及Sharepoint,使得SDK能够搭载于应用服务器之上,更大程度地满足企业应用的需要。

      除了实施SOA解决方案之外,WCF对于开发分布式系统而言,也是得天独厚的。当我们的应用系统需要在多个服务器上运行不同服务,以支撑大量的访问负荷、大数据量处理、数据挖掘等工作时,就可以利用WCF开发不同的服务,然后托管在不同的服务器上,此时,整个系统就可以有效地利用服务器资源,减轻系统负荷。

    参考:
    1、Juval Lowy著,张逸、徐宁译《WCF服务编程》
    2、Aaron Skonnard,《WCF深度绑定》
    3、Aaron Skonnard,《使用自定义行为扩展WCF》
    4、Boris Lublinsky,《实现一个.NET Web Services服务注册中心》

  • 相关阅读:
    BEGIN2 序列求和
    BEGIN2 序列求和
    《算法竞赛入门经典》 习题45 IP网络(IP Networks,ACM、ICPC NEERC 2005,UVa1590)
    C#中char空值的几种表示方式
    C#中char空值的几种表示方式
    C#中() =>是什么意思
    C#中() =>是什么意思
    C# Task 暂停与取消
    C# Task 暂停与取消
    C# WinForm设置透明
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/1805060.html
Copyright © 2020-2023  润新知