2

I am working on a WCF Service that is hosted in Windows Service, using nettcpbinding.

when i tried to perform load test on the service i built a simple client that call the service about 1000 call in second, the return from the service take about 2 to 8 seconds at first and after leaving the simple client running for about half hour the time to return the result increased, and some client gives some time out exceptions for the send time which was configured to be 2 minutes.

i revised the service throltting configuration and it's like this

these are the steps i tried to perform:

  1. revised the service throttling configuration

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

  2. was working on Windows 7 machine, so i moved to server 2008 but the same result.
  3. update the configuration of tcp binding to be like the following NetTcpBinding baseBinding = new NetTcpBinding(SecurityMode.None, true); baseBinding.MaxBufferSize = int.MaxValue;

            baseBinding.MaxConnections = int.MaxValue;
            baseBinding.ListenBacklog = int.MaxValue;
            baseBinding.MaxBufferPoolSize = long.MaxValue;
    
            baseBinding.TransferMode = TransferMode.Buffered;
            baseBinding.MaxReceivedMessageSize = int.MaxValue;
            baseBinding.PortSharingEnabled = true;
            baseBinding.ReaderQuotas.MaxDepth = int.MaxValue;
            baseBinding.ReaderQuotas.MaxStringContentLength = int.MaxValue;
            baseBinding.ReaderQuotas.MaxArrayLength = int.MaxValue;
            baseBinding.ReaderQuotas.MaxBytesPerRead = int.MaxValue;
            baseBinding.ReaderQuotas.MaxNameTableCharCount = int.MaxValue;
            baseBinding.ReliableSession.Enabled = true;
            baseBinding.ReliableSession.Ordered = true;
            baseBinding.ReliableSession.InactivityTimeout = new TimeSpan(23, 23, 59, 59);
    
    
            BindingElementCollection elements = baseBinding.CreateBindingElements();
            ReliableSessionBindingElement reliableSessionElement = elements.Find<ReliableSessionBindingElement>(); 
            if (reliableSessionElement != null)
            {
                reliableSessionElement.MaxPendingChannels = 128;
    
    
    
                TcpTransportBindingElement transport = elements.Find<TcpTransportBindingElement>();
    
                transport.ConnectionPoolSettings.MaxOutboundConnectionsPerEndpoint = 1000;
    
                CustomBinding newBinding = new CustomBinding(elements);                    
                newBinding.CloseTimeout = new TimeSpan(0,20,9);
                newBinding.OpenTimeout = new TimeSpan(0,25,0);
                newBinding.ReceiveTimeout = new TimeSpan(23,23,59,59);
                newBinding.SendTimeout = new TimeSpan(0,20,0);
                newBinding.Name = "netTcpServiceBinding";
    
                return newBinding;
            }
            else
            {
                throw new Exception("the base binding does not " +
                    "have ReliableSessionBindingElement");
            }
    
  4. changed my services function to use async and await

    public async Task<ReturnObj> Connect(ClientInfo clientInfo)
    {
        var task = Task.Factory.StartNew(() =>
        {
            // do the needed work
            // insert into database
            // query some table to return information to client
        });
    
    
        var res = await task;
        return res;
    }
    

    and updated the client to use async and await in it's call to the service.

  5. applied the Worker thread solution proposed in this link https://support.microsoft.com/en-us/kb/2538826 although i am using .net 4.5.1, and set the MinThreads to 1000 worker and 1000 IOCP

after all this the service start to handle more requests but the delay still exist and the simple client take about 4 hours to give time out

the strange thing that i found the service handle about 8 to 16 call within 100 ms, regarding the number of threads currently a live in the service.

i found a lot of articles talk about configuration needed to be placed in machine.config and Aspnet.config, i think this is not related to my case as i am using nettcp on windows service not IIS, but i have implemented these changes and found no change in the results.

could some one point me to what i am missing or i want from the service something it can't support?

