Wie kann ich verhindern, dass die Buchse/den Port Erschöpfung?
Ich bin versucht, performance-test einer website, indem Sie es mit Anfragen über mehrere threads. Jeder thread führt n Zeiten. (in einer for-Schleife)
Allerdings bin ich in Probleme laufen. Speziell die WebException ("Unable to connect to remote server") mit der inneren Ausnahme:
Ein Vorgang auf einem socket konnte nicht ausgeführt werden, weil das system
Pufferspeicher fehlte oder weil eine Warteschlange voll war
127.0.0.1:52395
Ich bin versucht zu laufen 100 threads bei 500 Iterationen pro thread.
Anfangs war ich mit HttpWebRequest
im System.Net um die GET-Anforderung an den server. Derzeit bin ich mit WebClient
da bin ich davon ausgegangen, dass jede iteration wurde mit einem neuen sockel (also 100 * 500 Steckdosen in einem kurzen Zeitraum von Zeit). Ich nahm WebClient (die instanziiert wird einmal pro thread) würde nur ein sockel.
Brauche ich nicht 50 000 sockets gleichzeitig öffnen, wie ich möchte zum senden der GET-Anforderung, die Antwort erhalten, und schließen Sie die Steckdose, mit der Freigabe für den Einsatz in der nächsten Schleife iteration. Ich verstehe, dass es ein großes problem wäre,
Aber auch mit WebClient, eine Reihe von sockets angefordert wird, was in einer Reihe von Steckdosen in TIME_WAIT
- Modus (überprüft mit netstat). Dies bewirkt, dass andere Anwendungen (z.B. internet-Browser) zu hängen und nicht mehr funktioniert.
Kann ich betreiben mein test mit weniger Iterationen und/oder weniger threads, wie es scheint, die sockets zu tun schließlich verlassen Sie diese TIME_WAIT-Zustand. Dies ist jedoch keine Lösung, da es nicht ausreichend testen Sie die Fähigkeiten des web-Servers.
Frage:
Wie kann ich explizit einen socket schließen (von der client-Seite) nach jedem thread iteration, um zu verhindern, dass TIME_WAIT-Staaten und Buchse Erschöpfung?
Code:
Klasse, wickelt die HttpRequest -
Edit: Gewickelt WebClient in einer Verwendung, so wird eine neue instanziiert,verwendet und entsorgt werden für jede iteration. Das problem noch besteht.
public sealed class HttpGetTest : ITest {
private readonly string m_url;
public HttpGetTest( string url ) {
m_url = url;
}
void ITest.Execute() {
using (WebClient webClient = new WebClient()){
using( Stream stream = webClient.OpenRead( m_url ) ) {
}
}
}
}
Den Teil meiner ThreadWrapperClass, erstellt einen neuen thread:
public void Execute() {
Action Hammer = () => {
for( int i = 1; i <= m_iterations; i++ ) {
//Where m_test is an ITest injected through constructor
m_test.Execute();
}
};
ThreadStart work = delegate {
Hammer();
};
Thread thread = new Thread( work );
thread.Start();
}
Denken Sie daran, es gibt nur ~65000 ports zur Verfügung, und nicht alle von Ihnen können verwendet werden, für ausgehende verbindungen. So würden Sie brauchen, um mehrere IPs/NICs zu tun, die 50000 verbindungen, die Sie versuchen zu tun
Ich verstehe, das wäre ein Problem, wenn ich war, die Ausführung einer großen Anzahl von threads, jedoch, sobald eine iteration der Schleife ist fertig, ich brauche die Steckdose nicht mehr, aber es sticks um, wodurch die nächste iteration eine neue zu öffnen. Ich bin auf der Suche einen Weg zu finden, um zu verhindern, dass
Du machst einen auf dem stream sind Sie immer zurück, aber nicht Ihre web-client. Sie könnten versuchen, eine using-Anweisung auf Ihrem WebClient als auch so, es wird entsorgt. Oder manuell entsorgen Sie es, sobald Sie fertig sind Lesen.
InformationsquelleAutor James | 2012-07-19
Du musst angemeldet sein, um einen Kommentar abzugeben.
Verstehen Sie den Zweck der TIME_WAIT? Es ist ein Zeitraum, in dem es wäre unsicher, die Wiederverwendung der port, da verlorene Pakete (erfolgreich Rückübertragung) von der vorherigen Transaktion könnte noch geliefert werden innerhalb dieser Zeitspanne.
Könnte Sie wahrscheinlich optimieren Sie es nach unten in die registry irgendwo, aber ich Frage mich, ob dies ein sinnvoller Nächster Schritt.
Sind meine Erfahrungen, um realistische Last in einer Testumgebung zu haben, erwies sich als sehr frustrierend. Sicherlich läuft Ihre Last-tester von localhost ist keineswegs realistisch, und die meisten Netzwerk-tests, die ich gemacht habe mit dem .net-http-apis zu erfordern scheinen, dass mehr Grunzen in der client als der server selbst.
Als solche, es ist besser, zu verschieben, um eine zweite Maschine für die Generierung von Last auf dem server... aber inländische routing-Ausrüstung ist selten bis zu dem job zu unterstützen, irgendwo in der Nähe die Anzahl der verbindungen, die dazu führen würde, dass jede Art von Last auf ein gut geschriebenes server-app, so jetzt müssen Sie aktualisieren Ihre routing - /switching-Ausrüstung, wie gut!
Schließlich, ich habe ein paar wirklich seltsame und unerwartete performance-Probleme rund um die .net-Http-client-API. Am Ende des Tages, Sie alle nutzen HttpWebRequest zu tun, die schweres heben. IMO ist es bei weitem nicht so performant wie es sein könnte. DNS ist die synchrone, auch beim aufrufen der APIs asynchron (obwohl, wenn Sie nur anfordert von einem einzigen host, dies ist nicht ein Problem), und-bei nachhaltiger Nutzung der CPU-Nutzung schleicht sich, bis der AUFTRAGGEBER wird die CPU eingeschränkt statt IO eingeschränkt. Wenn Sie schauen, um einen nachhaltigen und schweren Last, jede Anfrage-schwere app angewiesen auf HttpWebRequest ist IMO eine falsche Investition.
Alles in allem eine ziemlich knifflige Aufgabe, und schließlich etwas, das kann nur bewiesen werden, die in der freien Wildbahn, es sei denn, du hast plently von Bargeld zu verbringen, auf eine armada von besserer Ausrüstung.
[Hinweis: ich habe viel bessere perfomance aus meinem eigenen client geschrieben, mit asynchronen Socket-apis und eine 3rd-party-DNS-client-Bibliothek]
Nun, DNS ist nicht ein Problem für Sie, aber Sie könnte dies interessant finden: stackoverflow.com/questions/11480742/... . Ich habe gefunden, kann man viel besser chatten HTTP mit dem .net-Socket-api. Ich schrieb eine kleine Bibliothek selbst (spidering), kann Sie aber nicht teilen, denn es gehört zu meiner Firma, und es implementiert nur eine sehr begrenzte Untermenge von HTTP. Tut es aber machen .net in der Tat sehr schnell, wenn dabei HTTP, schlagen IO-Grenzen, während praktisch im Leerlauf.
InformationsquelleAutor spender
A: Dude, TIME_WAIT ist ein integraler und wichtiger! - ein Teil der TCP/IP-sich selbst!
Du kann Stimmen Sie die OS zu reduzieren TIME_WAIT (das kann negative Auswirkungen haben).
Und Sie können die Melodie des OS zu erhöhen #/ephemeral ports:
Hier ist ein link auf warum TIME_WAIT vorhanden ist ... und warum es eine Gute Sache:
InformationsquelleAutor paulsm4
Sieht es aus wie Sie nicht gezwungen werden, Ihre WebClient, um loszuwerden, die Ressourcen, die es reserviert hat. Sie führen eine Anwendung auf den stream zurückgegeben, aber Ihre WebClient hat noch Ressourcen.
Entweder wickeln Sie den WebClient-Instanzierung in einen using-block verwenden, oder manuell aufrufen, entsorgen Sie, sobald Sie fertig sind Lesen der URL.
Versuchen Sie dies:
Ich bin mir nicht sicher, was es ist, dann, sorry, ich hätte nicht mehr helfen.
InformationsquelleAutor Stefan H
Es ist nicht eine Frage der Schließung Steckdosen oder die Freigabe von Ressourcen in Ihrer app. Die ZEIT _WAIT wird eine TCP-stack timeot auf veröffentlicht Steckdosen zu verhindern, dass die re-Nutzung bis zu dem Zeitpunkt, als es ist praktisch unmöglich, für alle Pakete, die 'übrig', die aus einer früheren Verbindung zu diesem socket nicht abgelaufen sind.
Für test-Zwecke können Sie die Wartezeit reduzieren, die von der Standardeinstellung, (einige Minuten, AFAIK) auf einen kleineren Wert. Wenn die Last-Test-Server, habe ich es auf sechs Sekunden.
Ist es in der registry irgendwo - du wirst ihn finden, wenn Sie Google.
Gefunden:
Ändern TIME_WAIT-Verzögerung
InformationsquelleAutor Martin James
Brauchen Sie nicht zu mess around mit TIME_WAIT zu erreichen, was Sie wollen.
Das problem ist, dass Sie die Entsorgung der WebClient bei jedem Aufruf von Execute(). Wenn Sie das tun, schließen Sie die socket-Verbindung mit dem server und den TCP-port beschäftigt, für den TIME_WAIT-Periode.
Ein besserer Ansatz ist die Erstellung der WebClient in den Konstruktor von Ihrer HttpGetTest Klasse und die Wiederverwendung der gleichen Objekt während der Prüfung.
WebClient verwendet, keep-alive, die standardmäßig und wird dieselbe Verbindung für alle Ihre Anforderungen, also in Ihrem Fall gibt es nur 100 verbindungen geöffnet.
Hmm... die Frage wurde bearbeitet, ich wollte nicht sehen, mit dem original-code. 1. Ja das ist richtig wie ich sagte. 2. Ja, gleicher host, wie könnte es anders sein? Auch wollte er nicht sagen, es waren viele Techniker und auch wenn es eine Serverfarm, 100 threads wäre wahrscheinlich genug, um zu schlagen Sie alle den Servern (vorausgesetzt, es ist weit weniger als 100). Wahrscheinlich, es ist etwas anderes Los, WebClient sollte sich korrekt Verhalten, wenn Sie es wiederverwenden. Und die Frage ist "Wie kann ich verhindern, dass die Buchse/den Port Erschöpfung?": mit WebClient (oder vielleicht HttpClient) korrekt verhindert port Erschöpfung.
InformationsquelleAutor andrecarlucci