现在的位置: 首页 > 综合 > 正文

WCF学习笔记Ⅲ

2012年02月09日 ⁄ 综合 ⁄ 共 13232字 ⁄ 字号 评论关闭

鸣谢:老徐的博客

    分布式开发简介                                       

  学习WCF是不是就不需要学习.Net RemotingASMXWSEMSMQ了?

 

  这个问题一直是很多开发者关注的问题.按照微软的说法,WCF是微软分布式应用程序开发的集大成者,学习WCF编程,就不需要了解其他的技术.这个说法有一定的道理.WCF的出现确实解决了很多问题,它整合了.Net平台下所有的和分布式系统有关的技术,例如.Net RemotingASMXWSEMSMQ。以通信(Communiation)范围而论,它可以跨进程、跨机器、跨子网、企业网乃至于 Internet;可以以ASP.NETEXEWPFWindows FormsNT ServiceCOM+作为宿主(Host)。开发人员可以构建跨平台、安全、可靠和支持事务处理的企业级互联应用解决方案

 

  可事实并非如此,首先,技术的更新换代没有那么迅速,我们接触的工作平台和技术文章不会因为WCF的出现而全部更新,其次作为一个开发人员,在实际开发过程要学习或者解决技术问题,必须知道其相关的概念,扎实的基础知识毕不可少.

 

  在本节我们就来了解一下MSMQ的基本概念和开发过程.我们先来了解一下什么是MSMQ:

 

    MSMQ                                             

      MSMQ全称MicroSoft Message Queue,微软消息队列,是在多个不同的应用之间实现相互通信的一种异步传输模式,相互通信的应用可以分布于同一台机器上,也可以分布于相连的网络空间中的任一位置。它的实现原理是:消息的发送者把自己想要发送的信息放入一个容器中(我们称之为Message),然后把它保存至一个系统公用空间的消息队列(Message Queue)中;本地或者是异地的消息接收程序再从该队列中取出发给它的消息进行处理.

 

  其中两个重要的概念。一个是消息Message ,一个是队列Queue

  消息Message是由通信的双方所需要传递的信息,它可以是各式各样的媒体,如文本、声音、图象等等。消息最终的理解方式,为消息传递的双方事先商定,这样做的好处是,一是相当于对数据进行了简单的加密,二则采用自己定义的格式可以节省通信的传递量。消息可以含有发送和接收者的标识,只有指定的用户才能看到回执。时间戳,便于接收方对某些与时间相关的应用进行处理。截止时间,指定时间内消息还未到达则作废。

 

  队列的类型主要包括一下几种:

  ①“公共队列”在整个消息队列网络中复制,并且有可能由网络连接的所有站点访问。
  ②“专用队列不在整个网络中发布。相反,它们仅在所驻留的本地计算机上可用。专用队列只能由知道队列的完整路径名或标签的应用程序访问。
  ③“管理队列包含确认在给定消息队列网络中发送的消息回执的消息。指定希望 MessageQueue 组件使用的管理队列(如果有的话)。
  ④ “响应队列包含目标应用程序接收到消息时返回给发送应用程序的响应消息。指定希望 MessageQueue 组件使用的响应队列(如果有的话)。

 

     消息队列Queue是发送和接收消息的公用存储空间,它可以存在于内存中或者是物理文件中。消息可以以两种方式发送,即快递方式(express)和可恢复模式(recoverable,它们的区别在于,快递方式为了消息放置于内存中,可恢复模式放于物理磁盘上(详细参见MSDN).

 

     了解到消息队列MSMQ相关的基本概念以后,我们知道它的

  优点:稳定、消息优先级、脱机能力以及安全性,有保障的消息传递和执行许多业务处理的可靠的防故障机制。

  缺点:MSMQ不适合于Client需要Server端实时交互情况.大量请求时候,响应延迟.

 

 .NET Remoting                                        

  .Net Remoting技术,我们可以将其看作是一种分布式处理方式。作为应用程序之间通信的一种机制,.Net RemotingMSMQ消息队列不同,它不支持离线脱机消息,另外只适合.Net平台间程序的通信.从微软的产品角度来看,可以说Remoting就是分布式组件DCOM的一种升级,它改善了很多功能,并极好的融合到.Net平台下。.NET Remoting 提供了一种允许对象通过应用程序域与另一对象进行交互的框架。这也正是我们使用Remoting的原因。为什么呢?在Windows操作系统中,是将应用程序分离为单独的进程。这个进程形成了应用程序代码和数据周围的一道边界。如果不采用进程间通信IPCInternet Process Connection)机制,则在一个进程中执行的代码就不能访问另一进程。这是一种操作系统对应用程序的保护机制。然而在某些情况下,我们需要跨过应用程序域,与另外的应用程序域进行通信,即穿越边界(参考MSDN)

