Intentando ejecutar múltiples solicitudes HTTP en paralelo, pero estando limitado por Windows (registro)

Estoy desarrollando una aplicación (winforms C # .NET 4.0) donde accedo a una funcionalidad de búsqueda de un tercero a través de una simple solicitud HTTP. Llamo a una url con un parámetro, y a cambio obtengo una pequeña cadena con el resultado de la búsqueda. Suficientemente simple.

El desafío es, sin embargo, que tengo que hacer muchas de estas búsquedas (un par de miles), y me gustaría limitar el tiempo necesario. Por lo tanto, me gustaría ejecutar solicitudes en paralelo (digamos 10-20). Yo uso un ThreadPool para hacer esto, y la versión corta de mi código se ve así:

public void startAsyncLookup(Action returnLookupResult) { this.returnLookupResult = returnLookupResult; foreach (string number in numbersToLookup) { ThreadPool.QueueUserWorkItem(lookupNumber, number); } } public void lookupNumber(Object threadContext) { string numberToLookup = (string)threadContext; string url = @"http://some.url.com/?number=" + numberToLookup; WebClient webClient = new WebClient(); Stream responseData = webClient.OpenRead(url); LookupResult lookupResult = parseLookupResult(responseData); returnLookupResult(lookupResult); } 

Llenar numbersToLookup (una List ) desde otro lugar, llamar a startAsyncLookup y proporcionarle una función de callback returnLookupResult para devolver cada resultado. Esto funciona, pero descubrí que no obtengo el rendimiento que quiero.

Inicialmente pensé que podría ser la tercera parte que tiene un sistema pobre en su extremo, pero lo excluí tratando de ejecutar el mismo código desde dos máquinas diferentes al mismo tiempo. Cada uno de los dos tomó tanto tiempo como uno solo, por lo que podría descartar ese.

Luego, un colega me avisó que esto podría ser una limitación en Windows. Busqué en Google un poco y encontré esta publicación diciendo que, de forma predeterminada, Windows limita el número de solicitudes simultáneas al mismo servidor web a 4 para HTTP 1.0 y a 2 para HTTP 1.1 (para HTTP 1.1 esto está realmente de acuerdo con la especificación ( RFC2068)).

La misma publicación mencionada anteriormente también proporcionó una manera de boost estos límites. Al agregar dos valores de registro a [HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings] (MaxConnectionsPerServer y MaxConnectionsPer1_0Server), pude controlarlo yo mismo.

Entonces, probé esto (me senté a 20), reinicié mi computadora y traté de ejecutar mi progtwig nuevamente. Lamentablemente, no pareció ayudar a ninguno. También estuve atento al Monitor de recursos ( ver captura de pantalla ) mientras ejecutaba mi búsqueda por lotes, y noté que mi aplicación (la que tenía el título bloqueado) aún solo usaba dos conexiones TCP.

Entonces, la pregunta es, ¿por qué no está funcionando? ¿La publicación a la que me he vinculado usa los valores de registro incorrectos? ¿Es posible que ya no sea posible “piratear” en Windows (estoy en Windows 7)?

Cualquier idea sería muy apreciada 🙂

Y en caso de que alguien se pregunte, también he intentado con diferentes configuraciones para MaxThreads en ThreadPool (cada una de 10 a 100), y esto no pareció afectar mi rendimiento en absoluto, así que el problema tampoco debería estar allí.

Es asunto de ServicePoint . Que proporciona administración de conexión para conexiones HTTP. La cantidad máxima predeterminada de conexiones simultáneas permitidas por un objeto de ServicePoint es 2. Entonces, si necesita boostla, puede usar la propiedad ServicePointManager.DefaultConnectionLimit . Simplemente verifique el enlace en MSDN allí puede ver una muestra. Y establece el valor que necesitas

Para una referencia más rápida para alguien. Para boost el límite de conexión por host, puede hacer esto en su Main () o en cualquier momento antes de comenzar a hacer las solicitudes HTTP.

  System.Net.ServicePointManager.DefaultConnectionLimit = 1000; //or some other number > 4 

Dispara y olvida este método desde tu método principal. El usuario de Icognito es correcto, solo se permiten 2 hilos para jugar al mismo tiempo.

 private static void openServicePoint() { ServicePointManager.UseNagleAlgorithm = true; ServicePointManager.Expect100Continue = true; ServicePointManager.CheckCertificateRevocationList = true; ServicePointManager.DefaultConnectionLimit = 10000; Uri MS = new Uri("http://My awesome web site"); ServicePoint servicePoint = ServicePointManager.FindServicePoint(MS); } 

Para Internet Explorer 8: ejecute el Editor del registro y navegue hasta la siguiente clave HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Internet Explorer \ MAIN \ FeatureControl \ FEATURE_MAXCONNECTION SPERSERVER

y

HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Internet Explorer \ MAIN \ FeatureControl \ FEATURE_MAXCONNECTION SPER1_0SERVER

Si faltan FEATURE_MAXCONNECTIONSPERSERVER y FEATURE_MAXCONNECTIONSPER1_0SERVER, créelos. Ahora cree el valor DWORD llamado iexplore.exe para las dos claves secundarias (enumeradas anteriormente) y establezca su valor en 10 o en el número que desee.