¿Cómo puedo eliminar programáticamente el límite de 2 conexiones en WebClient?

88

Esos RFC "finos" exigen a todos los clientes de RFC que tengan cuidado de no utilizar más de 2 conexiones por host ...

Microsoft implementó esto en WebClient. Sé que se puede apagar con

App.config:

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
 <system.net> 
  <connectionManagement> 
   <add address="*" maxconnection="100" /> 
  </connectionManagement> 
 </system.net> 
</configuration> 

(que se encuentra en http://social.msdn.microsoft.com/forums/en-US/netfxnetcom/thread/1f863f20-09f9-49a5-8eee-17a89b591007 )

Pero, ¿cómo puedo hacerlo programáticamente?

Según http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager.defaultconnectionlimit.aspx

"Cambiar la propiedad DefaultConnectionLimit no tiene ningún efecto en los objetos ServicePoint existentes; solo afecta a los objetos ServicePoint que se inicializan después del cambio. Si el valor de esta propiedad no se ha establecido directamente o mediante la configuración, el valor predeterminado es la constante DefaultPersistentConnectionLimit".

Lo mejor es configurar el límite cuando instalo el WebClient, pero simplemente eliminar esta triste limitación mediante programación al comienzo de mi programa también estaría bien.

El servidor al que accedo no es un servidor web normal en Internet, sino que está bajo mi control y en la LAN local. Quiero hacer llamadas a API, pero no uso servicios web ni comunicación remota

cristiano
fuente
15
Realmente no es un estándar. El RFC "recomienda" que limite los clientes a dos conexiones, pero en realidad no es un requisito. Lo más probable es que el póster necesite descargar más de 2 elementos a la vez.
Erik Funkenbusch
12
Accedo a una API en mi propio servidor. No quiero dañar hosts en Internet.
Christian
12
Aumenté el límite de conexión para crear una herramienta de prueba de carga. Es realmente difícil realizar una prueba de carga con 2 conexiones medulares. Estoy seguro de que hay muchas razones para no navegar por las conexiones.
ScottS
1
Por cierto, la configuración anterior afectará a todas las conexiones controladas por .Net, no solo al webclient.
ScottS
2
¿Por qué más de dos? Démosle la vuelta a la pregunta: ¿por qué no puedo emitir más de dos solicitudes a un servidor al mismo tiempo de forma asincrónica? 2 es literalmente una limitación.
Csaba Toth

Respuestas:

50

Con algunos consejos de aquí y en otros lugares, logré solucionar esto en mi aplicación anulando la clase WebClient que estaba usando:

class AwesomeWebClient : WebClient {
    protected override WebRequest GetWebRequest(Uri address) {
        HttpWebRequest req = (HttpWebRequest)base.GetWebRequest(address);
        req.ServicePoint.ConnectionLimit = 10;
        return (WebRequest)req;
    }
}
Shizam
fuente
28
En mi humilde opinión, configurar el System.Net.ServicePointManager.DefaultConnectionLimites una mejor solución, ya que no se puede asumir que WebRequestes un HttpWebRequest, por ejemplo, podría ser un FileRequest.
Dennis
120

para los interesados:

System.Net.ServicePointManager.DefaultConnectionLimit = x (donde x es la cantidad deseada de conexiones)

sin necesidad de referencias adicionales

solo asegúrese de que esto se llame ANTES de que se cree el punto de servicio como se mencionó anteriormente en la publicación.

lilmoe
fuente
Entonces, ¿podría agregarse esto a application_start en el global? por lo que afecta a todas las conexiones realizadas?
TheAlbear
¿Cómo y dónde agregar System.Net.ServicePointManager.DefaultConnectionLimit = x?
Arul Sidthan
Curiosamente, el comentario de código para DefaultConnectionLimit (navegando usando F12) dice que su valor predeterminado es Int32.MaxValue. Sin embargo, por inspección de depuración, es 2 como se afirma.
crokusek
7

Esta solución le permite cambiar el límite de conexión en cualquier momento :

private static void ConfigureServicePoint(Uri uri)
{
    var servicePoint = ServicePointManager.FindServicePoint(uri);

    // Increase the number of TCP connections from the default (2)
    servicePoint.ConnectionLimit = 40;
}

La primera vez que alguien llama a este FindServicePoint , un ServicePoint instancia de se crea una WeakReference para retenerla dentro del ServicePointManager . Las solicitudes posteriores al administrador del mismo Uri devuelven la misma instancia. Si la conexión no se usa después, el GC la limpia.

George Tsiokos
fuente
1
El único problema con FindServicePoint es que le devuelve un ServicePoint, pero no sabe si será el mismo ServicePoint que recibe su cliente.
jeffa00
2
Eso no es un "problema", es solo una parte normal del trabajo. Al igual que con todas las soluciones, debe encontrar una manera de probarlo. Mi manera fue establecer la configuración en .config en "1", observar el terrible rendimiento y configurarlo en código (como aquí), observando el rendimiento mejorado.
Abacus
1
Se ServicePointpierde (junto con su configuración) después deMaxIdleTime
Colin Breame
5

Si encuentra que el objeto ServicePoint está siendo utilizado por su WebClient, puede cambiar su límite de conexión. Los objetos HttpWebRequest tienen un descriptor de acceso para recuperar el que fueron construidos para usar, por lo que puede hacerlo de esa manera. Si tiene suerte, todas sus solicitudes pueden terminar compartiendo el mismo ServicePoint, por lo que solo tendrá que hacerlo una vez.

No conozco ninguna forma global de cambiar el límite. Si modificó DefaultConnectionLimit lo suficientemente temprano en la ejecución, probablemente estaría bien.

Alternativamente, podría vivir con el límite de conexión, ya que la mayoría del software de servidor lo acelerará de todos modos. :)

Katelyn Gadd
fuente
Este servidor no me estrangulará (de hecho, lo hará, pero de una manera diferente) ya que está completamente bajo mi control
Christian
1
Un servidor puede acelerarse con muchas conexiones, pero no lo he experimentado ni siquiera con un servidor pequeño (alojado en una VM limitada). El límite 2 en el lado del cliente me detuvo por otro lado. Incrementar el límite liberó la situación.
Csaba Toth
1
También dudo que cualquiera de los navegadores de hoy obedezca al límite de HTTP 1.1 RFC de 2.
Csaba Toth
4

Tenemos una situación relacionada con la configuración anterior en App.Config

Para que esto sea válido en una aplicación CONSOLE, agregamos la dll de referencia System.Configuration. Sin la referencia, lo anterior fue inútil.

Teo-Kostas
fuente