我最近尝试在64位版本的Windows上运行.NET应用程序,并且惊讶地注意到我HttpWebRequest.GetResponse()
在本地网络上对Web服务的所有调用都在谈论(大约500ms)时间.以下是有关我的测试设置的一些信息:
.NET 3.5
Windows Vista Home Premium 32位,Windows Vista Business 64位和Windows Server 2008 64位.
测试代码是MSDN文章中HttpWebRequest.GetResponse
描述的示例的略微修改版本.我执行的唯一修改只是一个循环,因此我可以计算10个连续调用和基本身份验证,因为我定位的Web服务需要身份验证:
using System; using System.Diagnostics; using System.Net; using System.Text; using System.IO; public class Program { // Specify the URL to receive the request. public static void Main (string[] args) { CredentialCache crCache = null; Stopwatch s = new Stopwatch(); for (int i = 0; i < 10; i++) { s.Reset(); s.Start(); HttpWebRequest request = (HttpWebRequest)WebRequest.Create (args[0]); // Set some reasonable limits on resources used by this request request.MaximumAutomaticRedirections = 4; request.MaximumResponseHeadersLength = 4; // Set credentials to use for this request. if (crCache == null) { crCache = new CredentialCache(); crCache.Add(new Uri(args[0]), "Basic", new NetworkCredential("user", "password")); } request.Credentials = crCache; request.PreAuthenticate = true; HttpWebResponse response = (HttpWebResponse)request.GetResponse(); Console.WriteLine("Content length is {0}", response.ContentLength); Console.WriteLine("Content type is {0}", response.ContentType); // Get the stream associated with the response. Stream receiveStream = response.GetResponseStream(); // Pipes the stream to a higher level stream reader with the required encoding format. StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8); Console.WriteLine("Response stream received."); //Console.WriteLine (readStream.ReadToEnd ()); response.Close(); readStream.Close(); s.Stop(); Console.WriteLine("Request took: " + s.ElapsedMilliseconds); } } }
我编译了针对Windows Vista Home Premium的x86和针对64位Windows机器的x64的程序.这三台机器与托管Web服务的机器一起连接在同一网络交换机上.以下是我得到的结果:
Windows Vista Home Premium 32位,x86程序集:第一个呼叫GetResponse()
在大约150 毫秒内完成,而所有连续呼叫大约需要10毫秒.
Windows Vista Business 64位,Server 2008 64位,x86和x64程序集:第一次调用大约需要1000ms,而每次连续调用都在500ms内完成.如果我禁用HttpWebRequest.PreAuthenticate
,则每个都GetResponse
在1000毫秒内完成(这是非常合理的,因为在这种情况下,每个请求触发两个单独的HTTP请求,一个以Unauthorized结束,一个得到正确的响应).
有没有人知道我GetResponse
在64位版本的Windows上出现如此长时间延迟的原因?
有关该问题的其他信息:
当使用Firefox 3.5执行请求并且所有计算机的请求 - 响应延迟相同时,我测量了响应时间(通过建议的firebug),即问题未被重现.
我使用Wireshark进行了进一步的数据包分析,并得出以下结果:
32位:tcp对话如下:
host-> server 新的Web请求 HTTP GET/HTTP/1.1
server-> host两个TCP段(~5ms delta)
host-> server Tcp Ack(确认两个段)(~10us delta)
server-> host HTTP/1.1 200 OK(~800us delta)
host-> server 新的web请求 HTTP GET/HTTP/1.1&piggybacked TCP ack for previous segment(HTTP/1.1 200 OK)(~10ms delta)
64位:tcp对话如下:
host-> server 新的Web请求 HTTP GET/HTTP/1.1
server-> host两个TCP段(~5ms delta,与32bit相同)
host-> server Tcp Ack(确认两个段)(~10us delta,与32 bit相同)
server-> host HTTP/1.1 200 OK(~800us delta,与32 bit相同)
host-> server TCP ack for previous frame(HTTP/1.1 200 OK)(!!! 96ms)
host-> server新的Web请求HTTP GET/HTTP/1.1(!!! 309ms)
我在64位机器上获得的500毫秒大部分都是在最后两步中出现的.请注意,这绝对与TCP堆栈无关(因为一切都可以使用firefox).我们在最后两个步骤中获得不同的TCP Ack模式(在32位中捎带,而64位中的单独TCP Ack帧)的原因是新的Web请求在64位情况下延迟了309 + 96ms(因此TCP堆栈输出一个单独的Ack框架,它不能等待应用层).
所以,似乎:
问题是由完成Web请求和发出新请求之间的增量时间引起的.
这个问题与.NET Framework有关吗?(绝对不是TCP相关的).
从MSDN获取的股票Microsoft代码出现问题(MS不能错?).
有线索吗?
只是遇到遇到这个问题并遇到问题的其他人.
64位系统延迟的原因是WebClient等待Windows返回代理值.
编写这样的代码来克服这个问题.
WebClient wc = New WebClient; wc.Proxy = null;
这将消除一些用户(包括我自己:)看到的延迟
很高兴我终于可以回馈给那些帮助过我的社区了:)