我正在尝试通过多线程向网站发送请求来进行性能测试。每个线程都执行n次请求(在循环中)。
然而,我遇到了问题。具体来说是WebException ("无法连接到远程服务器")并带有内部异常:
由于系统缓冲区空间不足或队列已满,因此无法执行套接字操作127.0.0.1:52395
我正在尝试运行100个线程,每个线程500个迭代。
最初,我使用的是System.Net中的HttpWebRequest
进行GET请求。目前,我正在使用WebClient
,因为我假设每次迭代都使用一个新的套接字(因此在短时间内会有100 * 500个套接字)。我假设WebClient(每个线程实例化一次)只会使用一个套接字。
我不需要同时打开50,000个套接字,因为我想发送GET请求、接收响应并关闭套接字,以便在下一次循环迭代中释放它。我知道这可能是一个问题
但是,即使使用WebClient,也会请求一堆套接字,导致大量套接字处于TIME_WAIT
模式(使用netstat检查)。这会导致其他应用程序(如Internet浏览器)停止响应和运行。
我可以降低测试的迭代次数和/或线程数量,因为套接字似乎最终会退出此TIME_WAIT
状态。然而,这并不是解决方案,因为它不能充分测试Web服务器的能力。
问题:
如何在每个线程迭代后显式关闭套接字(从客户端)以防止TIME_WAIT
状态和套接字耗尽?
代码:
HttpRequest的包装类
编辑:将WebClient包装在using中,因此为每个迭代实例化、使用和处理一个新的WebClient。问题仍然存在。
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 ) ) {
}
}
}
}
创建新线程的ThreadWrapperClass的部分:
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();
}