Comment puis-je supprimer par programme la limite de 2 connexions dans WebClient

88

Ces RFC "fines" obligent chaque client RFC à ne pas utiliser plus de 2 connexions par hôte ...

Microsoft a implémenté cela dans WebClient. Je sais qu'il peut être désactivé avec

App.config:

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

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

Mais comment puis-je le faire par programme?

Conformément à http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager.defaultconnectionlimit.aspx

"La modification de la propriété DefaultConnectionLimit n'a aucun effet sur les objets ServicePoint existants; elle affecte uniquement les objets ServicePoint qui sont initialisés après la modification. Si la valeur de cette propriété n'a pas été définie directement ou via la configuration, la valeur par défaut est la constante DefaultPersistentConnectionLimit."

J'aimerais mieux configurer la limite lorsque j'instancie le WebClient, mais supprimer simplement cette triste limitation par programme au début de mon programme serait également très bien.

Le serveur auquel j'accède n'est pas un serveur Web régulier sur Internet, mais sous mon contrôle et dans le réseau local. Je veux faire des appels d'API, mais je n'utilise pas de services Web ni de communication à distance

Christian
la source
15
Ce n'est pas vraiment une norme. La RFC "recommande" de limiter les clients à deux connexions, mais ce n'est pas vraiment une exigence. Plus que probablement, l'affiche doit télécharger plus de 2 éléments à la fois.
Erik Funkenbusch
12
J'accède à une API sur mon propre serveur. Je ne veux pas nuire aux hôtes sur Internet.
Christian
12
J'ai augmenté la limite de connexion pour créer un outil de test de charge. Il est vraiment difficile de charger le test avec 2 connexions de mesure. Je suis sûr qu'il existe de nombreuses raisons non liées à la navigation pour utiliser de nombreuses connexions.
ScottS
1
BTW, la configuration ci-dessus affectera toutes les connexions contrôlées par .Net, pas seulement le client Web.
ScottS
2
Pourquoi plus de deux? Tournons-nous autour de la question: pourquoi je ne pouvais pas émettre plus de deux requêtes à un serveur en même temps de manière asynchrone? 2 est littéralement une limitation.
Csaba Toth

Réponses:

50

Avec quelques conseils d'ici et d'ailleurs, j'ai réussi à résoudre ce problème dans mon application en remplaçant la classe WebClient que j'utilisais:

class AwesomeWebClient : WebClient {
    protected override WebRequest GetWebRequest(Uri address) {
        HttpWebRequest req = (HttpWebRequest)base.GetWebRequest(address);
        req.ServicePoint.ConnectionLimit = 10;
        return (WebRequest)req;
    }
}
Shizam
la source
28
IMHO que la définition de la System.Net.ServicePointManager.DefaultConnectionLimitest une meilleure solution, car ne peut pas supposer que le WebRequestest un HttpWebRequest, par exemple, il pourrait être un FileRequest.
Dennis
120

pour les intéressés:

System.Net.ServicePointManager.DefaultConnectionLimit = x (où x est le nombre de connexions souhaité)

pas besoin de références supplémentaires

assurez-vous simplement que cela est appelé AVANT que le point de service soit créé comme mentionné ci-dessus dans le message.

lilmoe
la source
Cela pourrait-il donc être ajouté à application_start dans le global? donc cela affecte toutes les connexions faites?
TheAlbear
Comment et où ajouter System.Net.ServicePointManager.DefaultConnectionLimit = x?
Arul Sidthan
Curieusement, le commentaire de code pour DefaultConnectionLimit (navigation à l'aide de F12) indique que sa valeur par défaut est Int32.MaxValue. Cependant, par inspection de débogage, il est de 2 comme indiqué.
crokusek
7

Cette solution vous permet de modifier la limite de connexion à tout moment :

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 première fois que quelqu'un appelle ce FindServicePoint , une instance ServicePoint est créée et une WeakReference est créée pour la conserver dans ServicePointManager . Les demandes suivantes adressées au gestionnaire pour le même Uri renvoient la même instance. Si la connexion n'est pas utilisée après, le CPG la nettoie.

George Tsiokos
la source
1
Le seul problème avec FindServicePoint est qu'il vous rend un ServicePoint mais vous ne savez pas si ce sera le même ServicePoint que votre client.
jeffa00
2
Ce n'est pas un "problème", c'est juste une partie normale du travail. Comme pour toutes les solutions, vous devez trouver un moyen de tester cela. Ma façon était de définir le paramètre dans le .config sur "1", d'observer les performances terribles et de le définir dans le code (comme ici), en observant les performances améliorées.
Abacus
1
Le ServicePointest perdu (avec vos paramètres) aprèsMaxIdleTime
Colin Breame
5

Si vous trouvez l'objet ServicePoint utilisé par votre WebClient, vous pouvez modifier sa limite de connexion. Les objets HttpWebRequest ont un accesseur pour récupérer celui pour lequel ils ont été construits, vous pouvez donc le faire de cette façon. Si vous avez de la chance, toutes vos demandes peuvent finir par partager le même ServicePoint, vous n'aurez donc à le faire qu'une seule fois.

Je ne connais aucun moyen global de modifier la limite. Si vous avez modifié le DefaultConnectionLimit suffisamment tôt dans l'exécution, tout ira probablement bien.

Alternativement, vous pouvez simplement vivre avec la limite de connexion, car la plupart des logiciels de serveur vont vous ralentir de toute façon. :)

Katelyn Gadd
la source
Ce serveur ne me ralentira pas (en fait, il le fera, mais d'une manière différente) car il est complètement sous mon contrôle
Christian
1
Un serveur peut ralentir avec beaucoup de connexions, mais je n'ai pas vécu cela même avec un petit serveur (hébergé dans une VM limitée). La limite 2 côté client m'a retenu en revanche. Augmenter la limite a libéré la situation.
Csaba Toth
1
Je doute également que l'un des navigateurs actuels obéisse à la limite de 2 de la RFC HTTP 1.1.
Csaba Toth
4

Nous avons une situation concernant la partie de configuration ci-dessus dans App.Config

Pour que cela soit valide dans une application CONSOLE, nous avons ajouté la dll de référence System.Configuration. Sans la référence, ce qui précède était inutile.

Teo-Kostas
la source