.Net Remoting的通信架构如下图.

  

我们可以通过上图简单理解一下.Net Remoting的通信框架,而现在来介绍一下其中涉及到的几个比较重要的概念:

     1.通道(channel),

.Net Remoting中是通过通道(chanel)来实现两个应用程序域之间对象的通信的。首先,客户端通过Remoting,访问通道以获得服务端对象,再通过代理解析为客户端对象。这就提供一种可能性,即以服务的方式来发布服务器对象。远程对象代码可以运行在服务器上(如服务器激活的对象和客户端激活的对象),然后客户端再通过Remoting连接服务器,获得该服务对象并通过序列化在客户端运行。

 

     通道(channel)4. 很多资料上说有2-3.应该有4.

     (1)HttpChannel。在将远程对象驻留在 ASP.NET 中时,可以使用此通道。此通道使用 HTTP 协议在客户端和服务器之间发送消息。可以使用HTTP协议中的加密机制.需要主机名字和端口号.
   (2)TcpChannel。在将远程对象驻留在  操作系统服务或其他可执行文件中时,此通道使用 TCP 套接字在客户端和服务器之间发送消息。同样需要提供主机名字和端口号.不提供任何内置的安全功能。

    (3)IPCChanel。进程间通道,只使用同一个系统内,进程之见的通信.不需要需要主机名字和端口号.
  (4)自定义通道 。自定义的传输通道可以使用任何基本的传输协议UDP\SMTP\IPX\消息排队等机制进行通信.用户可以根据需要自定义方式协议,因此.Net Remoting相对其他机制更加的灵活。不提供任何内置的安全功能。

 

     2.远程对象(Obeject)

  在Remoting中要传递的对象,设计者除了需要了解通道的类型和端口号之外,无需再了解数据包的格式。但必须注意的是,客户端在获取服务器端对象时,并不是获得实际的服务端对象,而是通过代理获得它的引用。远程对象要继承自MarshalByRefObject,这个可以使远程对象在remoting应用通信中使用,支持对象的跨域边界访问.

 

     3.激活方式

  (1)服务器端激活,又叫做知名WellKnown方式,是因为服务器应用程序在激活对象实例之前会在一个众所周知的统一资源标识符(URI)上来发布这个类型。然后该服务器进程会为此类型配置一个WellKnown对象,并根据指定的端口或地址来发布对象。服务器端激活又分为SingleTon模式和SingleCall模式两种。SingleTon模式:此为有状态模式。如果设置为SingleTon激活方式,则Remoting将为所有客户端建立同一个对象实例。SingleCall模式:SingleCall是一种无状态模式。一旦设置为SingleCall模式,则当客户端调用远程对象的方法时, Remoting会为每一个客户端建立一个远程对象实例,至于对象实例的销毁则是由GC自动管理的。

  (2)客户端激活。与WellKnown模式不同, Remoting在激活每个对象实例的时候,会给每个客户端激活的类型指派一个URI。客户端激活模式一旦获得客户端的请求,将为每一个客户端都建立一个实例引用。SingleCall模式和客户端激活模式是有区别的:首先,对象实例创建的时间不一样。客户端激活方式是客户一旦发出调用的请求,就实例化;而SingleCall则是要等到调用对象方法时再创建。其次,SingleCall模式激活的对象是无状态的,对象生命期的管理是由GC管理的,而客户端激活的对象则有状态,其生命周期可自定义。其三,两种激活模式在服务器端和客户端实现的方法不一样。尤其是在客户端,SingleCall模式是由 GetObject()来激活,它调用对象默认的构造函数。而客户端激活模式,则通过CreateInstance()来激活,它可以传递参数,所以可以调用自定义的构造函数来创建实例。(详细参考MSDN)
     (3)代理Proxy,客户端访问的不能直接访问远程对象,它是通过代理来访问代理上的方法.代理对象又分为透明代理和真实代理,区别是,在透明代理上,客户通过Invoke调用的是远程对象上真实代理的方法.然后把消息再传递给通道.

