【问题标题】:Why is this WebRequest code slow?为什么这个 WebRequest 代码很慢?
【发布时间】:2010-10-19 18:05:06
【问题描述】:

我请求了 100 页,全部 404。我写了

    {
    var s = DateTime.Now;
    for(int i=0; i < 100;i++)
        DL.CheckExist("http://google.com/lol" + i.ToString() + ".jpg");
    var e = DateTime.Now;
    var d = e-s;
        d=d;
        Console.WriteLine(d);
    }

static public bool CheckExist(string url)
{
    HttpWebRequest wreq = null;
    HttpWebResponse wresp = null;
    bool ret = false;

    try
    {
        wreq = (HttpWebRequest)WebRequest.Create(url);
        wreq.KeepAlive = true;
        wreq.Method = "HEAD";
        wresp = (HttpWebResponse)wreq.GetResponse();
        ret = true;
    }
    catch (System.Net.WebException)
    {
    }
    finally
    {
        if (wresp != null)
            wresp.Close();
    }
    return ret;
}

两次运行显示它需要 00:00:30.7968750 和 00:00:26.8750000。然后我尝试了firefox并使用以下代码

<html>
<body>
<script type="text/javascript">
for(var i=0; i<100; i++)
    document.write("<img src=http://google.com/lol" + i + ".jpg><br>");
</script>

</body>
</html>

使用我的计算时间并计算它大约是 4 秒。 4 秒比我的应用快 6.5-7.5。我计划扫描数千个文件,因此花费 3.75 小时而不是 30 分钟将是一个大问题。我怎样才能使这段代码更快?我知道有人会说 Firefox 缓存了图像,但我想说 1)它仍然需要检查远程服务器的标头以查看它是否已更新(这是我希望我的应用程序执行的操作)2)我不是接收正文,我的代码应该只请求标题。那么,我该如何解决呢?