mkalashy
  • 103
  • 1
  • 4
  • 2
    If the method cannot run in 1/1000th of a second you will never be able to prevent timeout. you keep feeding the service data and it cannot process it faster than you feed it. eventually the funnel will be full and leftovers will fail. – Franck Jun 11 '15 at 14:54
  • 1
    If you need to service 1000 requests per second you may want to start looking into load balancing/load sharing systems. – Ron Beyer Jun 11 '15 at 14:57
  • Yes he need something like azure with a lots of nodes. He need a setup that can connect to database, do inserts, query data, build object and return to the user all that in 1/1000th of a second or better to not drop connections overtime. i have killer SQL server balancing here and i cannot get better than 4 ms he need 4 times faster. – Franck Jun 11 '15 at 15:01
  • @Franck, i appreciate your answer but could refer me to a link on MSDN that say so, to make sure if i am on the wrong way or not – mkalashy Jun 15 '15 at 11:34
  • @RonBeyer could you refer me to a link on MSDN that proove that i need to have load balancing to handle 1000 call per second – mkalashy Jun 15 '15 at 11:35
  • there is no link it's just basic maths. If i send you a message to read every second and you take 1 second to read it you will be just in time. but if you take 2 second to read it, the time you read one you have 2 more on the side as i send you faster than you can read. the next second you read another one but you have 2 more on the side. eventually once you have read 1000 message in 2000 seconds me i have sent you 2000 messages that lay on you desk. Eventually the desk wont be able to hold all the stack of unread messages. message falling on the floor are dropped connections. – Franck Jun 15 '15 at 11:42
  • if your processor take 100 ms to run your method it will be able to do MAXIMUM 10 times the method per seconds. Now that being said you need to run 1000 times your method in 1 second hence you need to run the method 1000 times in 1 sec = 1000 ms / 1000 times = 1 ms per methodl. So your whole method has to process faster than or equal to 1 millisecond which i don't think it's possible on a single server. forget about multi thread 1 sec as one call can only run on 1 processor. right now your method takes about 12.5 ms you need 12.5 times the speed on a single core to drop that to our 1 ms. – Franck Jun 15 '15 at 11:51
  • 1
    please update your question with client implementation - it may be that creating client instances takes a long time or it may be some other issue. Is your WS method implementation does any long running computation or any IO task? It may be that the issue is not in WCF but in waiting for database to complete operation. – pg0xC Jun 17 '15 at 10:55

2 Answers2

1

It could be how your test client is written. With NetTcp, when you create a channel, it tries to get one from the idle connection pool. If it's empty, then it opens a new socket connection. When you close a client channel, it's returned back to the idle connection pool. The default size of the idle connection pool is 10, which means once there are 10 connections in the idle pool, any subsequent closes will actually close the TCP socket. If your test code is creating and disposing of channels quickly, you could be discarding connections in the pool. You could then be hitting a problem of too many sockets in the TIME_WAIT state.
Here is a blog post describing how to modifying the pooling behavior.

MattC
  • 373
  • 1
  • 6
0

This is most likely due to the concurrency mode set to Single (this is default value). Try setting ConcurrencyMode to Multiple by adding ServiceBehaviourAttribute to your service implementation.

Be sure to check documenttation: https://msdn.microsoft.com/en-us/library/system.servicemodel.concurrencymode(v=vs.110).aspx

Example:

// With ConcurrencyMode.Multiple, threads can call an operation at any time.   
// It is your responsibility to guard your state with locks. If 
// you always guarantee you leave state consistent when you leave 
// the lock, you can assume it is valid when you enter the lock.

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
class MultipleCachingHttpFetcher : IContract

You may be interested also in Sessions, Instancing, and Concurrency article which describes concurrency problems.

pg0xC
  • 1,226
  • 10
  • 20
  • i am already have it set to multiple, this is my current configuration [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)] – mkalashy Jun 15 '15 at 11:32