Ask a questionAsk a question
 

AnswerwsHttpBinding not responsive after 10 calls

  • Tuesday, September 29, 2009 9:55 AMWout Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Has Code
    Hi,

    My WCF service is unresponsive after 10 calls (using wsHttpBinding, hosted in ServiceHost). Anybody got an idea what's going on? Looks like there's a session limit (MaxConcurrentSessions ), even though I explicitly declare to not use sessions. Not that client isn't closing the proxy, I don't want to rely on the client to do this. In .NET remoting the single call activation worked like a charm, can the same thing be achieved in WCF? Problem is similar to described here: http://stackoverflow.com/questions/832871/wcf-concurrent-requests-piling-up-on-the-server-when-using-wshttpbinding .

    Server contract:

    using System;
    using System.Collections.Generic;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.Text;
    
    namespace BusinessApp.Data {
        /// <summary>
        /// Don't allow transport sessions.
        /// </summary>
        [ServiceContract(SessionMode = SessionMode.NotAllowed)]
        public interface IService {
            [OperationContract]
            List<Product> GetAllProducts();
    
            [OperationContract]
            [CustomDataContractSerializer(true)]
            List<Category> GetAllCategories();
        }
    }
    
    


    Server:

    using System;
    using System.Collections.Generic;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.Text;
    
    using BusinessApp.Data;
    
    namespace BusinessApp.WcfService {
        [ServiceBehavior(AddressFilterMode = AddressFilterMode.Any, InstanceContextMode = InstanceContextMode.Single)]
        public class Service : IService {
            private static int callNumber;
    
            public List<Product> GetAllProducts() {
                Console.WriteLine("{0}: GetAllProducts()", callNumber++);
                List<Product> products = new List<Product>();
                products.Add(new Product { Name = "Apple", Description = "Juicy apple", Price = 1.20m });
                products.Add(new Product { Name = "Tomato", Description = "Red tomato", Price = 1.35m });
                return products;
            }
    
            public List<Category> GetAllCategories() {
                Console.WriteLine("{0}: GetAllCategories()", callNumber++);
                List<Category> categories = new List<Category>();
                Category foodCategory = new Category { Name = "Food" };
                foodCategory.Products.AddRange(GetAllProducts());
                foodCategory.CheapestProduct = foodCategory.Products[0];
                categories.Add(foodCategory);
                return categories;
            }
        }
    }
    
    

    Client:

                ChannelFactory<IService> channelFactory = new ChannelFactory<IService>("WsHttpService");
                channelFactory.Credentials.UserName.UserName = "john";
                channelFactory.Credentials.UserName.Password = "P@ssword";
    
                IService service = channelFactory.CreateChannel();
                List<Product> products = service.GetAllProducts();
    
    


    Wout

Answers

  • Wednesday, October 28, 2009 11:56 PMSergei Dorogin Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    Hi, Wout.
    Very interesting question!

    I believe you should set EstablishSecurityContext property of WSHttpBinding to false.

                var binding = new WSHttpBinding();
                binding.Security.Message.EstablishSecurityContext = false;

    It's needed to be done on both client and server.

    Also check this:
    http://blogs.msdn.com/drnick/archive/2009/07/15/load-balanced-web-service-bindings.aspx
    Sergei Dorogin, Lead Developer, CROC Inc. (www.croc.ru)
    • Marked As Answer byWout Thursday, November 12, 2009 11:45 AM
    • Proposed As Answer byQyl Tuesday, November 03, 2009 9:24 PM
    •  

