多线程HttpWebRequest随机挂起在responseStream上
本文关键字:responseStream 挂起 HttpWebRequest 随机 多线程 | 更新日期: 2023-09-27 18:14:25
我正在编写一个多线程网络爬虫,每秒使用数百个线程执行大量并发httpwebrequest,应用程序工作得很好,但有时(随机)其中一个webrequest挂在getResponseStream()上完全忽略超时(这发生在我并发执行数百个请求时)使爬行过程永不结束,奇怪的是,与fiddler这永远不会发生,应用程序永远不会挂起,因为它是随机发生的,所以很难调试。
我试着设置
Keep-Alive = false
ServicePointManager。
安全协议=安全协议类型。但我仍然得到奇怪的行为,有什么想法吗?
感谢HttpWebRequest代码:
public static string RequestHttp(string url, string referer, ref CookieContainer cookieContainer_0, IWebProxy proxy)
{
string str = string.Empty;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
request.UserAgent = randomuseragent();
request.ContentType = "application/x-www-form-urlencoded";
request.Accept = "*/*";
request.CookieContainer = cookieContainer_0;
request.Proxy = proxy;
request.Timeout = 15000;
request.Referer = referer;
//request.ServicePoint.MaxIdleTime = 15000;
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
using (Stream responseStream = response.GetResponseStream())
{
List<byte> list = new List<byte>();
byte[] buffer = new byte[0x400];
int count = responseStream.Read(buffer, 0, buffer.Length);
while (count != 0)
{
list.AddRange(buffer.ToList<byte>().GetRange(0, count));
if (list.Count >= 0x100000)
{
break;
}
count = 0;
try
{
HERE IT HANGS SOMETIMES ---> count = responseStream.Read(buffer, 0, buffer.Length);
continue;
}
catch
{
continue;
}
}
//responseStream.Close();
int num2 = 0x200 * 0x400;
if (list.Count >= num2)
{
list.RemoveRange((num2 * 3) / 10, list.Count - num2);
}
byte[] bytes = list.ToArray();
str = Encoding.Default.GetString(bytes);
Encoding encoding = Encoding.Default;
if (str.ToLower().IndexOf("charset=") > 0)
{
encoding = GetEncoding(str);
}
else
{
try
{
encoding = Encoding.GetEncoding(response.CharacterSet);
}
catch
{
}
}
str = encoding.GetString(bytes);
// response.Close();
}
}
return str.Trim();
}
Timeout属性"获取或设置GetResponse和GetRequestStream方法的超时值(以毫秒为单位)。"默认值为100,000毫秒(100秒)。
ReadWriteTimeout属性,"获取或设置写入或读取流时的毫秒超时。"默认值为300,000毫秒(5分钟)。
您正在设置Timeout
,但将ReadWriteTimeout
保留为默认值,因此您的读取可能需要长达五分钟的时间才能超时。您可能需要将ReadWriteTimeout
设置为较低的值。您还可以考虑限制下载的数据大小。在我的爬虫中,我有时会偶然发现一个无休止的流,最终会导致内存不足异常。
我在爬行时注意到的另一件事是,有时关闭响应流会挂起。我发现如果我想在读取整个流之前退出,我必须调用request.Abort
来可靠地终止请求。
您提供的代码中没有任何明显的内容。
你为什么注释response.Close() out?
文档提示如果不显式关闭连接可能会耗尽。处理响应可能会关闭连接,但我认为仅仅释放所有资源并不是最优的。关闭响应也将关闭流,以使其被覆盖。
没有超时的系统挂起可能只是网络问题,使响应对象成为dead duck,或者问题是由于线程数量过多导致内存碎片。
查看任何可能产生模式的东西可能有助于找到来源:
- 通常有多少线程在运行(你能在更少的线程中捆绑请求集吗)
- 线程停止时的网络性能如何
- 是否有特定的计数或范围
- 发生时最后处理的数据(是否有任何特定的控制字符或数据序列可以打乱流)
想问更多的问题,但没有足够的信誉,所以只能回复。
祝你好运!
下面是一些做类似事情的代码,它也用于访问多个网站,每个调用都在不同的任务中。不同之处在于,我只读取流一次,然后解析结果。这可能是一种绕过流读取器随机锁定的方法,或者至少使其更容易调试。
try
{
_webResponse = (HttpWebResponse)_request.GetResponse();
if(_request.HaveResponse)
{
if (_webResponse.StatusCode == HttpStatusCode.OK)
{
var _stream = _webResponse.GetResponseStream();
using (var _streamReader = new StreamReader(_stream))
{
string str = _streamReader.ReadToEnd();