RemoteObject也就是我们远程要访问的对象.首先定义一个Class,继承MarshalByRefObject,可以使用在remoting应用中,支持对象的跨域边界访问.

namespace RemoteObject
{
    //创建远程对象.继承MarshalByRefObject,可以使用在remoting应用中,支持对象的跨域边界访问
    public class MyRemoteObject : MarshalByRefObject//访问远程对象需要通过代理
    {
        //简单的例子,实现加法功能的方法AddForTcpTest,这个远程对象可以实现封装业务逻辑或者数据访问等操作。
        public int AddForTcpTest(int a, int b)
        { return a + b; }

        //实现减法功能的方法MinusForHttpTest,测试HTTP通道。
        public int MinusForHttpTest(int a, int b)
        { return a - b; }

        //实现乘法功能的方法MultipleForIpcTest,测试Ipc通道
        public int MultipleForIpcTest(int a, int b)
        { return a * b; }
    } 
}
//对象分别定义了3种方法,目的是为了测试3种不同的通道方式的效果. 

NetRemotingHost: 服务端注册通道,以便进程间通信,我们这里注册了三种通道,

分别是HttpChanel\TcpChanel\IPCChanel

 

namespace NetRemotingHost
{
    class NetRemotingHost
    {
        //创建宿主应用程序
        static void Main(string[] args)
        {
            //////////////////////////////////////创建三种通道/////////////////////////////////////////////////
            ///创建Tcp通道,使用端口
            TcpChannel chanTcp = new TcpChannel(10001);
            ///创建Http通道,使用端口
            HttpChannel chanHttp = new HttpChannel(10002);
            ///创建IPC通道,使用端口,IPC只适合同系统内进程的通信,所以不需要设置端口和主机名
            IpcChannel chanIPC = new IpcChannel("FrankTestIpc");

            //////////////////////////////////////注册通道//////////////////////////////////////////////////
            ///注册TCP通道
            ChannelServices.RegisterChannel(chanTcp);
            ///注册HTTP通道
            ChannelServices.RegisterChannel(chanHttp);
            ///注册IPC通道
            ChannelServices.RegisterChannel(chanIPC);

            ////////////////////////////////////////打印通道/////////////////////////////////////////////////
            // 打印TCP通道的名称.
            Console.WriteLine("The name of the TCPChannel is {0}.",chanTcp.ChannelName);
            // 打印TCP通道的优先级.
            Console.WriteLine("The priority of the TCPChannel is {0}.",chanTcp.ChannelPriority);
            // 打印Http通道的名称.
            Console.WriteLine("The name of the HttpChannel is {0}.",chanTcp.ChannelName);
            // 打印Http通道的优先级.
            Console.WriteLine("The priority of the HttpChannel is {0}.",chanTcp.ChannelPriority);
            // 打印IPC通道的名称.
            Console.WriteLine("The name of the IpcChannel is {0}.",chanTcp.ChannelName);
            // 打印IPC通道的优先级.
            Console.WriteLine("The priority of the IpcChannel is {0}.",chanTcp.ChannelPriority);

            ///////////////////////////////////////////注册对象/////////////////////////////////////////////////
            //注册对象MyRemoteObject到Net Remoting运行库
            //配置远程通信基础框架.第个参数是对象的URI,“RemoteObject.MyRemoteObject”,客户端URL一定要和这个匹配,不然会出现查找不到代理对象的异常
            RemotingConfiguration.RegisterWellKnownServiceType(typeof(RemoteObject.MyRemoteObject), "RemoteObject.MyRemoteObject", WellKnownObjectMode.Singleton);
            //远程对象激活方式是单件激活模式,每次调用共享一个对象,SingleCall激活模式会在每次调用的时候产生一个新对象
            //向信道暴露一个IPC远程对象.
            //RemotingConfiguration.RegisterWellKnownService(Type(typeof(RemoteObject), "RemoteObject.rem", System.Runtime.Remoting.WellKnownObjectMode.Singleton);

            ///////////////////For Debug/////////////////////////////////////////////////////////////////////////
            Console.WriteLine("Press any key to exit!");
            System.Console.ReadLine();
        }
    }
}


