在上文WCF从理论到实践:事件广播 中,已经实现了完整的WCF服务端和客户端示例,其中也涉及到了远程对象实例创建的问题。本文就进一步的探索WCF中远程对象的创建模式和其生命周期
本文出发点:
通过阅读本文,您可以了解以下知识:
- WCF中有哪几种对象实例模式?
- 几种实例模式下对象的生命周期?
- 各种实例模式的应用场合?
- 使用不同的实例模式,需要注意的有哪些?
- 代码不骗人,用一个小范例来看看不同实例模式的区别?
本文适合的读者
本文适合有一定WCF基础知识的初学者
WCF中有哪几种对象实例创建模式?
WCF中有三种实例模式,这在.Net Framework中已经用InstanceContextMode枚举具体的列了出来,它们分别为:PerSession,PerCall,Single
几种实例模式下对象的生命周期?
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是不能用于此种模式的,具体什么可用,什么不能用,可以查阅http://www.cnblogs.com/jillzhang/archive/2008/02/03/1063406.html 。另外,PerSession模式并不是代表状态会自动维护,那些被设置了IsTerminating=True的操作完成的时候,也会释放资源和销毁对象。即使不是Ture,那如果客户端长时间不与服务端联系,达到服务端最大忍耐限度,服务端也会变心。
- 对于Single模式,既然例外就它老哥一个,就简单得多了,它能保持服务对象中的非静态全局变量。但是特别要注意的是,如果在这种模式下的话,要特别注意线程安全的问题,让10个人同时让一个理发师傅来服务。
代码不骗人,用一个小范例来看看不同实例模式的区别?
写了一个简单的范例,来验证和说明上述的观点,下面就先看一下最后的运行效果:
服务端运行效果解图:
从上面的解图可以看出,在服务启动的时候,也就是宿主ServiceHost.Open()的时候,便已经创建了Single模式的服务对象实例
客户端运行效果截图:
再回过头来看服务端效果:
本文参考资料
本文范例项目文件: