none
How to increase the concurrency of RESTful WCF Service? RRS feed

  • Question

  • Hi

       I used

    [ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall,ConcurrencyMode=ConcurrencyMode.Multiple)]

     to make my wcf service support concurrency. And I use WebInvoke and WebGet to make it as a RESTful WCF Service. Finally, I used WebServiceHost to launch the whole service. Also the service throttling is set in app.config

          <serviceBehaviors>
            <behavior name="Default">
              <serviceMetadata httpGetEnabled="true"></serviceMetadata>
              <serviceDebug includeExceptionDetailInFaults="true"/>
              <serviceThrottling maxConcurrentCalls="16" maxConcurrentInstances="2147483647" maxConcurrentSessions="10" />
            </behavior>
          </serviceBehaviors>

       In load test, I created 100 HTTP requests at the same time to call the service and monitor the result . I found all the requests are handled by the same managed thread(having the same managed thread Id :1 )..... I hope the HTTP request could be handled concurrently, without waiting for the previous requst handled. Can Restful WCF support concurrency?

    Thanks,

    Yi







    Friday, August 12, 2011 4:19 PM

Answers

All replies

  • I tried a similar scenario (see code below), and the service is using multiple threads (see code below). Can you check the differences between your test service and the one on the code below?

      public class Post_593df2bb_9505_49f2_92e9_e6e925d95830
      {
        [ServiceContract]
        [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple)]
        public class Service
        {
          const int MillisecondsToSleep = 500;
          [WebInvoke]
          public string Echo(string text)
          {
            Console.WriteLine("Called Echo at thread {0}", Thread.CurrentThread.ManagedThreadId);
            Thread.Sleep(MillisecondsToSleep);
            return text;
          }
          [WebGet]
          public int Add(int x, int y)
          {
            Console.WriteLine("Called Add at thread {0}", Thread.CurrentThread.ManagedThreadId);
            Thread.Sleep(MillisecondsToSleep);
            return x + y;
          }
        }
        public static void Test()
        {
          string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
          WebServiceHost host = new WebServiceHost(typeof(Service), new Uri(baseAddress));
          ServiceThrottlingBehavior stb = host.Description.Behaviors.Find<ServiceThrottlingBehavior>();
          if (stb == null)
          {
            stb = new ServiceThrottlingBehavior();
            host.Description.Behaviors.Add(stb);
          }
    
          stb.MaxConcurrentCalls = 50;
          stb.MaxConcurrentInstances = 50;
          stb.MaxConcurrentSessions = 50;
    
          host.Open();
          Console.WriteLine("Host opened");
    
          Thread[] requestThreads = new Thread[20];
          for (int i = 0; i < requestThreads.Length; i++)
          {
            bool useGet = (i % 2) == 0;
            requestThreads[i] = new Thread(new ThreadStart(delegate
            {
              string address = baseAddress + (useGet ? "/Add?x=3&y=9" : "/Echo");
              HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(address);
              req.Method = useGet ? "GET" : "POST";
              if (!useGet)
              {
                req.ContentType = "application/json";
                byte[] reqBody = Encoding.UTF8.GetBytes("\"Hello world\"");
                Stream reqStream = req.GetRequestStream();
                reqStream.Write(reqBody, 0, reqBody.Length);
                reqStream.Close();
              }
    
              HttpWebResponse resp;
              try
              {
                resp = (HttpWebResponse)req.GetResponse();
              }
              catch (WebException ex)
              {
                resp = ex.Response as HttpWebResponse;
              }
    
              if (resp == null)
              {
                Console.WriteLine("Response is null");
              }
              else
              {
                Console.WriteLine("HTTP/{0} {1} {2}", resp.ProtocolVersion, (int)resp.StatusCode, resp.StatusDescription);
                resp.Close();
              }
            }));
          }
    
          for (int i = 0; i < requestThreads.Length; i++)
          {
            requestThreads[i].Start();
          }
    
          for (int i = 0; i < requestThreads.Length; i++)
          {
            requestThreads[i].Join();
          }
    
          Console.Write("Press ENTER to close the host");
          Console.ReadLine();
          host.Close();
        }
      }
    
    


    Carlos Figueira
    Friday, August 12, 2011 5:50 PM
    Moderator
  • Thank you for your reply:)

    I found the problem was maybe caused by the application which used WebServiceHost  to launch the WCF service .  If I use a WPF application and launch the service, in a button_click event handler, then the WCF concurrency are gone! Howeve if the applicaion is a console application ,then the concurrency is still there.  Could you explain why these happened ? Will the concurrency be restricted in UI thread?

    Thanks,

    Yi

     

     

    • Marked as answer by Yi Zhou Saturday, August 13, 2011 2:04 PM
    • Unmarked as answer by Yi Zhou Saturday, August 13, 2011 2:04 PM
    Saturday, August 13, 2011 1:20 PM
  • That explains. By default, if there is a synchronization context in the moment the service is started (which is the case for methods called by UI events on WPF/WinForms apps), then WCF will try to deliver all the calls in that same thread (so you can update some UI control within a service call, for example). You can turn this off by setting the [ServiceBehavior(UseSynchronizationContext = false)] in your service.

    More information at the MSDN page at http://msdn.microsoft.com/en-us/library/system.servicemodel.servicebehaviorattribute.usesynchronizationcontext.aspx, or at this blog post http://nevmehta.blogspot.com/2006/12/what-is-usesynchronizationcontext.html.


    Carlos Figueira
    • Marked as answer by Yi Zhou Saturday, August 13, 2011 2:04 PM
    Saturday, August 13, 2011 1:32 PM
    Moderator
  • Thank you. It addressed my issue!
    Saturday, August 13, 2011 2:04 PM