我使用VSTS 2008 + C#+ .Net 3.5开发控制台应用程序,并将请求发送到另一台服务器(Windows Server 2008上为IIS 7.0)。我发现当请求线程数很大(例如2000个线程)时,调用response =(HttpWebResponse)request.GetResponse()时,客户端将收到错误“无法连接到远程服务器失败”。我的困惑是-我有将超时设置为一个很大的值,但是在一分钟内我收到了这样的失败消息。我认为,即使连接的确大于IIS可以提供的服务,客户端也不会这么快收到失败消息,而是应该在超时后收到这样的消息。任何意见?任何想法有什么问题吗?有什么想法可以使IIS 7.0提供更多的并发连接?
这是我的代码,class Program
{
private static int ClientCount = 2000;
private static string TargetURL = "http://labtest/abc.wmv";
private static int Timeout = 3600;
static void PerformanceWorker()
{
Stream dataStream = null;
HttpWebRequest request = null;
HttpWebResponse response = null;
StreamReader reader = null;
try
{
request = (HttpWebRequest)WebRequest.Create(TargetURL);
request.Timeout = Timeout * 1000;
request.Proxy = null;
response = (HttpWebResponse)request.GetResponse();
dataStream = response.GetResponseStream();
reader = new StreamReader(dataStream);
// 1 M at one time
char[] c = new char[1000 * 10];
while (reader.Read(c, 0, c.Length) > 0)
{
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message + "\n" + ex.StackTrace);
}
finally
{
if (null != reader)
{
reader.Close();
}
if (null != dataStream)
{
dataStream.Close();
}
if (null != response)
{
response.Close();
}
}
}
static void Main(string[] args)
{
Thread[] workers = new Thread[ClientCount];
for (int i = 0; i < ClientCount; i++)
{
workers[i] = new Thread((new ThreadStart(PerformanceWorker)));
}
for (int i = 0; i < ClientCount; i++)
{
workers[i].Start();
}
for (int i = 0; i < ClientCount; i++)
{
workers[i].Join();
}
return;
}
}
最佳答案
Kev已经回答了您的问题,我只想补充一下,创建这么多线程并不是真正好的设计解决方案(只是上下文切换开销是一个很大的负数),而且扩展性不好。
快速的答案是:使用异步操作读取数据,而不是创建一堆线程。或至少使用线程池(并减少工作线程数)。请记住,与一个来源的更多连接只会使事情加速到一定程度。尝试对其进行基准测试,可能会发现3-5个连接的工作速度比现在使用的2000个更快。
您可以在此处阅读有关异步客户端/服务器体系结构(IOCP-输入/输出完成端口)的更多信息。您可以从这里开始:
MSDN - Using an Asynchronous Server Socket
MSDN - Asynchronous Server Socket Example
CodeProject - Multi-threaded .NET TCP Server Examples
所有这些示例都使用较低级别的TCP对象,但也可以将其应用于WebRequest / WebResponse。
更新
要尝试线程池版本,可以执行以下操作:ManualResetEvent[] events = new ManualResetEvent[ClientCount];
for (uint cnt = 0; cnt < events.Length; cnt++)
{
events[cnt] = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(obj => PerformanceWorker());
}
WaitHandle.WaitAll(events);
未经测试,可能需要一些调整。
关于c# - HttpWebRequest中的“无法连接到远程服务器失败”,我们在Stack Overflow上找到一个类似的问题:
https://stackoverflow.com/questions/1598748/