当前位置:编程学习 > 网站相关 >>

WCF后续之旅(10): 通过WCF Extension实现以对象池的方式创建Service Instance

我们知道WCF有3种典型的对service instance进行实例化的方式,他们分别与WCF的三种InstanceContextMode相匹配,他们分别是PerCall,PerSession和Single。PerCall为每次service invocation创建一个新的service instance; 而PerSession则让一个service instance处理来自通过各Session(一般是同一个proxy对象)的调用请求;而Single则是用同一个service instance来处理所有的调用请求。SOA的一个原则是创建无状态的service(stateless service),PerCall应该是我们经常使用的实例化方式,尽管PerSession是默认的InstanceContextMode。

但是对于PerCall这种实例化方式来说,为每次service请求都创建新的service instance,有时候显得有点极端,频繁的对象创建会对系统的性能造成一定的影响。我们能够以池的机制(Pooling)进行对象的获取和创建呢:当service调用请求抵达service端,先试图从池中获取一个没有被使用的service instance,如何找到,直接获取该对象;否则创建新的对象。当service instance对象执行完毕,将对象释放到池中以供下次service 调用使用。

一、实现原理

我们今天就来试着实现这样的service instance提供机制。主要的实现原理是:让所有的service实现一个公共的interface(IPooledObject),定义了IsBusy的属性表明该对象当前是否正在被使用;为每个service type维护一个weak reference列表,每个weak reference对应一个确定的service instance,我们姑且将该weak reference列表成为该service type对应的对象池(object pool);为了处理service的调用需要提供一个确定的service instance的时候,遍历对象池,通过weak reference的Target属性找出一个可用的service instance(IsBusy=false)。如何顺利找到这样的service instance,则将其从对象池取出,将IsBusy属性设为true;如何没有找到,则通过反射创建一个新的service instance,将IsBusy设为true,同时利用weak reference将其包装,并将该weak reference加入到对象池中,最后返回该service instance用于处理service 调用。当service 调用结束,不是直接将其dispose掉,而是将其释放回对象池,供后续的service调用使用。

由于我们通过weak reference来实现对象池,weak reference引用的service instance是可以被GC回收的,这样做的好处是充分利用的GC的垃圾回收功能,避免不需要的service instance常驻内容,带来不必要的内存压力。此外,正是因为weak reference引用的service instance是可以被GC回收,我们需要一个后台的任务定期地将已经被回收的weak reference清除掉。

和本系列前两篇文章(WCF和Unity Appliation Block集成;WCF和Policy Injection Application Block集成)一样,涉及的是service instance的提供的问题,所以,我们也是通过自定义InstanceProvider来实现以对象池的机制创建service instance的目的。

四、PooledInstnaceProvider的创建

在创建我们自定义的InstanceProvider之前,我们先来介绍几个辅助的class:

I、IPooledObject

   1: namespace Artech.WCFExtensions
   2: {
   3:     public interface IPooledObject
   4:     {
   5:         bool IsBusy
   6:         { get; set; }
   7:     }
   8: }

由于我们要判断service instance是否可用,我们让所有的service type实现IPooledObject interface。IPooledObject 仅仅定义一个bool类型的属性:IsBusy。通过该属性判断service instance是否正在被使用。

II、WeakReferenceCollection和WeakReferenceDictionary

   1: namespace Artech.WCFExtensions
   2: {
   3:     public class WeakReferenceCollection:List<WeakReference>
   4:     {}
   5: 
   6:     public class WeakReferenceDictionary : Dictionary<Type, WeakReferenceCollection>
   7:     {}
   8: }

WeakReferenceCollection仅仅是WeakReference的列表,WeakReferenceDictionary 则是key为Type,value为WeakReferenceCollection的dictionary。在提供service instance的时候,就是根据service type为key找到对应的WeakReferenceCollection。

III、PooledInstanceLocator

   1: namespace Artech.WCFExtensions
   2: {
   3:     public static class PooledInstanceLocator
   4:     {
   5:         internal static WeakReferenceDictionary ServiceInstancePool
   6:         { get; set; }
   7: 
   8:         static PooledInstanceLocator()
   9:         {
  10:             ServiceInstancePool = new WeakReferenceDictionary();
  11:         }
  12: 
  13:        public static IPooledObject GetInstanceFromPool(Type serviceType)
  14:         {
  15:             if(!serviceType.GetInterfaces().Contains(typeof(IPooledObject)))
  16:             {
  17:                 throw new InvalidCastException("InstanceType must implement Artech.WCFExtensions.IPooledInstance");
  18:             }
  19: 
  20:             if (!ServiceInstancePool.ContainsKey(serviceType))
  21:             {
  22:                 ServiceInstancePool[serviceType] = new WeakReferenceCollection();
  23:             }
  24: 
  25:             WeakReferenceCollection instanceReferenceList = ServiceInstancePool[serviceType] ;
  26: 
  27:             lock (serviceType)
  28:             {
  29:                 IPooledObject serviceInstance =null;
  30:                 foreach (WeakReference weakReference in instanceReferenceList)
  31:                 {
  32:                     serviceInstance = weakReference.Target as IPooledObject;
  33:                     if (serviceInstance != null && !serviceInstance.IsBusy)
  34:                     {
  35:                         serviceInstance.IsBusy = true;
  36:               

补充:综合编程 , 其他综合 ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,