Wie kann ich das 2-Verbindungslimit in WebClient programmgesteuert entfernen?

88

Diese "feinen" RFCs verlangen von jedem RFC-Client, dass sie nicht mehr als 2 Verbindungen pro Host verwenden ...

Microsoft hat dies in WebClient implementiert. Ich weiß, dass es mit ausgeschaltet werden kann

App.config:

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

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

Aber wie kann ich das programmgesteuert machen?

Gemäß http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager.defaultconnectionlimit.aspx

"Das Ändern der DefaultConnectionLimit-Eigenschaft hat keine Auswirkungen auf vorhandene ServicePoint-Objekte. Es betrifft nur ServicePoint-Objekte, die nach der Änderung initialisiert werden. Wenn der Wert dieser Eigenschaft weder direkt noch durch Konfiguration festgelegt wurde, wird standardmäßig die Konstante DefaultPersistentConnectionLimit festgelegt."

Ich möchte das Limit am besten konfigurieren, wenn ich den WebClient instanziiere, aber es wäre auch in Ordnung, diese traurige Einschränkung zu Beginn meines Programms programmgesteuert zu entfernen.

Der Server, auf den ich zugreife, ist kein regulärer Webserver im Internet, sondern unter meiner Kontrolle und im lokalen LAN. Ich möchte API-Aufrufe durchführen, verwende jedoch keine Webservices oder Remoting

Christian
quelle
15
Es ist nicht wirklich ein Standard. Der RFC "empfiehlt", dass Sie Clients auf zwei Verbindungen beschränken, dies ist jedoch nicht unbedingt erforderlich. Höchstwahrscheinlich muss das Poster mehr als 2 Elemente gleichzeitig herunterladen.
Erik Funkenbusch
12
Ich greife auf eine API auf meinem eigenen Server zu. Ich möchte Hosts im Internet keinen Schaden zufügen.
Christian
12
Ich habe das Verbindungslimit erhöht, um ein Lasttest-Tool zu erstellen. Es ist wirklich schwer, einen Test mit 2 Messanschlüssen zu laden. Ich bin mir sicher, dass es viele Gründe gibt, viele Verbindungen zu verwenden, um nicht zu surfen.
ScottS
1
Übrigens wirkt sich die obige Konfiguration auf alle .Net-gesteuerten Verbindungen aus, nicht nur auf den Webclient.
ScottS
2
Warum mehr als zwei? Wenden wir uns der Frage zu: Warum konnte ich nicht mehr als zwei Anfragen gleichzeitig asynchron an einen Server senden? 2 ist buchstäblich eine Einschränkung.
Csaba Toth

Antworten:

50

Mit einigen Tipps von hier und anderswo konnte ich dies in meiner Anwendung beheben, indem ich die von mir verwendete WebClient-Klasse überschrieb:

class AwesomeWebClient : WebClient {
    protected override WebRequest GetWebRequest(Uri address) {
        HttpWebRequest req = (HttpWebRequest)base.GetWebRequest(address);
        req.ServicePoint.ConnectionLimit = 10;
        return (WebRequest)req;
    }
}
Shizam
quelle
28
IMHO, dass das Einstellen der System.Net.ServicePointManager.DefaultConnectionLimiteine bessere Lösung ist, da nicht angenommen werden kann, dass das ein WebRequestist HttpWebRequest, z. B. könnte es ein sein FileRequest.
Dennis
120

für Interessierte:

System.Net.ServicePointManager.DefaultConnectionLimit = x (wobei x Ihre gewünschte Anzahl von Verbindungen ist)

Keine zusätzlichen Referenzen erforderlich

Stellen Sie einfach sicher, dass dies aufgerufen wird, BEVOR der Servicepunkt wie oben im Beitrag erwähnt erstellt wird.

lilmoe
quelle
Könnte dies also zu application_start im globalen Bereich hinzugefügt werden? Also betrifft es alle Verbindungen hergestellt?
TheAlbear
Wie und wo soll System.Net.ServicePointManager.DefaultConnectionLimit = x hinzugefügt werden?
Arul Sidthan
Seltsamerweise besagt der Codekommentar für DefaultConnectionLimit (Navigation mit F12), dass der Standardwert Int32.MaxValue ist. Bei der Debug-Inspektion ist es jedoch 2, wie behauptet.
Crokusek
7

Mit dieser Lösung können Sie das Verbindungslimit jederzeit ändern :

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

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

Wenn jemand FindServicePoint zum ersten Mal aufruft , wird eine ServicePoint- Instanz erstellt und eine WeakReference erstellt, um sie im ServicePointManager beizubehalten . Nachfolgende Anforderungen an den Manager für denselben Uri geben dieselbe Instanz zurück. Wenn die Verbindung danach nicht mehr verwendet wird, bereinigt der GC sie.

George Tsiokos
quelle
1
Das einzige Problem mit FindServicePoint besteht darin, dass Sie einen ServicePoint zurückgeben, aber nicht wissen, ob es sich um denselben ServicePoint handelt, den Ihr Client erhält.
Jeffa00
2
Das ist kein "Problem", es ist nur ein normaler Teil des Jobs. Wie bei allen Lösungen müssen Sie einen Weg finden, dies zu testen. Mein Weg war, die Einstellung in der .config auf "1" zu setzen, die schreckliche Leistung zu beobachten und sie in Code (wie hier) zu setzen, um die verbesserte Leistung zu beobachten.
Abacus
Das ServicePointist verloren (zusammen mit Ihren Einstellungen) nachMaxIdleTime
Colin Breame
5

Wenn Sie das von Ihrem WebClient verwendete ServicePoint-Objekt finden, können Sie dessen Verbindungslimit ändern. HttpWebRequest-Objekte verfügen über einen Accessor zum Abrufen des Objekts, für das sie erstellt wurden. Sie können dies also auf diese Weise tun. Wenn Sie Glück haben, teilen sich alle Ihre Anfragen möglicherweise denselben ServicePoint, sodass Sie dies nur einmal tun müssen.

Ich kenne keinen globalen Weg, um das Limit zu ändern. Wenn Sie das DefaultConnectionLimit früh genug in der Ausführung geändert haben, ist dies wahrscheinlich in Ordnung.

Alternativ könnten Sie einfach mit dem Verbindungslimit leben, da die meisten Server-Software Sie sowieso drosseln wird. :) :)

Katelyn Gadd
quelle
Dieser Server wird mich nicht drosseln (tatsächlich, aber auf andere Weise), da er vollständig unter meiner Kontrolle steht
Christian
1
Ein Server kann mit vielen Verbindungen drosseln, aber ich habe das selbst mit einem kleinen Server (der in einer begrenzten VM gehostet wird) nicht erlebt. Das Limit 2 auf der Client-Seite hielt mich dagegen zurück. Das Erhöhen der Grenze befreite die Situation.
Csaba Toth
1
Ich bezweifle auch, dass irgendein heutiger Browser das HTTP 1.1 RFC-Limit von 2 einhalten würde.
Csaba Toth
4

Wir haben eine Situation bezüglich der obigen Konfiguration in App.Config

Damit dies in einer CONSOLE-Anwendung gültig ist, haben wir die System.Configuration-Referenz-DLL hinzugefügt. Ohne den Hinweis war das oben Genannte nutzlos.

Teo-Kostas
quelle