All Replies

  • Tuesday, September 29, 2009 11:07 AMAlan Smith MVPMVPUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Hi,

    The wsHttpBinding will use secure sessions when you use username/password autthentication.

    When you call the service, it is important to close the client procy after you have made the call, this will close the secure session.

    If you want more cliennts to connect symaltaniously you can increase the maximum number of sessions.

    Regards,

    Alan

    www.CloudCasts.net - Community Webcasts Powered by Azure
  • Tuesday, September 29, 2009 12:16 PMWout Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Hi Alan,

    Thank you for your answer. So there is no way to automatically close the session server side after each call? This is how the old asmx web services worked, and I guess the current WCF BasicHttpBinding as well. If this is the case I'll have to switch to BasicHttpBinding, as this is the behavior that I want, because I don't want to rely on the client to close the session, as this would leave the server sensitive to a DOS attack. A bunch of clients not closing the session would tie the server up in a split second. Is this a design oversight in the wsHttpBinding?

    Best regards,

    Wout
  • Tuesday, September 29, 2009 12:28 PMAlan Smith MVPMVPUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Hi,

    Sessions in WCF are different from ASP.NET sessions.

    As for your scenario, I seem to remember there may be an option to supress the creation of secure sessions, but I'm not sure what it was (maybe i'm wrong here).

    One option to protect against clients who forget to close the sessions is to set the receive timeout on the service binding configuration. THe defualt is 10 minutes, meaning that the session will live for 10 minutes without a call before it is closed by the service. If you reduce this you can minimize (but not eleminate) this.

    Regards,

    Alan


    www.CloudCasts.net - Community Webcasts Powered by Azure
  • Tuesday, September 29, 2009 12:42 PMWout Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Has Code
    Hi Alan,

    Yes, I was aware of the receive timeout, but the objective is to eliminate the session creation completely. For now I'll stick to BasicHttpBinding for better protection against dodgy clients.

    Is there an official channel to request a feature? It would be nice to have an option for the WsHttpBinding to not create a session (which I thought the
    [ServiceContract(SessionMode = SessionMode.NotAllowed)]
    did).

    Thank you for you help,

    Wout
  • Tuesday, September 29, 2009 2:24 PMFrank Xu Lei Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Hi,
      it seems something wrong with your Service Throttling configration.
      for default the MaxConcurrentSessions is 10.
      there are 3 Properties:MaxConcurrentCalls、MaxConcurrentSessions、MaxConcurrentInstances.
      they default values are:16,10,26.
     
      so if concurrency clients num more than 10,it will be dead locked and the 11th client can not receive any response until a timeout exception which will cause the cchannel faulted. and client can not use the channel.
     
      So you can try to udapted the Throttling configration.
      as following:
    <serviceBehaviors>
            
    <behavior name="WCFService.WCFServiceBehavior">
              
    <serviceTimeouts transactionTimeout="00:01:00"/>
              
    <serviceMetadata httpGetEnabled="true" />
              
    <serviceDebug includeExceptionDetailInFaults="false" />
              
    <serviceThrottling maxConcurrentCalls="1000" maxConcurrentInstances="1000" maxConcurrentSessions="1000"/>-->
            
    </behavior>
          
    </serviceBehaviors>
      then set the behavior  for your service.

    regards

    Frank Xu Lei--谦卑若愚,好学若饥
    专注于.NET平台下分布式应用系统开发和企业应用系统集成
    Focus on Distributed Applications Development and EAI based on .NET
    欢迎访问老徐的中文技术博客:Welcome to My Chinese Technical Blog
    欢迎访问微软WCF中文技术论坛:Welcome to Microsoft Chinese WCF Forum
    欢迎访问微软WCF英文技术论坛:Welcome to Microsoft English WCF Forum
  • Tuesday, September 29, 2009 3:23 PMWout Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Hi Frank Xu Lei,

    I'm aware of throttling, but problem is I don't want 1000 dangling sessions, because both 10 or 1000 don't really protect against DOS attacks. The server will still hang within a split second if the client doesn't close the session.

    What I want is to create no sessions at all, or automatically kill the session on the server side as soon as the call is completed.

    Best regards,

    Wout

  • Monday, October 05, 2009 4:11 AMSteven Cheng - MSFTMSFT, ModeratorUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Proposed AnswerHas Code
    Hi Wout,

    Yes, you can turn off reliableSession for wshttpbinding with two settings:

    1. mark your serviceContract as SessionMode=NotAllowed(as you mentioned in previous message)

    2. In binding config, turn off the reliableSession as below:

    <bindings>
    
    <wsHttpBinding>
    
    <binding name="Binding1" >
    
    <reliableSession enabled="false"/>
    
    <security mode= "None"></security>
    
    </binding>
    
    </wsHttpBinding>
    
    </bindings>
    
    
    

    Also, if message secuirty is not necessary for your scenario, I think basicHttpBinding is good enough.
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    • Proposed As Answer bySteven Cheng - MSFTMSFT, ModeratorTuesday, October 06, 2009 2:02 AM
    • Unproposed As Answer byWout Wednesday, October 07, 2009 7:53 AM
    • Marked As Answer bySteven Cheng - MSFTMSFT, ModeratorWednesday, October 07, 2009 2:02 AM
    • Unmarked As Answer byWout Wednesday, October 07, 2009 7:51 AM
    • Proposed As Answer byQyl Tuesday, November 03, 2009 9:24 PM
    • Marked As Answer byWout Thursday, November 12, 2009 12:16 PM
    • Unmarked As Answer byWout Thursday, November 12, 2009 12:21 PM
    •  
  • Monday, October 05, 2009 4:18 AMRohan Fernando Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    What if you increast the concurrent calls in service throtling behaviour

    <serviceThrottling
                maxConcurrentCalls="100"
                maxConcurrentSessions="100"
                maxConcurrentInstances="100"
              />

    Rohan Fernando
  • Monday, October 05, 2009 4:18 AMRohan Fernando Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
  • Wednesday, October 07, 2009 7:53 AMWout Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Hi Steven,

    I have tried setting reliableSession enabled to false in the server configuration, but the behavior remains exactly the same, still need to close the session explicitly on the client. Thank you for the reply though.

    Wout

  • Wednesday, October 07, 2009 10:15 AMSANDEVKAR Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Did u close the service after calling the method?
  • Thursday, October 08, 2009 4:16 AMHaripraghash Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Hi,

    When you set ServiceBehavior(InstanceContextMode=InstanceContextMode.Single, and cehck OperationContext.Current.SessionId inside the operation you will see that session is null. That i guess means sessions are not enabled. Or you can try setting the following which didnt allow me to create more than 25 client proxies. If your not interested in sessions at all then you can try percall instance mode. Or last but not least you try setting ReleaseInstancemode in you service bevaior to AfterCall. But than that will result in  a per call service.

    <

     

    serviceBehaviors>
    <
    behavior name="CustomUserNameValidator.Service1Behavior">
    <
    serviceCredentials>
    <
    userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="CustomUserNameValidator.MyUserNamePasswordValidator, CustomUserNameValidator, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
    </
    serviceCredentials>

    <!--

     

    To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->

    <

     

    serviceMetadata httpsGetEnabled="true"/>

    <!--

     

    To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->

    <

     

    serviceDebug includeExceptionDetailInFaults="false"/>

    <

     

    serviceThrottling maxConcurrentSessions="25"/>

    </

     

    behavior>

    </

     

    serviceBehaviors>

  • Wednesday, October 28, 2009 11:56 PMSergei Dorogin Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    Hi, Wout.
    Very interesting question!

    I believe you should set EstablishSecurityContext property of WSHttpBinding to false.

                var binding = new WSHttpBinding();
                binding.Security.Message.EstablishSecurityContext = false;

    It's needed to be done on both client and server.

    Also check this:
    http://blogs.msdn.com/drnick/archive/2009/07/15/load-balanced-web-service-bindings.aspx
    Sergei Dorogin, Lead Developer, CROC Inc. (www.croc.ru)
    • Marked As Answer byWout Thursday, November 12, 2009 11:45 AM
    • Proposed As Answer byQyl Tuesday, November 03, 2009 9:24 PM
    •  
  • Tuesday, November 03, 2009 9:23 PMQyl Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Has Code
    I had the same x call problem with wsHttpBinding. I used the varous suggestions from this forum and this is what finally worked:

    Set SessionMode to NotAllowed on service interface:
        [ServiceContract(SessionMode=SessionMode.NotAllowed)]
        public interface IMainService
     
    

    DO NOT set InstanceContextMode.PerCall on the class (don't know if this matters)

    Add Bindings section to config file with reliableSession enabled = false, security mode=Message, establishSecurityContext=false:

          <service behaviorConfiguration="SixService.MainServiceBehavior" name="SixService.MainService">
            <endpoint address="" binding="wsHttpBinding" bindingConfiguration="Binding1" contract="SixService.IMainService">
              <identity>
                <dns value="localhost" />
              </identity>
            </endpoint>
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
          </service>
        </services>
        <bindings>
          <wsHttpBinding>
            <binding name="Binding1">
              <reliableSession enabled="false" />
              <security mode="Message">
                <message establishSecurityContext="false" />
              </security>
            </binding>
          </wsHttpBinding>
        </bindings>
    
    So far this is allowing me to have no session with wsHttpBinding, so I am a happy camper, thanks for all the help!

  • Thursday, November 12, 2009 12:06 PMWout Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Hi Sergei,

    I have just tested and verified that this does solve the issue! I'm very glad you found it, I was already surprised that the wsHttpBinding didn't allow this. I now add this binding's security's message configuration at the server side:

        <message clientCredentialType="UserName" establishSecurityContext="false" />

    At the client side I set the binding's security's message establishSecurityContext to false:

        <message clientCredentialType="UserName" establishSecurityContext="false" />

    So now the server configuration eliminates the existence of these sessions, correct?


    However!!! Have any idea what the difference is between property WSHttpBindingBase.ReliableSession.Enabled and WSHttpBinding.Security.Message.EstablishSecurityContext?

    Many thanks!

    Wout
  • Thursday, November 12, 2009 12:18 PMWout Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Hi Steven,

    Have any idea what the difference is between property WSHttpBindingBase.ReliableSession.Enabled and WSHttpBinding.Security.Message.EstablishSecurityContext?

    Thank you for your help!

    Wout
  • Thursday, November 12, 2009 12:24 PMWout Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Has Code
    Oops, revisited the server config again. It was definitely not
    <reliableSession enabled="false"
    
     />
    that did the trick. I had it in there, which made me think that made it work, but it was this that did make it work:
    <message clientCredentialType="UserName" establishSecurityContext="false" /
    
    Apologies for the confusion! But I'm glad everything is adding up it's working properly now!

    Wout