连续十次请求后的HttpWebRequest超时

时间:2009-07-28 04:21:56

标签: .net vb.net httpwebrequest

我正在为特定网站编写网络抓取工具。该应用程序是一个VB.Net Windows窗体应用程序,使用多个线程 - 每个Web请求是连续的。但是,在十次成功的页面检索之后,每个连续的请求都会超时。

我已经回顾了已经在SO上发布的类似问题,并在我的GetPage例程中实现了推荐的技术,如下所示:

Public Function GetPage(ByVal url As String) As String
    Dim result As String = String.Empty

    Dim uri As New Uri(url)
    Dim sp As ServicePoint = ServicePointManager.FindServicePoint(uri)
    sp.ConnectionLimit = 100

    Dim request As HttpWebRequest = WebRequest.Create(uri)
    request.KeepAlive = False
    request.Timeout = 15000

    Try
        Using response As HttpWebResponse = DirectCast(request.GetResponse, HttpWebResponse)
            Using dataStream As Stream = response.GetResponseStream()
                Using reader As New StreamReader(dataStream)
                    If response.StatusCode <> HttpStatusCode.OK Then
                        Throw New Exception("Got response status code: " + response.StatusCode)
                    End If
                    result = reader.ReadToEnd()
                End Using
            End Using
            response.Close()
        End Using

    Catch ex As Exception
        Dim msg As String = "Error reading page """ & url & """. " & ex.Message
        Logger.LogMessage(msg, LogOutputLevel.Diagnostics)
    End Try

    Return result

End Function

我错过了什么吗?我没有关闭或处理应该是的对象吗?似乎很奇怪,它总是在连续十次请求之后发生。

注意:

  1. 在此方法所在的类的构造函数中,我有以下内容:

    ServicePointManager.DefaultConnectionLimit = 100

  2. 如果我将KeepAlive设置为true,则会在五次请求后开始超时。

  3. 所有请求均针对同一域中的网页。

  4. 修改

    我在两次到七秒之间的每个网络请求之间添加了延迟,这样我就不会“锤击”网站或尝试DOS攻击。但是,问题仍然存在。

6 个答案:

答案 0 :(得分:4)

我今天遇到了这个问题,我的决议是确保响应始终关闭。

我认为你需要在使用中抛出异常之前放入response.Close()。

Using response As HttpWebResponse = DirectCast(request.GetResponse, HttpWebResponse) 
        Using dataStream As Stream = response.GetResponseStream() 
            Using reader As New StreamReader(dataStream) 
                If response.StatusCode <> HttpStatusCode.OK Then 
                    response.Close()  
                    Throw New Exception("Got response status code: " + response.StatusCode) 
                End If 
                result = reader.ReadToEnd() 
            End Using 
        End Using 
        response.Close() 
    End Using

答案 1 :(得分:3)

我认为该网站有一些DOS保护,当它受到许多rapis请求的攻击时会启动。您可能想尝试在webrequest上设置UserAgent。

答案 2 :(得分:2)

我使用了以下解决方案,它对我有用。希望它对你也有帮助。

在变量形式上声明“全局”。

HttpWebRequest myHttpWebRequest;
HttpWebResponse myHttpWebResponse;

然后在每次连接后始终使用myHttpWebResponse.Close();

myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
myHttpWebResponse.Close();

答案 3 :(得分:1)

我知道这是一个老问题,但我最近遇到了这个问题(由于我的目标环境使用4.0并且不允许任何外部程序集引用)

我做了一些挖掘但是从.NET内部工作的角度来看,找到了各种修复并且非常有趣

ServicePointManager.DefaultConnectionLimit = 100;

ServicePointManager在内部处理由多个HttpWebRequest对象创建的实际HTTP请求。问题是,这些不会自动关闭,并且HttpWebRequest不会立即收集垃圾

所以我发现了一些非常有趣的东西 - 如果我让HttpWebRequest成为一个实例级变量而且我在切换引用后强制进行垃圾收集......它可以工作(没有DefaultConnectionLimit = 100 hack)

private HttpWebRequest Request { get; set; }

public void MyMethod() {
   Request = (HttpWebRequest)HttpWebRequest.Create("http://myUrl");
   GC.Collect();
   GC.WaitForFullGCComplete();
}

每次在方法中创建新的局部变量之前。这似乎解决了我的问题 - 可能有点太晚了,无法帮助你,但我想我会分享以防其他人遇到这个问题

答案 4 :(得分:1)

如果服务器正在使用数据库并且没有正确关闭每个数据库连接,则可能会在最大值时收到错误(例如状态码502)。达到连接限制(直到数据库连接超时)。 在这种情况下,解决方案只是“睡眠”。给定时间的webrequest线程。 此外,您应确保在处理后关闭每个请求和响应流(最好通过使用&#39;使用&#39;语句):

答案 5 :(得分:0)

myRequest.Connection =“关闭”; 将使服务器关闭连接,这将使连接管理器也关闭连接。