创建Tcp通道,使用端口10001, 创建Http通道,使用端口10002,创建IPC通道,使用端口10003,IPC只适合同系统内进程的通信,所以不需要设置端口和主机名.然后调用ChannelServices类的静态方法RegisterChannel进行注册.最后一步注册对象MyRemoteObjectNet Remoting运行库,同时要先配置远程通信基础框架.2个参数是对象的URIRemoteObject.MyRemoteObject,客户端URL一定要和这个匹配,不然会出现查找不到代理对象的异常.WellKnownObjectMode.Singleton);远程对象激活方式是单件激活模式,每次调用共享一个对象,SingleCall激活模式会在每次调用的时候产生一个新对象.

 

RemoteClient,客户端配置文件

<configuration>
<appSettings>
<add key="ServiceURLTcp" value="tcp://localhost:10001/RemoteObject.MyRemoteObject"/>
<add key="ServiceURLHttp" value="http://localhost:10002/RemoteObject.MyRemoteObject"/>
<add key="ServiceURLIpc" value="ipc://FrankTestIpc/RemoteObject.MyRemoteObject"/>
</appSettings>
  <system.runtime.remoting></system.runtime.remoting>
</configuration>

配置文件设置的是具体通道的URL信息.具体c#实现代码如下

namespace RemoteClient
{
    class MyClient//客户端
    {
        [STAThread]//主线程,建立客户端程序:注册通道,根据URL得到对象代理,使用代理调用远程对象
        static void Main(string[] args)
        {
            //为远程对象创建代理
            //代理的优势在于不仅可以跨域访问对象还可以跨进程,和系统,使用TCP通道
            try
            {
                ////
                MyRemoteObject proxyObjectTcp= (MyRemoteObject)Activator.GetObject(typeof(MyRemoteObject), System.Configuration.ConfigurationSettings.AppSettings["ServiceURLTcp"]);
                //通过代理访问对象的方法,输出结果
                Console.WriteLine
                   ("This call object by TcpChannel,100+200 = {0}", proxyObjectTcp.AddForTcpTest(100, 200));
                
                //////
               MyRemoteObject proxyObjectHttp= (MyRemoteObject)Activator.GetObject(typeof(MyRemoteObject), System.Configuration.ConfigurationSettings.AppSettings["ServiceURLHttp"]);
                //通过代理访问对象的方法,输出结果
                Console.WriteLine
                   ("This call object by HttpChannel,100-200 = {0}", proxyObjectHttp.MinusForHttpTest(100, 200));
                
                //// 注册一个远程对象的客户端代理.
                //System.Runtime.Remoting.WellKnownClientTypeEntry remoteType = new System.Runtime.Remoting.WellKnownClientTypeEntry(typeof(RemoteObject.MyRemoteObject), "ipc://FrankTestIpc/RemoteObject.MyRemoteObject");
                //System.Runtime.Remoting.RemotingConfiguration.RegisterWellKnownClientType(remoteType);//如果需要客户端和住进程通讯,要在客户端注册代理,方式和服务器端注册注册远程对象的代理相同

                MyRemoteObject proxyObjectIpc = (MyRemoteObject)Activator.GetObject(typeof(MyRemoteObject), System.Configuration.ConfigurationSettings.AppSettings["ServiceURLIpc"]);

                //通过代理访问对象的方法,输出结果
                Console.WriteLine
                    ("This call object by IpcChannel,100*200 = {0}", proxyObjectIpc.MultipleForIpcTest(100, 200));
            }
            catch (Exception e)
            { throw e; }
            finally 
            { }
            //For Debug
            Console.WriteLine("Press any key to exit!");
            Console.ReadLine();
        }
    }
}

 主进程通过配置获取远程对象的信息,为远程对象创建代理,代理的优势在于不仅可以跨域访问对象还可以跨进程,和系统,使用TCP通道,降低系统耦合性.最后客户端通过代理访问远程对象的方法,输出结果.首先要运行服务器端,其次是客户端,IDE使用的是Visual Studio 2005/2008.其次注意项目引用.

 

   Enterpise Services                                      

首先介绍的是:

一.基本概念