【问题讨论】:

    标签: c# httpwebrequest httpwebresponse


    【解决方案1】:

    设置cookie很重要,您必须像此代码一样添加AspxAutoDetectCookieSupport=1

     req.CookieContainer = new CookieContainer();         
     req.CookieContainer.Add(new Cookie("AspxAutoDetectCookieSupport", "1") { Domain = target.Host });
    

    【讨论】:

      【解决方案2】:

      好的,如果您获得所有网页的状态代码 404,那么这是由于未指定凭据。所以你需要添加

      wreq.Credentials = CredentialCache.DefaultCredentials;
      

      然后您可能还会遇到状态代码= 500,因为您需要指定用户代理。看起来像下面的行

      wreq.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0) Gecko/20100101 Firefox/4.0";
      

      “默认情况下,WebClient 实例不发送可选的 HTTP 标头。如果您的请求需要可选标头,则必须将标头添加到 Headers 集合中。例如,要在响应中保留查询,您必须添加用户-代理标头。此外,如果缺少用户代理标头,服务器可能会返回 500(内部服务器错误)。”

      参考:https://msdn.microsoft.com/en-us/library/system.net.webclient(v=vs.110).aspx

      为了提高你需要添加的 HttpWebrequest 的性能

      wreq.Proxy=null
      

      现在代码将如下所示:

       static public bool CheckExist(string url)
      {
          HttpWebRequest wreq = null;
          HttpWebResponse wresp = null;
          bool ret = false;
      
      try
      {
          wreq = (HttpWebRequest)WebRequest.Create(url);
          wreq.Credentials = CredentialCache.DefaultCredentials;
          wreq.Proxy=null;
          wreq.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0) Gecko/20100101 Firefox/4.0";
          wreq.KeepAlive = true;
          wreq.Method = "HEAD";
          wresp = (HttpWebResponse)wreq.GetResponse();
          ret = true;
      }
      catch (System.Net.WebException)
      {
      }
      finally
      {
          if (wresp != null)
              wresp.Close();
      }
      return ret;
      

      }

      【讨论】:

        【解决方案3】:

        我注意到HttpWebRequest 挂在第一个请求上。我做了一些研究,似乎正在发生的事情是请求正在配置或自动检测代理。如果你设置了

        request.Proxy = null;
        

        在网络请求对象上,您或许能够避免初始延迟。

        使用代理自动检测:

        using (var response = (HttpWebResponse)request.GetResponse()) //6,956 ms
        {
        }
        

        没有代理自动检测:

        request.Proxy = null;
        using (var response = (HttpWebResponse)request.GetResponse()) //154 ms
        {
        }
        

        【讨论】:

        • 当我将此行放入我的代码中时 request.Proxy = null;我能够立即得到结果!谢谢
        • 如果请求需要通过某些客户端站点的代理,会有什么后果?它还会知道它需要获取代理吗?
        • 我不知道。代理自动检测似乎很慢(或者是,现在已经超过 2 年了),这会禁用它。我的猜测是,如果您设置此标志,它将无法正确检测代理。
        • 凌晨 1 点,我正把头撞在墙上,调试线程代码,试图找出导致某些请求花费这么长时间的原因。和Proxy = null 来救援!谢谢十亿!!!
        • 有时将 Expect100Continue 设置为 false 有助于加快 webrequests(如果服务器/服务支持):ServicePointManager.Expect100Continue = false;msdn.microsoft.com/en-us/library/… 默认情况下,在每次查询之前发送 continue 100 状态。通过禁用它可以加快请求。
        【解决方案4】:

        完成后关闭响应流,因此在 checkExist() 中,在 wresp = (HttpWebResponse)wreq.GetResponse(); 之后添加 wresp.Close()

        【讨论】:

          【解决方案5】:

          答案是将 HttpWebRequest/HttpWebResponse 仅更改为 WebRequest/WebResponse。这解决了问题。

          【讨论】:

            【解决方案6】:

            您是否尝试在部署代码的机器上的 IE 中打开相同的 URL?如果它是 Windows Server 机器,那么有时是因为您请求的 url 不在 IE 的安全站点列表中(HttpWebRequest 可以使用)。你只需要添加它。

            您有更多可以发布的信息吗?我做过类似的事情,之前遇到过很多 HttpWebRequest 的问题。都是独一无二的。所以更多信息会有所帮助。

            顺便说一句,在这种情况下,使用异步方法调用它并没有真正的帮助。它不会缩短下载时间。它只是不会阻塞你的调用线程而已。

            【讨论】:

            • 我用IE6试了一下,大概需要5秒。我的代码使用 = wreq.Method = "HEAD";需要 12.5。我假设它使用 2 个线程。该数据看起来足够接近。
            • 注意到您提到您的请求页面是 404。以前没有故意这样做,但 WebRequest 行为在这种情况下可能会有所不同。值得研究的东西。如果您使用 GET 请求现有页面,是否需要正常的 4 秒?
            【解决方案7】:

            将您的代码更改为异步 getresponse

            public override WebResponse GetResponse() {
                •••
                IAsyncResult asyncResult = BeginGetResponse(null, null);
                •••
                return EndGetResponse(asyncResult);
            }
            

            Async Get

            【讨论】:

            【解决方案8】:

            可能 Firefox 一次发出多个请求,而您的代码一个一个地执行它们。也许添加线程会加快你的程序。

            【讨论】:

            • 好点。网站是否接受超过 3 个线程?这可以解释为什么一个站点可能会快 3-4 倍,但不会超过 6.5 倍。嗯。我会记住这一点,今晚再试一次
            • 所以我检查了另一个应用程序,我测试的一个站点可以处理 8 个线程。这样就可以解释了。如果这是唯一的原因,我会有点尴尬。
            • 也许 firefox 一次只发出 3 个请求。
            猜你喜欢
            • 1970-01-01
            • 2011-03-27
            • 2011-05-07
            • 2020-11-01
            • 1970-01-01
            • 2017-01-10
            • 2011-08-31
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多