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