Тайм-Ауты HttpWebRequest После Десяти Последовательных Запросов



Я пишу веб-искатель для конкретного сайта. Приложение представляет собой VB.Net приложение Windows Forms, которое не использует несколько потоков - каждый веб-запрос является последовательным. Однако после десяти успешных попыток извлечения страницы каждый последующий запрос заканчивается.



Я рассмотрел аналогичные вопросы, уже опубликованные здесь на 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. Все запросы на страницы в одном и том же домен.



EDIT



Я добавил задержку между каждым веб-запросом от двух до семи секунд, чтобы не было похоже, что я" забиваю " сайт или пытаюсь атаковать DOS. Однако проблема все равно возникает.
558   6  

6 ответов:

Я думаю, что сайт имеет какую-то защиту DOS, которая срабатывает, когда на него попадает несколько запросов rapis. Вы, возможно, захотите попробовать установить юзерагент на запросы WebRequest.

Я столкнулся с этим вопросом сегодня, и моя резолюция состояла в том, чтобы гарантировать, что ответ был закрыт во все времена.

Я думаю, что вам нужно поставить в ответе.Закройте (), прежде чем вы бросите свое исключение внутри using.

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

Я использовал следующее решение, и оно работает для меня. Надеюсь, вам это тоже поможет.

Объявляем" глобальными " по форме переменные.

HttpWebRequest myHttpWebRequest;
HttpWebResponse myHttpWebResponse;

Затем всегда используйте myHttpWebResponse.Close(); после каждого соединения.

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

Я знаю, что это старый вопрос, но у меня недавно была эта проблема (из-за моей целевой среды, использующей 4.0 и не допускающей никаких внешних ссылок на сборки)

Я немного покопался, однако, и нашел своего рода исправление, и это очень интересно с точки зрения внутренней работы .NET

ServicePointManager.DefaultConnectionLimit = 100;

ServicePointManager внутренне обрабатывает фактический HTTP-запрос, созданный несколькими объектами HttpWebRequest ..проблема в том, что они не закрываются автоматически, а HttpWebRequest-нет. получает мусор, собранный немедленно

Итак, я нашел кое-что очень интересное – если я делаю HttpWebRequest переменной уровня экземпляра и заставляю сборку мусора после переключения ссылки ... это работает (без DefaultConnectionLimit = 100 hack)

private HttpWebRequest Request { get; set; }

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

До этого я каждый раз создавал новую локальную переменную в методе. Это, казалось, решило мою проблему-вероятно, немного слишком поздно, чтобы помочь вам, но я подумал, что поделюсь, если кто-нибудь еще столкнется с этим

Если сервер использует базу данных и не закрывает каждое соединение с базой данных должным образом, вы можете получить сообщение об ошибке (например, statuscode 502) при максимальном значении. соединение ограничено (до истечения времени ожидания соединения с базой данных). Решением в этом случае является только "спящий" поток webrequest в течение заданного времени. Кроме того, вы должны убедиться, что каждый поток запросов и ответов закрывается после обработки (в лучшем случае с помощью оператора Using):

MyRequest.Соединение = " Закрыть"; заставит сервер закрыть соединение, которое заставит диспетчер соединений закрыть соединение тоже.

Comments

    Ничего не найдено.