Многопоточный HttpWebRequest зависает случайным образом на responseStream

1

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

Я попытался установить

Keep-Alive = false

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;

но я все еще получаю странное поведение, любые идеи?

благодаря

Код 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();
    }
Теги:
multithreading
fiddler
hang
httpwebrequest

3 ответа

1

Свойство Timeout. Получает или задает значение тайм-аута в миллисекундах для методов GetResponse и GetRequestStream. " Значение по умолчанию - 100 000 миллисекунд (100 секунд).

Свойство ReadWriteTimeout: "Получает или устанавливает тайм-аут в миллисекундах при записи или чтении из потока". Значение по умолчанию - 300 000 миллисекунд (5 минут).

Вы устанавливаете Timeout, но оставляете ReadWriteTimeout по умолчанию, поэтому ваши чтения могут занять до пяти минут до тайминга. Вероятно, вы хотите установить ReadWriteTimeout на меньшее значение. Вы также можете ограничить размер загружаемых данных. С помощью моего искателя я иногда натыкался на нескончаемый поток, который в итоге привел бы к исключению из памяти.

Что-то еще, что я заметил при сканировании, заключается в том, что иногда закрытие потока ответов будет зависать. Я обнаружил, что мне нужно было вызвать request.Abort чтобы надежно завершить запрос, если я захочу выйти, прежде чем читать весь поток.

  • 0
    Да, я уже пробовал ReadWriteTimeout, я просто удалил его, потому что я делаю тесты с Fiddler, если Fiddler открыт, проблема никогда не возникает, и ни один запрос не зависает (без использования ReadWriteTimeout), я просто сейчас исследую с fiddler и почему, если я оставлю его открытым, это "исправит" мое приложение.
0

Ниже приведен код, который делает что-то подобное, он также используется для доступа к нескольким веб-сайтам, каждый вызов находится в другой задаче. Разница в том, что я только прочитал поток один раз, а затем проанализировал результаты. Это может быть способ обойти блокировку потока в случайном порядке или, по крайней мере, облегчить его отладку.

       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();
0

В коде нет ничего очевидного.

Почему вы прокомментировали ответ.Close()?

Документация указывает, что соединения могут закончиться, если они явно не закрыты. Ответ, который может быть удален, может закрыть соединение, но просто освобождение всех ресурсов не оптимально, я думаю. Закрытие ответа также закроет поток, чтобы он был закрыт.

Система, зависающая без таймаута, может быть просто сетевой проблемой, создающей объект ответа мертвой утиной, или проблема связана с большим количеством потоков, что приводит к фрагментации памяти.

Глядя на все, что может создать шаблон, может помочь найти источник:

  1. Сколько потоков обычно выполняется (можете ли вы объединить наборы запросов в меньшие потоки)
  2. Как производительность сети в то время, когда поток остановился
  3. Есть ли определенный счет или диапазон, когда это происходит
  4. Какие данные обрабатывались последним, когда это произошло (есть ли какие-либо конкретные управляющие символы или последовательности данных, которые могут нарушить поток)

Хотите задать больше вопросов, но недостаточно репутации, поэтому можете только ответить.

Удачи!

  • 0
    В настоящее время 1 поток = 1 запрос, я думаю, что это не зависит от производительности netowrk, потому что это происходит как на win7, так и на моем сервере с win 2008, это происходит абсолютно случайно на случайных URL-адресах, но все это исправляется, если я продолжу держать fiddler открытым это никогда не зависает, это странно, я не очень разбираюсь в отладке с помощью fiddler, и я впервые пишу многопоточное приложение.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню