HTTPWebResponse + StreamReader 非常慢
Posted
技术标签:
【中文标题】HTTPWebResponse + StreamReader 非常慢【英文标题】:HTTPWebResponse + StreamReader Very Slow 【发布时间】: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 时间?
【问题讨论】:
【参考方案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 );
【讨论】:
以上是关于HTTPWebResponse + StreamReader 非常慢的主要内容,如果未能解决你的问题,请参考以下文章
(HttpWebResponse)request.GetResponse() throwing 操作已经超时
HttpClientWebClientHttpWebRequestHttpWebResponse
解决 HttpWebResponse.GetResponse()一直提示超时
从 HttpWebRequest 和 HttpWebResponse 获取 Http 状态码(200、301、404 等)