一、Remoting基础
一种分布式处理方式。从微软的产品角度来看,可以说Remoting就是DCOM的一种升级,它改善了很多功能,并极好的融合到.Net平台下。
Remoting 提供了一种允许对象通过应用程序域与另一对象进行交互的框架。正是我们使用Remoting的原因。在Windows操作系统中,是将应用程序分离为单独的进程。这个进程形成了应用程序代码和数据周围的一道边界。如果不采用进程间通信(RPC)机制,则在一个进程中执行的代码就不能访问另一进程。然而在某些情况下,我们需要跨过应用程序域,与另外的应用程序域进行通信,即穿越边界。在Remoting中是通过通道(channel)来实现两个应用程序域之间对象的通信的。
1、Remoting的两种通道
Remoting的通道主要有两种:Tcp和Http。
2、远程对象的激活方式
在访问远程类型的一个对象实例之前,必须通过一个名为Activation的进程创建它并进行初始化。这种客户端通过通道来创建远程对象,称为对象的激活。在Remoting中,远程对象的激活分为两大类:服务器端激活和客户端激活。
(1) 服务器端激活,又叫做WellKnow方式,很多又翻译为知名对象。为什么称为知名对象激活模式呢?是因为服务器应用程序在激活对象实例之前会在一个众所周知的统一资源标识符(URI)上来发布这个类型。服务器端激活又分为SingleTon模式和SingleCall模式两种
SingleTon模式:此为有状态模式。Remoting将为所有客户端建立同一个对象实例。当对象处于活动状态时,SingleTon实例会处理所有后来的客户端访问请求,SingleTon实例将在方法调用中一直维持其状态。举例来说,如果一个远程对象有一个累加方法(i=0;++i),被多个客户端(例如两个)调用。如果设置为SingleTon方式,则第一个客户获得值为1,第二个客户获得值为2,因为他们获得的对象实例是相同的。
SingleCall模式:SingleCall是一种无状态模式。一旦设置为SingleCall模式,则当客户端调用远程对象的方法时,Remoting会为每一个客户端建立一个远程对象实例,至于对象实例的销毁则是由GC自动管理的。同上一个例子而言,则访问远程对象的两个客户获得的都是1。
两种模式如何选取?
首先说下什么是有状态对象和无状态对象?有状态就是有数据存储功能,购物车就是很好的例子,买一件东西放进购物车,可以再次购买或者删减。无状态就是一次操作,不保存数据。举例说明,比如有个Class下面有两个方法, methodA(), methodB(), 和一个数据成员String data. 如果是Stateful, 那么methodA() 方法调用后, methodA()方法把data值改为"A", 那么methodB()在调用时, 就会得到data的值是"A". 如果是 Stateless, 那么methodA()中不论你怎么改变data的值, methodB()中取到的永远是data = "". 再说下什么是线程安全?“线程安全”由多线程对共享资源的访问引起。如果调用某个接口时需要我们自己采取同步措施来保护该接口访问的共享资源,则这样的接口不是线程安全的.怎样才能设计出线程安全的类或者接口呢?如果接口中访问的数据都属于私有数据,那么这样的接口是线程安全的.或者几个接口对共享数据都是只读操作,那么这样的接口也是线程安全的.如果多个接口之间有共享数据,而且有读有写的话,如果设计者自己采取了同步措施,调用者不需要考虑数据同步问题,则这样的接口是线程安全的。
SingleTon模式就是有状态的,线程安全的。SingleCall不是。但是在并发情况下, 用Singleton访问Remote Object的接口(Method), Remoting会自动给所调用的接口(Method)加锁作同步机制, 就是说所有的并发调用会被串行化, 假如一个接口(Method) Foo() 需要执行2秒钟, 有100个.Net Remoting Client访问这个Foo() Method, 点被(运气差)点那个Client要在200秒之后才能得到结果, 而对Singlecall, 如果忽略cpu线程切换的时间(至少比秒低2个数量级), 只要2秒, 100个线程一起在2秒内干完了活。
(2) 客户端激活。与WellKnown模式不同,Remoting在激活每个对象实例的时候,会给每个客户端激活的类型指派一个URI。客户端激活模式一旦获得客户端的请求,将为每一个客户端都建立一个实例引用。SingleCall模式和客户端激活模式是有区别的:首先,对象实例创建的时间不一样。客户端激活方式是客户一旦发出调用的请求,就实例化;而SingleCall则是要等到调用对象方法时再创建。其次,SingleCall模式激活的对象是无状态的,对象生命期的管理是由GC管理的,而客户端激活的对象则有状态,其生命周期可自定义。其三,两种激活模式在服务器端和客户端实现的方法不一样。尤其是在客户端,SingleCall模式是由GetObject()来激活,它调用对象默认的构造函数。而客户端激活模式,则通过CreateInstance()来激活,它可以传递参数,所以可以调用自定义的构造函数来创建实例。
分离实现:有时候我们居于安全性或其他方面考虑,不适宜在客户端部署具体服务程序集,那么有两种做法
(1) 服务器激活。使用接口分离,只在客户端部署服务程序集接口和公共实体程序集
(2) 客户端激活。使用接口分离程序集的方式无法创建客户激活对象,因为客户端使用Activator.CreateInstance()方法创建对象。于是使用“空类”的方法,客户端与服务器部署相同名称,命名空间的程序集,只是客户端的程序集的方法不包含实现代码(例如直接throw exception)。
二、远程对象激活与租用周期
参考文章
http://www.cnblogs.com/wayfarer/archive/2004/07/30/28723.aspx
http://www.cnblogs.com/wayfarer/archive/2004/08/05/30437.html