1.什么是COM+

     COM+的底层结构仍然以COM为基础,它不仅具备了COM的易于用户定制\可重用\简化开发的优点,同时又避免了COM实现方面的一些不足.把COMDCOMMTS的编程模型结合起来,它通过操作系统的各种支持,使组件对象模型建立在应用层上,继承了它们的绝大多数特性,增加了新的功能。COM+的几个主要特性: 比如队列服务、负载平衡、内存数据库、事件服务等。它更加注重于分布式网络应用的设计和实现(参考msdn)。   

  

2.什么是Enterpise Services

     Enterprise Services微软应用程序服务器技术的别称.Net Enterprise Services提供了可以在.Net 组件中使用的COM+服务.因为它也是基于以前的COM+技术,在.NET平台上开发.NET组件,使用Enterprise Services可以将.NET组件并进行封装为COM对象,这样.NET组件就可以使用COM+服务了..NET做为新一代的开发平台,实现了COM组件相互之间的调用,继承了向前兼容的优良传统.同样COM+可以调用.Net 组件,会给COM+服务带来一些扩展.

 

二.Enterprise Services中重要的类及特性

     Enterprise Servicesg工作在三层架构中的业务逻辑层或者数据访问层.由于基于COM+技术,所以它也可以通过Micro Application Center Server实现负载均衡.下面我们来介绍一下Enterprise Services里几个重要的概念.

 

  (1)上下文(context又翻译为环境)所有的COM+服务都是通过上下文(context又翻译为环境)实现的,上下文是进程里提供给对象运行时服务的空间.如果一个对象调用另外一个上下文里的对象,这个方法调用会被代理截取,COM运行时就可以利用代理来预处理或者迟处理请求并执行相关的服务代码.过程如图1

 

图1COM+服务与上下文

  (2)自动事务处理(automatic transaction)

     Enterprise Services里最常用的特性就是自动事务处理,这个一般在类的星星[Transaction]使用这个特性,就不需要再编写复杂的代码来显示执行事务准备工作,如对象的传递等,设置这个属性后,上下文环境会在后台进行设置.具体的设置在TransactionOption类的属性里选择.Required表示共享一个事务,必要的时候创建一个新事务.

  (3)对象池(Obejct pooling):

     这个属性可以设置是需要对象池和对象池的大小.主要是考虑到对象的创建和销毁会占用更多的资源.使用对象池会事先创建对象,客户的请求到来就直接到对象池里查找需要的对象,直接响应请求,可以提高服务的性能,节约时间.

  (4)ServicedComponent

     是所有使用COM+服务类的基类.ServicedComponent继承自ContextBoundObject类.ContextBoundObject继承自MarshalByRefObject.这个类在上一节的.Net Remoting介绍过,使支持remoting的程序可以跨程序域边界的访问对象.

     另外还有分布式事务处理的等概念,Enterprise Services里是使用DTC来实现的.

 

 Web Service                                        

  1.Web Service的基本概念

  Web Services 是设计支持机器与机器的通过网络互操作的一种软件系统(W3C的定义).是一组可以通过网络调用的应用程序API. Web Services 是应用程序组件 使用开放协议进行通信 ,独立的(self-contained)并可自我描述 ,可通过使用UDDI来发现 ,可被其他应用程序使用的功能.

 

     Web services 平台主要涉及到XML \ SOAP\ WSDL\ UDDI四个主要元素.

     (1)XML :XMLEXtensible Markup Language的缩写,XML是一种类似于HTML的标记语言,XML是用来描述数据的,XML的标记不是在XML中预定义的,你必须定义自己的标记 XML使用文档类型定义(DTD)或者模式(Schema)来描述数据 ,XML使用DTD或者Schema后就是自描述的语言.
     (2)SOAP :SOAP(Simple Object Access Protocol)简单对象访问协议是在分散或分布式的环境中交换信息的简单的协议,是一个基于XML的协议。它包括四个部分:SOAP封装(envelop),封装定义了一个描述消息中的内容是什么,是谁发送的,谁应当接受并处理它以及如何处理它们的框架;SOAP编码规则(encoding rules),用于表示应用程序需要使用的数据类型的实例SOAP RPC表示(RPC representation),表示远程过程调用和应答的协定;SOAP绑定(binding),使用底层协议交换信息。 
     (3)WSDL: Web services 描述语言,它的主要构成要素有五个.Types: 定义WSDL定义中所用到的数据类型,即XML Schema Types;Message : 对一组消息的输入和输出参数的定义;portType : 定义Web服务的操作;Binding :描述特定服务接口的协议、数据格式、安全性和其它属性.Services : 制定特定服务的URL和提供的调用接口,包含一组端口元素.  这样Web services 就实现了自我描述.

     (4) UDDI :Universal Description Discovery and Integration即统一描述、发现和集成协议。UDDI同时也是Web服务集成的一个体系框架。它包含了服务描述与发现的标准规范。UDDI规范利用了W3CInternet工程任务组织(IETF)的很多标准作为其实现基础,比如扩展标注语言(XML),HTTP和域名服务(DNS)这些协议。有了它我们的Web services 就可以注册到UDDI中心.供其客户查找使用.

 

     Web services 一般分为4:

  (1)面向业务的服务(Business-Oriented Web Service): 该类服务针对的是那些面向企业应用服务;

  (2)面向客户的服务(Consumer-Oriented Web Service): 此类服务针对的是那些原先的B2C的网站的改造,比如我们完全就可以在个人理财桌面系统中集成(调用)Internet上的股票价格查询Web服务、机票预定Web服务等,使得个人理财应用的自动化程度更高。

  (3)面向设备的服务(Device-Oriented Web Service): 此类服务的使用终端一般是手持设备和日用家电,比如PalmPocketPC、手机等。。

  (4)面向系统的服务(System-Oriented Web Service): 一些传统意义上的系统服务,比如用户权限认证,系统监控等,譬如跨国企业的所有在线服务可以使用同一个用户权限认证Web服务。

 

 

 2.Web Service优势和缺点

   我们先来了解以前平台的缺点.中间件平台(RMI, Jini, CORBA, DCOM 等等)提供了强大的服务实现手段,但是,这些系统有一个共同的缺陷,那就是它们无法扩展到互联网上:它们要求服务客户端与系统提供的服务本身之间必须进行紧密耦合,即要求一个同类基本结构。不支持跨平台的信息交换.而对比后我们就发现

