【问题标题】:HTTPWebResponse + StreamReader Very SlowHTTPWebResponse + StreamReader 非常慢
【发布时间】:2010-10-28 10:19:15
【问题描述】:

我正在尝试在 C# 中实现一个有限的网络爬虫(仅适用于几百个站点) 使用 HttpWebResponse.GetResponse() 和 Streamreader.ReadToEnd() ,还尝试使用 StreamReader.Read() 和循环来构建我的 HTML 字符串。

我只下载大约 5-10K 的页面。

这一切都非常缓慢!例如,GetResponse() 平均时间约为半秒,而 StreamREader.ReadToEnd() 平均时间约为 5 秒!

所有站点都应该非常快,因为它们离我的位置非常近,并且拥有快速的服务器。 (在 Explorer 中几乎不需要 D/L)而且我没有使用任何代理。

我的爬虫有大约 20 个线程同时从同一站点读取。这会导致问题吗?

如何大幅减少 StreamReader.ReadToEnd 时间?

【问题讨论】:

    标签: c# performance web-crawler httpwebresponse streamreader


    【解决方案1】:

    HttpWebRequest 可能需要一段时间才能检测到您的proxy settings。尝试将其添加到您的应用程序配置中:

    <system.net>
      <defaultProxy enabled="false">
        <proxy/>
        <bypasslist/>
        <module/>
      </defaultProxy>
    </system.net>
    

    通过缓冲读取以减少对底层操作系统套接字的调用次数,您可能还会看到性能略有提升:

    using (BufferedStream buffer = new BufferedStream(stream))
    {
      using (StreamReader reader = new StreamReader(buffer))
      {
        pageContent = reader.ReadToEnd();
      }
    }
    

    【讨论】:

    • 谢谢!这完全将我的代码从几秒加速到了几毫秒!
    • C++ 中的等效代码是什么? using (...) 在 C++ 中不起作用
    【解决方案2】:

    WebClient 的 DownloadString 是一个简单的 HttpWebRequest 包装器,您可以暂时尝试使用它,看看速度是否有所提高?如果事情变得更快,您能否分享您的代码,以便我们看看它可能有什么问题?

    编辑:

    似乎 HttpWebRequest 观察到了 IE 的“最大并发连接数”设置,这些 URL 是否在同一个域中?您可以尝试增加连接限制,看看是否有帮助?我找到了this article关于这个问题:

    默认情况下,您无法执行更多操作 超过 2-3 个异步 HttpWebRequest(取决于 在操作系统上)。为了覆盖它 (最简单的方法,恕我直言)不要忘记 在下面添加这个 应用程序配置中的部分 文件:

    <system.net>
      <connectionManagement>
         <add address="*" maxconnection="65000" />
      </connectionManagement>
    </system.net>
    

    【讨论】:

    • 尝试使用 WebClient,结果相同(平均时间没有改变)。我还应该提到我有一个 1.5MBPS 的连接,平均 d/l 速度为 180KBPS 我在想也许 20 个线程都同时调用 StreamReader.Read 可能与它有关?还是这无关紧要?
    • 根据我的经验,在这样的连接上,3-4 个线程会使带宽饱和。除非您正在 ping 的网站真的很慢并且您有很多线程在休眠,等待 I/O,否则无需运行更多。
    • 哇!我正在使用异步 HttpWebRequest 加载测试服务器,每个客户端大约有 300 个线程,每个线程都在“串行”下载。更改 maxconnection 设置使每个线程下载数据的速度提高了 10 倍。
    【解决方案3】:

    我遇到了同样的问题,但是当我将HttpWebRequest的Proxy参数设置为null时,它解决了问题。

    UriBuilder ub = new UriBuilder(url);
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create( ub.Uri );
    request.Proxy = null;
    HttpWebResponse response = (HttpWebResponse)request.GetResponse();
    

    【讨论】:

      【解决方案4】:

      您是否尝试过 ServicePointManager.maxConnections?对于类似的事情,我通常将其设置为 200。

      【讨论】:

        【解决方案5】:

        我遇到了同样的问题,但最糟糕的是。 响应 = (HttpWebResponse)webRequest.GetResponse();在我的代码中 在运行更多代码之前延迟了大约 10 秒,之后下载使我的连接饱和。

        库尔特的回答 defaultProxy enabled="false"

        解决了这个问题。现在响应几乎是即时的,我可以以我的连接最大速度下载任何 http 文件 :) 抱歉英语不好

        【讨论】:

          【解决方案6】:

          我发现Application Config方法不起作用,但问题仍然是由于代理设置造成的。我的简单请求过去最多需要 30 秒,现在需要 1 秒。

          public string GetWebData()
          {
                      string DestAddr = "http://mydestination.com";
                      System.Net.WebClient myWebClient = new System.Net.WebClient();
                      WebProxy myProxy = new WebProxy();
                      myProxy.IsBypassed(new Uri(DestAddr));
                      myWebClient.Proxy = myProxy;
                      return myWebClient.DownloadString(DestAddr);
          }
          

          【讨论】:

            【解决方案7】:

            谢谢大家的回答,他们帮助我找到了正确的方向。我也遇到过同样的性能问题,尽管更改应用程序配置文件的建议解决方案(据我所知,该解决方案适用于 Web 应用程序)不符合我的需求,但我的解决方案如下所示:

            HttpWebRequest webRequest;
            
            webRequest = (HttpWebRequest)System.Net.WebRequest.Create(fullUrl);
            webRequest.Method = WebRequestMethods.Http.Post;
            
            if (useDefaultProxy)
            {
                webRequest.Proxy = System.Net.WebRequest.DefaultWebProxy;
                webRequest.Credentials = CredentialCache.DefaultCredentials;
            }
            else
            {
                System.Net.WebRequest.DefaultWebProxy = null;
                webRequest.Proxy = System.Net.WebRequest.DefaultWebProxy;
            }
            

            【讨论】:

              【解决方案8】:

              为什么多线程不能解决这个问题?多线程将最大限度地减少网络等待时间,并且由于您将缓冲区的内容存储在系统内存 (RAM) 中,因此处理文件系统不会出现 IO 瓶颈。因此,需要 82 秒下载和解析的 82 个页面应该需要 15 秒(假设是 4x 处理器)。如果我遗漏了什么,请纠正我。

              ____ 下载主题_____*

              下载内容

              表单流

              阅读内容

              _________________________*

              【讨论】:

                【解决方案9】:

                尝试像这样将 cookie(AspxAutoDetectCookieSupport=1) 添加到您的请求中

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

                【讨论】:

                  猜你喜欢
                  • 2012-04-14
                  • 1970-01-01
                  • 1970-01-01
                  • 2015-09-17
                  • 1970-01-01
                  • 2015-05-22
                  • 1970-01-01
                  • 2017-12-12
                  • 2015-06-14
                  相关资源
                  最近更新 更多