locked
Asynchronous HTTPWebRequest, Maximum Connections - Best Approach - Threads or Delegates?

    Question

  • I'm making HTTPWebrequest asynchronously using the the BeginInvoke method. The code is working - sort of . Here's the deal, the main thread appears to have successfully looped through 500,000 urls and sent asynchrous requests using a delegate. The thing is the code to submit the requests is still running. It's like the main thread has finished it's loop but the delegates haven't caught up. I'm fighting the urge to used the EndInvoke method so as to cause blocking. How can I cause let's say 50 thread to simulatenously execute on an XP machine using .Net 2.0. Which method is faster Multithreading using the thread or delegates? What are the maximum number of HTTP requests that can be active at one time on an XP machine versus a 2003 server using the Httpwebrequest class?

    Friday, December 28, 2007 7:33 PM

Answers

  • For HTTP 1.1 you have maximum of 2 TCP connection per host (e.g. server) that can be active.

     

    Which usually means you can only have 2 simultaneous request pending response.

     

    Only after a response is received (for a request) can the next request be send over the same connection.

     

    This fact limits the usefulness of creating more than 2 threads, where each tries to hit the same host. If you want to increase the request/sec metric you may benefit from increasing this default connection limit per host.

     

    Though arbitrarily increasing the connection limit may start to degrade the performance. Where this degradation starts occuring does look pretty random in nature but is actually dependent on many factors, like: the bandwidth available, latency to the server/host, other network using process/threads current demands on the system.

     

    Having said that you can increase the number of connections per host in the following way(s):

    a) Increase the maximum for ALL hosts change the ServicePointManager.DefaultConnectionLimit

    b) Increase the maximum for a specific host retrieve the ServicePoint for a host by calling

    ServicePointManager.FindServicePoint and then change the ServicePoint.ConnectionLimit

     

    Note that

    a) ALL these changes are only app domain wide and will not affect other processes connection limits.

    b) you are contending for the network bandwith with all other applications or threads in the same application; and if you increase the connection limit too large, you may starve other(s).

    c) you need to experiment to find a sweet spot; for what a connection limit should be.

     

    It also makes sense to limit your request handling threads (if you create any) to this maximum connection limit; otherwise you'd be creating threads that just wait other threads to finish off.

     

    (please mark this answered if the reply is to your satisfaction)

    Monday, December 31, 2007 4:27 AM
    Moderator

All replies

  • For HTTP 1.1 you have maximum of 2 TCP connection per host (e.g. server) that can be active.

     

    Which usually means you can only have 2 simultaneous request pending response.

     

    Only after a response is received (for a request) can the next request be send over the same connection.

     

    This fact limits the usefulness of creating more than 2 threads, where each tries to hit the same host. If you want to increase the request/sec metric you may benefit from increasing this default connection limit per host.

     

    Though arbitrarily increasing the connection limit may start to degrade the performance. Where this degradation starts occuring does look pretty random in nature but is actually dependent on many factors, like: the bandwidth available, latency to the server/host, other network using process/threads current demands on the system.

     

    Having said that you can increase the number of connections per host in the following way(s):

    a) Increase the maximum for ALL hosts change the ServicePointManager.DefaultConnectionLimit

    b) Increase the maximum for a specific host retrieve the ServicePoint for a host by calling

    ServicePointManager.FindServicePoint and then change the ServicePoint.ConnectionLimit

     

    Note that

    a) ALL these changes are only app domain wide and will not affect other processes connection limits.

    b) you are contending for the network bandwith with all other applications or threads in the same application; and if you increase the connection limit too large, you may starve other(s).

    c) you need to experiment to find a sweet spot; for what a connection limit should be.

     

    It also makes sense to limit your request handling threads (if you create any) to this maximum connection limit; otherwise you'd be creating threads that just wait other threads to finish off.

     

    (please mark this answered if the reply is to your satisfaction)

    Monday, December 31, 2007 4:27 AM
    Moderator
  • Lot of good info there thanks! I'll have to poke around to find where the servicepoint manager is a try from there. I actually set my maximum up to 1000 threads but never got much over 400. Incidentally I noticed way more threads out in release mode than in debug mode, however, the time to process 500,000 urls never changed. I did check my network utilization as the app was running - it was nothing. CPU and disk activity on source and destination hosts was also very low too. When you mention handling threads, is that workerthreads or asyncthreads?

     

    Monday, December 31, 2007 3:32 PM
  • Were you able to find out anything further with regard to sending and processing the large number of requests? I'm trying to tune a similar application and I'd appreciate any info about your approach and results. Thanks.
    Wednesday, October 01, 2008 2:57 PM
  • Setting ServicePointManager.DefaultConnectionLimit did not work for me! I checked request.ServicePoint.ConnectionLimit, and it was right, but still 2 connections were allowed. The real solution is as follows (.NET 3.5SP1 WPF App):
    App.config:
    <?xml version="1.0" encoding="utf-8" ?> 
    <configuration> 
      <system.net> 
        <connectionManagement> 
          <add address="*" maxconnection="100" /> 
        </connectionManagement> 
      </system.net> 
    </configuration> 
    That's it.
    • Proposed as answer by TWiStErRob Saturday, February 07, 2009 11:44 PM
    Saturday, February 07, 2009 11:43 PM