Web Service 的优点:

  (1)跨平台:WebService完全基于XML(可扩展标记语言)、XSDXMLSchema)等独立于平台、独立于软件供应商的标准;

  (2)自描述:Web Service 使用WSDL标准语言进行自我描述,包括服务的方法\参数\类型\返回值等相关的完备信息.

  (3)模块化:Web Service 是应用程序组件,我们可以使用任何开发平台来开发,并且按照模块进行封装.

  (4)跨放火墙:Web Service 使用http协议进行通信,可以穿越防火墙.

Web Service 的缺点

  (1)效率低下,不适合做单应用系统的开发.

(2)安全问题,Web Service的没有自身的安全机制,必须借助http协议或IIS等宿主程序实现信息安全加密

 

3.Web Service使用的场合

     那么什么时候应该使用Web Service,从上面的总结我们可以看出.使用Web Service能够带来利益的情况.

(1)跨防火墙的通信
(2)应用程序集成,主要是指企业应用系统的集成.
(3)B2B的集成,主要是指电子商务平台的集成.
(4)软件和数据重用,软件重用是一个很大的主题,重用的形式很多,重用的程度有大有小。最基本的形式是源代码模块或者类一级的重用,另一种形式是二进制形式的组件重用。
     有一些情况,不适合使用WebService

  (1)单机应用程序

  单机应用程序如office,可以直接调用系统WindowsAPI\COM进行编程,实现功能效率更高.

(2)局域网的同构应用程序
      例如在局域网里,使用COM+.NET Remoting进行通信,会获得更高的效率.我们不需要使用WebService.

 

4.Web Service安全问题

     安全问题是开发和部署Web service涉及最多的问题,主要还是防止重要信息的泄露.包括非法请求和恶意攻击.网络常见的安全问题Web service都会面临.

     Web service的部署方式一般包括3:

(1)IIS托管.这个最简单,直接借助IIS,发布方式类网站发布.好处是它可以使用所有的ASP.Net的认证授权机制

(2)Console.可以驻留在控制台程序中.

(3)Windows Service.驻留在系统服务中.

 

 WSE3.0                                          

WSE3.0

抱歉!评论已关闭.