What happened to ServiceHost.Throttle

The title says it all really.  The ServiceHost generic used to have a property named Throttle which allowed setting of no. of concurrent threads and so on, but this has now disappeared/moved.

Anyone know where it went

David



Answer this question

What happened to ServiceHost.Throttle

  • Nir Floripa

    Ralph, you've got it spot on.  The xml configuration is exactly what I want, but I want to do it programmatically.  It used to be very easy!

    I'm afraid the info you've given isn't enough for me to find ServiceThrottle, so an example would be much appreciated.

    David


  • david_wants

    David, I've posted a rough draft of the reference documentation for ServiceThrottlingBehavior at http://blogs.msdn.com/ralph.squillace/archive/2005/12/12/502887.aspx.

    Any errors, let me know. :-) I'll update the post as information becomes available.

  • iamreal2

    Ralph,

    Many thanks, this exactly what I needed, and looking at it I'm not surprised I couldn't find it.

    There's no documentation around on the various properties of ServiceThrottlingBehaviour, and anyone trying this will need to know the following.

    MaxConcurrentCalls - works the way you'd expect.  Set it to the no. of messages you want the service to process simultaneously.  If you have multiple servers reading from the same queue, this allows you to control the way the overall work ispartitiones, and also to control resource usage on each server.

    MaxPendingOperations - Appears this MUST be larger than MaxConcurrentCalls.  If it's <= MaxConcurrentCalls, then the service processes MaxConcurrentCalls messages, then empties the queue of further mesages and throws them away.  You have to stop the app and restart to get it to do anything else useful.  MaxConcurrentCalls + 1 appears to be a good value.  This is a change to the operation of the equivalent parameter in Beta1.

    MaxInstances - do not set this at all!  It defaults to maxint.  If you set it to some other no., then service will process that no. of messages and then stop!

    MaxConnections - no idea what this does.


    David


  • Mike Marino

    David,

    Won't switching from per-call instancing to singleton resolve your problem In this case there should be a single thread which does the whole processing.

    leszek<g>


  • mayflower

    I don't want a single thread.  I want a selectable no. of threads so I can optimise the cpu use for a particular machine.  This is what I could do with Beta1

    For the particular type of job I'm running, best throughput is achieved with 4-10 threads - depending on the cpu/memory configuration of the particular machine. That is the service should remove (say) 5 messages from the MSMQ and start a thread to process each.  As each thread is completed, remove another message from the queue and start another thread to process it, always keeping the same no. of threads processing so long as messages are available from the queue.

    The throttle property in Beta1 was perfect for providing this control, you could set the no. of messages being processed at once, and also the no of messages held locally pending processing, so you could avoid the MSMQ latency when one message completed before starting processing of the next.

    As it is, it appears that that control has been removed and replaced by a straight choice of either only one thread - not much use on a multi cpu machine - or as many threads as there are messages - not much use on any machine!

    David


  • Amanda Theodore

    It's been a week since I posted this question and still no replies.  Perhaps I didn't explain why it's a problem.

    When writing a service using MsmqIntegrationBinding, the new ServiceHost appears to read every message out of the queue, start a thread for each and try to process them all at once.  This is NOT the desired efect.  For starters it makes the priority queue feature of MSMQ useless - you can't jump a lower priority message in the queue if the message has already been read.

    It also makes it impossible to control resource use on the server computer.  If I post 1000 messages to a message queue, it's because I want 1000 jobs done - eventually.  What I do not want is 1000 threads starting up, each opening its own database connection and firing 1000 SQL statements at my poor overworked database server.

    With ServiceHost.Throttle I used to be able to set the max no of threads the service would use to process messages, and the max. no of additional messages that would be prefetched from the queue prior to processing by a thread.  This facility seems to have vanished in Nov CTP.

    You can achieve a similar sort of effect by setting the no. of IO Completion Port threads in System.Threading.ThreadPool, but this is a bit drastic since it affects the rest of the app, rather than just the service.

    Is there a new way to do this

    David


  • Lau Kok Soon

    OK, try this at home. See what it does for you. :-)


    using System;
    using System.Configuration;
    using System.Collections.Generic;
    using System.ServiceModel;
    using System.ServiceModel.Design;

    namespace Microsoft.WCF.Documentation
    {
      class HostApplication
      {

        static void Main()
        {
          HostApplication app = new HostApplication();
          app.Run();
        }

        private void Run()
        {
          // Get base address from app settings in configuration if you want.
          Uri baseAddress = new Uri(ConfigurationManager.AppSettings["baseAddress"]);

          // Create a ServiceHost for the service type and provide the base address.
          using (ServiceHost serviceHost = new ServiceHost(typeof(SampleService), baseAddress))
          {
              try
              {
                ServiceThrottlingBehavior throttle = new ServiceThrottlingBehavior();
                throttle.MaxConcurrentCalls = 1;
                throttle.MaxConnections = 1;
                throttle.MaxInstances = 1;
                throttle.MaxPendingOperations = 1;
                serviceHost.Description.Behaviors.Add(throttle);
                           
                // Open the ServiceHostBase to create listeners and start listening for messages.
                serviceHost.Open();

                // The service can now be accessed.
                Console.WriteLine("The service is ready.");
                Console.WriteLine("Press <ENTER> to terminate service.");
                Console.WriteLine();
                Console.ReadLine();

                // Close the ServiceHostBase to shutdown the service.
                serviceHost.Close();
              }
              catch (TimeoutException timeProblem)
              {
                  Console.WriteLine("The service operation timed out. " + timeProblem.Message);
              }
              catch (CommunicationException commProblem)
              {
                  Console.WriteLine("There was a communication problem. " + commProblem.Message);
              }
          }
        }
      }
    }


  • awparran

    OK, just for fun (and for documentation) I wrote another way to do this, using a custom service attribute, which was the way that I suggested before. Depends whether you want an attribute or not. First, I rewrote the service host code a bit to detect whether the throttle has already been set:

          // Create a ServiceHost for the service type and provide the base address.
          using (ServiceHost serviceHost = new ServiceHost(typeof(SampleService), baseAddress))
          {
              try
              {
                ServiceThrottlingBehavior throttle = serviceHost.Description.Behaviors.Find<ServiceThrottlingBehavior>();
                if (throttle == null)
                {
                  throttle = new ServiceThrottlingBehavior();
                  throttle.MaxConcurrentCalls = 1;
                  throttle.MaxConnections = 1;
                  throttle.MaxInstances = 1;
                  throttle.MaxPendingOperations = 1;
                  serviceHost.Description.Behaviors.Add(throttle);
                }
                else
                  Console.WriteLine("Prior to ServiceHost.Open: A ServiceThrottleBehavior has already been configured for this host.");
                // Open the ServiceHostBase to create listeners and start listening for messages.
                serviceHost.Open();


    Then I wrote the attribute:

      [AttributeUsage(AttributeTargets.Class)]
      public class ServiceThrottlingAttribute : Attribute, IServiceBehavior
      {
        private ServiceThrottlingBehavior throttle;

        public ServiceThrottlingAttribute(
          int maxConcurrentCalls,
          int maxConnections,
          int maxInstances,
          int maxPendingOperations)
        {
          this.throttle = new ServiceThrottlingBehavior();
          throttle.MaxConcurrentCalls = maxConcurrentCalls;
          throttle.MaxConnections = maxConnections;
          throttle.MaxInstances = maxInstances;
          throttle.MaxPendingOperations = maxPendingOperations;
        }
       
        #region IServiceBehavior Members

        public void ApplyBehavior(
          ServiceDescription description,
          ServiceHostBase serviceHostBase,
          System.Collections.ObjectModel.Collection<DispatchBehavior> behaviors,
          System.Collections.ObjectModel.Collection<BindingParameterCollection> parameters
        )
        {
          ServiceThrottlingBehavior currentThrottle = description.Behaviors.Find<ServiceThrottlingBehavior>();
          if (currentThrottle == null)
          {
            description.Behaviors.Add(this.throttle);
            Console.WriteLine("Throttling added by the ServiceThrottleAttribute.");
          }
          else
          {
            Console.WriteLine("In ServiceThrottleAttribute.ApplyBehavior: "
            + "A ServiceThrottleBehavior has already been configured for this host.");
          }
        }

        #endregion
      }

    Now you can do this in your service:

      [ServiceThrottling(1,1,1,1)]
      class SampleService : ISampleService
      {
      #region ISampleService Members

      public string  SampleMethod(string msg)
      {
        return "The service greets you: " + msg;
      }

    and the output looks like this:

    In ServiceThrottleAttribute.ApplyBehavior: A ServiceThrottleBehavior has already been configured for this host.
    The service is ready.
    Press <ENTER> to terminate service.


  • Dean Wills

    Daniel,

    That appears to be the class I'm after, but the problem is where to find one.  Under Beta1, the code looked as follows :-

    // create and open a service host for the JobProcessor
    queuedHost = new ServiceHost(typeof(JobProcessor));

    // set the desired no. of operating threads
    queuedHost.Throttle.MaxConcurrentCalls = 4;


    This restricted the no. of simultaneous calls to this particular service to 4 - from all endpoints.  The property Throttle has vanished, so the no. of simultaneous calls appears to be unrestricted now.  If there is an endpoint using MsmqIntegrationBinding then the effect is to read all messages from the queue and start processing them all simultaneously - not a good idea.

    What I need to know is what has happened to the property   I know the class is still there.

    David

     



  • chadmv

    Hmmm. I think you want this configuration:

    <behaviors>

    <behavior>

    <throttling maxConcurrentCalls="" maxConnections="" maxInstances="" maxPendingOperations=""/>

    </behavior>

    </behaviors>

    Programmatically, the ServiceThrottle is now get/set attached to the Dispatcher of your ServiceHost (you can get at that easily by calling DispatchBehavior.Dispatcher.ServiceThrottle from an IServiceBehavior implementation). The instances are controlled using InstanceContextThrottle, which you can fish out from the InstanceContext.

    Hope this helps. I'll see about writing up a little sample for this tomorrow sometime. If there is a direct property for this to be used programmatically, someone else may know. Cheers, Ralph
      


  • theartful_dodger

    Sorry; today I was out. I'll write a small sample for you in the morning (Redmond time). :-) Cheers, Ralph
  • Balamurugan

    It appearst that this functionality was moved to System.ServiceModel.ServiceThrottle.  This type has a MaxConcurrentCalls property.  Does this meet the requirements for your scenarios

    Thanks.

    Daniel Roth

  • EdZilla

    David,

    I'm glad that got you started. I think one of the issues may be that you were looking in System.ServiceModel but ServiceThrottlingBehavior is in System.ServiceModel.Design.

    Thanks, too, for the feedback. I believe that I have some more information about this, but we just haven't gotten it into the documentation yet. I'll see if I can't find out more about this and post it.

    Cheers, Ralph

  • What happened to ServiceHost.Throttle