64 位 Windows 上的 HttpWebRequest GetResponse 延迟 [英] HttpWebRequest GetResponse delay on 64bit Windows

查看:23
本文介绍了64 位 Windows 上的 HttpWebRequest GetResponse 延迟的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近尝试在 64 位版本的 Windows 上运行一个 .NET 应用程序,并惊讶地发现我对本地网络上的 Web 服务的所有 HttpWebRequest.GetResponse() 调用都非常大(大约 500 毫秒)) 时间完成.以下是有关我的测试设置的一些信息:

I recently tried running a .NET application on 64bit versions of Windows and was surprised to notice that all my HttpWebRequest.GetResponse() calls to web services on my local network were talking huge (around 500ms) time to complete. Here's a few info regarding my test setup:

  • .NET 3.5
  • Windows Vista Home Premium 32 位、Windows Vista Business 64 位和 Windows Server 2008 64 位.

测试代码是 MSDN 关于 HttpWebRequest.GetResponse 的文章.我执行的唯一修改只是一个循环,以便我可以计时 10 个连续调用和基本身份验证,因为我的目标 Web 服务需要身份验证:

The test code is a slightly modified version of the example described in MSDN's article on HttpWebRequest.GetResponse. The only modifications I performed were just a loop so that I could time 10 consequtive calls, and Basic Authentication, since the web service I was targeting needed authentication:

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 服务的机器连接在同一网络交换机上.这是我得到的结果:

I compiled the program targeting x86 for Windows Vista Home Premium and x64 for the 64bit Windows machines. The three machines were connected on the same network switch together with the machine hosting the web service. Here are the results I got:

  • Windows Vista Home Premium 32 位,x86 程序集:对 GetResponse() 的第一次调用在 150 毫秒左右完成,而所有连续调用花费了大约 10 毫秒.
  • Windows Vista Business 64 位、Server 2008 64 位、x86 和 x64 程序集:第一次调用大约需要 1000 毫秒,而每个连续调用在 500 毫秒内完成/强>.如果我禁用 HttpWebRequest.PreAuthenticate,每个 GetResponse 都会在 1000 毫秒 内完成(这是很合理的,因为在这种情况下,每个请求都会触发两个单独的 HTTP 请求,一个以 Unauthorized 结束,一个得到了正确的回应).
  • Windows Vista Home Premium 32bit, x86 assembly: The first call to GetResponse() was completed in around 150ms, while all consecutive calls took around 10ms.
  • Windows Vista Business 64bit, Server 2008 64 bit, x86 and x64 assemblies: The first call took around 1000ms, while each consecutive call completed in 500ms. If I disable HttpWebRequest.PreAuthenticate, each GetResponse completes in 1000ms (which is quite reasonable since in this case each request triggers two separate HTTP requests, one ending up with Unauthorized and one the gets the proper response).

有没有人知道我在 64 位版本的 Windows 上 GetResponse 延迟这么长的原因?

Does anybody have a clue of the reason I get such long GetResponse delays on the 64 bit versions of Windows?

问题的其他信息:

  • 我测量了使用 Firefox 3.5 执行请求时的响应时间(按照建议通过 firebug),并且所有机器的请求响应延迟都相同,即问题没有重现.
  • 我使用 Wireshark 进行了进一步的数据包分析,得出以下结果:

32bit:tcp会话如下:

  • host->server 新的网络请求 HTTP GET/HTTP/1.1
  • server->host 两个 TCP 段(~5ms delta)
  • host->server Tcp Ack(确认两个段)(~10us delta)
  • 服务器->主机 HTTP/1.1 200 OK (~800us delta)
  • host->server 新的网络请求 HTTP GET/HTTP/1.1 &前一个段的搭载 TCP ack (HTTP/1.1 200 OK) (~10ms delta)
  • host->server New web request HTTP GET/HTTP/1.1
  • server->host Two TCP segments (~5ms delta)
  • host->server Tcp Ack (acknowledges both segments) (~10us delta)
  • server->host HTTP/1.1 200 OK (~800us delta)
  • host->server New web request HTTP GET/HTTP/1.1 & piggybacked TCP ack for previous segment (HTTP/1.1 200 OK) (~10ms delta)

64位:tcp对话如下:

  • host->server 新的网络请求 HTTP GET/HTTP/1.1
  • server->host 两个 TCP 段(~5ms delta,与 32bit 相同)
  • host->server Tcp Ack(确认两个段)(~10us delta,与 32 位相同)
  • 服务器->主机 HTTP/1.1 200 OK(~800us delta,与 32 位相同)
  • 主机->前一帧的服务器 TCP 确认 (HTTP/1.1 200 OK) (!!! 96ms)
  • host->server 新的 web 请求 HTTP GET/HTTP/1.1 (!!! 309ms)
  • host->server New web request HTTP GET/HTTP/1.1
  • server->host Two TCP segments (~5ms delta, same as 32bit)
  • host->server Tcp Ack (acknowledges both segments) (~10us delta, same as 32 bit)
  • server->host HTTP/1.1 200 OK (~800us delta, same as 32 bit)
  • host->server TCP ack for previous frame (HTTP/1.1 200 OK) (!!! 96ms)
  • host->server New web request HTTP GET/HTTP/1.1 (!!! 309ms)

我在 64 位机器上得到的 500 毫秒主要发生在最后两个步骤中.请注意,这绝对与 TCP 堆栈无关(因为在 Firefox 中一切正常).我们在最后两个步骤中得到不同 TCP Ack 模式的原因(32 位搭载,而 64 位单独的 TCP Ack 帧)是因为新的 Web 请求在 64 位情况下延迟了 309+96 毫秒(因此 TCP 堆栈输出一个单独的Ack帧,它不能等待应用层).

The 500ms I get on the 64 bit machines is mostly occured in the last two steps. Note that this is definitely not related to the TCP stack (since everything works ok with firefox). The reason we get different TCP Ack pattern in the last two steps (piggybacked in 32 bit, while separate TCP Ack frame in 64 bit) is that the new Web Request is delayed for 309+96ms in the 64bit case (so the TCP stack outputs a separate Ack frame, it can not wait for the application layer).

所以,看起来像:

  • 该问题是由完成 Web 请求和发出新请求之间的时间差引起的.
  • 这个问题与 .NET Framework 有关系吗?(绝对与 TCP 无关).
  • 问题发生在从 MSDN 中提取的 Microsoft 股票代码上(MS 不会错吧?).

有什么线索吗?

推荐答案

仅适用于遇到此线程并遇到问题的任何其他人.

Just for anyone else that comes across this thread and is having issues.

在 64 位系统上延迟的原因是 WebClient 等待 Windows 返回代理值.

The cause of the delay on 64bit systems is the WebClient waiting for Windows to return the proxy value.

像这样编写代码来解决这个问题.

Write your code like this to overcome this issue.

WebClient wc = New WebClient;
wc.Proxy = null;

这将消除一些用户(包括我自己:))看到的延迟

That will eliminate the delay seen by some users (including myself :))

很高兴我终于可以回馈对我有很大帮助的社区:)

Glad I could finally give something back to the community that has helped me so much :)

这篇关于64 位 Windows 上的 HttpWebRequest GetResponse 延迟的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