Jak mogę zapobiec wyczerpaniu gniazd / portów?
Próbuję przetestować witrynę, uderzając ją żądaniami w wielu wątkach. Każdy wątek jest wykonywanyn czasy. (w pętli for)
Mam jednak problemy. W szczególności wyjątek WebException („Nie można połączyć się ze zdalnym serwerem”) z wewnętrznym wyjątkiem:
Nie można wykonać operacji na gnieździe, ponieważ w systemie brakowało wystarczającej ilości miejsca na bufor lub kolejka była pełna 127.0.0.1:52395
Próbuję uruchomić 100 wątków przy 500 iteracjach na wątek.
Początkowo używałemHttpWebRequest
w System.Net, aby wysłać żądanie GET do serwera. Obecnie używamWebClient
ponieważ założyłem, że każda iteracja używa nowego gniazda (więc 100 * 500 gniazd w krótkim czasie). Zakładałem, że WebClient (który jest tworzony raz na wątek) używałby tylko jednego gniazda.
Nie potrzebuję 50 000 otwartych gniazd od razu, ponieważ chciałbym wysłać żądanie GET, odebrać odpowiedź i zamknąć gniazdo, uwalniając je do użycia w następnej iteracji pętli. Rozumiem, że byłoby to problemem
Jednak nawet w przypadku WebClient żąda się wielu gniazd, co powoduje powstanie wielu gniazdTIME_WAIT
tryb (sprawdzany za pomocą netstat). Powoduje to, że inne aplikacje (takie jak przeglądarki internetowe) zawieszają się i przestają działać.
Mogę obsługiwać test z mniejszą liczbą iteracji i / lub mniejszą liczbą wątków, ponieważ wydaje się, że gniazda ostatecznie kończą ten stan OCZEKIWANIA CZASU. Nie jest to jednak rozwiązanie, ponieważ nie sprawdza odpowiednio możliwości serwera WWW.
Pytanie:
Jak jawnie zamknąć gniazdo (od strony klienta) po każdej iteracji wątku, aby zapobiec stanom TIME_WAIT i wyczerpaniu gniazda?
Kod:
Klasa, która otacza HttpRequest
Edytować: Wrapped WebClient w użyciu, więc nowy jest tworzony, używany i usuwany dla każdej iteracji. Problem nadal występuje.
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 ) ) {
}
}
}
}
Część mojej klasy ThreadWrapperClass, która tworzy nowy wątek:
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();
}