Instance Pooling in WCF – Part II

Posted: May 13, 2009 in WCF
Tags: , ,

In my last post I had started writing about Instance Pooling in WCF and we ended up developing a simple class providing object pooling functionality.In this post we will see what needs to be done step by step to incorporate this instance pool into the WCF framework.

Implementing IInstanceProvider

The class System.Runtime.Dispatcher.DispatchRuntime exposes the property InstanceProvider of type IInstanceProvider.DispatchRuntime uses this instance to acquire and release instances of service objects.IInstanceProvider defines the following methods:

  • GetInstance – Returns an service object instance
  • ReleaseInstance – Releases a service object instance

I have developed a class ServiceObjectPool which implements this interface and internally talks to the object pool as shown below:

public class ServiceObjectPool:IInstanceProvider   
{
    private ResourcePool pool = null;

    public ServiceObjectPool(Type resourceType, int maxPoolSize, int initialSize)
    {
        pool = new ResourcePool(resourceType, maxPoolSize, initialSize); //Create the pool
    }
    public ServiceObjectPool(Type resourceType, int maxPoolSize, int initialSize, int incrementSize)
    {
       pool = new ResourcePool(resourceType,maxPoolSize,initialSize,incrementSize); //Create the pool
    }
    public object GetInstance(System.ServiceModel.InstanceContext instanceContext, System.ServiceModel.Channels.Message message)
    {
        return pool.Acquire(); //Acquire from the Pool
    }

    public object GetInstance(System.ServiceModel.InstanceContext instanceContext)
    {
        return pool.Acquire(); //Acquire from the pool
    }

    public void ReleaseInstance(System.ServiceModel.InstanceContext instanceContext, object instance)
    {
        pool.Release(instance); //Release the object back to pool
    }

    }

Attaching the InstanceProvider to DispatchRuntime

To attach the custom Instance Provider to DispatchRuntime I have developed a custom behavior class ServicePoolBehavior as shown below:

public class ServicePoolBehavior : IServiceBehavior
    {
        public int MinPoolSize { get; set; }
        public int MaxPoolSize { get; set; }
        public int IncrementSize { get; set; }

        public void AddBindingParameters(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {
            return;
        }
        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
        {
        …….

        }

        public void Validate(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
        {

            return;

        }

    }

The main code goes into the ApplyDispatchBehavior method as shown below:

public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
{

     //Create the ServiceObjectPool instance
     ServiceObjectPool pool = new ServiceObjectPool(serviceDescription.ServiceType,MaxPoolSize ,MinPoolSize ,IncrementSize);
     ServiceThrottle throt = null;

     //Change the ServiceThrottle Setting in line with the Object Pool Settings

     foreach (ChannelDispatcher chDisp in serviceHostBase.ChannelDispatchers)
     {
         if(chDisp.ServiceThrottle!=null)
         {
             if (throt == null)
             {
                 throt = chDisp.ServiceThrottle;

             }
             else
             {
                 chDisp.ServiceThrottle = throt;
             }

             if (throt.MaxConcurrentInstances > MaxPoolSize)
             {
                 throt.MaxConcurrentInstances = MaxPoolSize;
             }
         }
         foreach (EndpointDispatcher endDisp in chDisp.Endpoints)
         {

             //Attach the Pool to Dispatch Runtime
             endDisp.DispatchRuntime.InstanceProvider = pool;
         }
     }
}

Attaching Behavior To Host

This can be done through code,attribute or configuration.Here I chose the configuration route.To attach the service behavior through configuration we need implement a subclass of System.ServiceModel.Configuration.BehaviorExtensionElement as shown below:

public class ServicePoolBehaviorExtensionElement:BehaviorExtensionElement
{
    [ConfigurationPropertyAttribute(“minPoolSize”,DefaultValue=2)]
    [IntegerValidator(MinValue=1)]
    public int MinPoolSize { get; set; }
    [ConfigurationPropertyAttribute(“maxPoolSize”,DefaultValue=10)]
    [IntegerValidator(MinValue = 1)]
    public int MaxPoolSize { get; set; }
    [ConfigurationPropertyAttribute(“incrementSize”,DefaultValue=2)]
    [IntegerValidator(MinValue = 1)]
    public int IncrementSize { get; set; }

    public override Type BehaviorType
    {
        get { return  typeof(ServicePoolBehavior); }
    }

    protected override object CreateBehavior()
    {
        ServicePoolBehavior behavior = new ServicePoolBehavior();
        behavior.MaxPoolSize = Convert.ToInt32( this.ElementInformation.Properties[“minPoolSize”].Value);
        behavior.MinPoolSize = Convert.ToInt32( this.ElementInformation.Properties[“maxPoolSize”].Value);
        behavior.IncrementSize = Convert.ToInt32( this.ElementInformation.Properties[“incrementSize”].Value) ;
        return behavior;
    }

}

The following lines needs to be added in the configuration file of the host:

    <extensions>
        <behaviorExtensions>
            <add name=”poolBehavior” type=”SB.ServiceModel.Pool.ServicePoolBehaviorExtensionElement, SB.ServiceModel.Pool, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null” />
        </behaviorExtensions>
    </extensions>
    <behaviors>
        <serviceBehaviors>
            <behavior name=”testBehavior”>
                <serviceDebug includeExceptionDetailInFaults=”true” />
                <serviceMetadata httpGetEnabled=”true” httpGetUrl=”
http://localhost:9001/Meta” />
                <poolBehavior minPoolSize=”5″ maxPoolSize=”10″ incrementSize=”2″/>
            </behavior>
        </serviceBehaviors>
    </behaviors>
     <services>
          <service behaviorConfiguration=”testBehavior” name=”SampleService.Test”>
               <endpoint address=”
http://localhost:9001/Test” binding=”wsHttpBinding”
                    name=”testhttp” contract=”SampleService.ITest” />
          </service>
     </services>
</system.serviceModel>

With this we complete the development of a simple pooling behavior attached to WCF service host.

Advertisements
Comments
  1. bured says:

    Sankarsan, where u take class ResourcePool?
    ResourcePool from System.EnterpriseServices namespace havent same constructor and methods.

  2. Val says:

    Sankarsan,
    Please provide the whole solution. In addition, when I try to edit web.config file, I get error message, that says that element cannot be recognized. How does it work?

  3. Robert Broomandan says:

    Hi Sankarsan,

    Can you provide the solution ?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s