none
Многопоточность и HttpWebRequest/Response RRS feed

  • Вопрос

  • Привет всем! Скорее всего вопрос покажется кому-то старым и заезженным, но хочется сказать, что я пересмотрел множество статей про многопоточность и так и не нашел ответа на свой вопрос. Ситуация такая: я пишу парсер, в котором обработка разных по типажу web страниц разбита на методы. Каждый из них устанавливает соединение с сайтом, получает ответ и обрабатывает его. Вот этот метод:

    private static HttpWebResponse connect(string location, string cookie)
            {
                Sem.WaitOne();      //Sem - Семафор с 
                           //ограничением в один поток
    /--------------------------------------------------
                //Добавление заголовков в GET запрос
                string UserAgent = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.162 Safari/535.19";
                string Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
                Uri requestUri = new Uri(location);
                HttpWebRequest myHttpWebRequest = (HttpWebRequest)HttpWebRequest.Create(requestUri);
                myHttpWebRequest.Proxy = Proxy;
                myHttpWebRequest.Method = "GET";
                myHttpWebRequest.UserAgent = UserAgent;
                myHttpWebRequest.Accept = Accept;
                myHttpWebRequest.ContentType = "application/x-www-form-urlencoded";
                myHttpWebRequest.AllowAutoRedirect = false;
                myHttpWebRequest.Headers.Add("Accept-Language", "ru-RU");
                myHttpWebRequest.Headers.Add("Accept-Charset", "windows-1251,utf-8;q=0.7,*;q=0.3");
                myHttpWebRequest.Headers.Add(HttpRequestHeader.Cookie, cookie);
                Sem.Release();
                HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
                return myHttpWebResponse;
            }
    Ближе к делу. Я не знаю, как правильно, безошибочно оптимизировать этот фрагмент кода для множества потоков(тобиж каждый из потоков мог бы вызывать этот метод без особого ограничения и без ошибочно), а также сделать подключение через рандомное Proxy. Что я делал: Я занес список прокси в БД и время от времени пополнял очередь(Queue). Но вот в чем проблема - некоторые прокси принудительно завершают соединение. Думал насчет того, чтобы ставить try/catch на участок кода и выполнять метод заново. Да и сома идея с очередью мне кажется не разумной... 

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

    10 августа 2012 г. 8:27

Ответы

  • Добрый день.

    С прокси не подскажу, видимо вам действительно придется через try/catch реализовывать несколько попыток. А вот в чем проблема с многопоточностью не очень понятно.

    У вас, на первый взгляд, из того, что не из этого метода только внешняя Proxy, если на ней возникаю гонки, то надо их и решать, а так метод должен нормально работатать в нескольких потоках.

    • Помечено в качестве ответа Abolmasov Dmitry 30 августа 2012 г. 13:11
    10 августа 2012 г. 12:33
    Отвечающий
  • "Ну для меня во первых важно знать - есть ли более грамотный способ это все реализовать" - реализовать что? Если вызов медода в множестве потоков, то тут каких либо проблем нет. Только учтите, что слишком большое количество потоков - это тоже зло. "С многопоточностью, с тех пор как я поставил Semaphore на заголовки проблем не стало." -  а какие проблемы были с вязанные с многопоточностью? "очень важно, чтобы все это работало очень быстро. " - ну это уже не только от многопоточности зависит, но и от массы факторов, например скорости сети, и работы самих серверов (если будет большое количество запросов, обработают ли они их).
    • Помечено в качестве ответа Abolmasov Dmitry 30 августа 2012 г. 13:11
    10 августа 2012 г. 13:24
    Модератор

Все ответы

  • Добрый день.

    С прокси не подскажу, видимо вам действительно придется через try/catch реализовывать несколько попыток. А вот в чем проблема с многопоточностью не очень понятно.

    У вас, на первый взгляд, из того, что не из этого метода только внешняя Proxy, если на ней возникаю гонки, то надо их и решать, а так метод должен нормально работатать в нескольких потоках.

    • Помечено в качестве ответа Abolmasov Dmitry 30 августа 2012 г. 13:11
    10 августа 2012 г. 12:33
    Отвечающий
  • Ну для меня во первых важно знать - есть ли более грамотный способ это все реализовать. С многопоточностью, с тех пор как я поставил Semaphore на заголовки проблем не стало. Дело в том, что парсеру нужно обработать более 3*10^6 ссылок, поэтому очень важно, чтобы все это работало очень быстро.

    Тем не менее, спасибо :) Будем копать...

    10 августа 2012 г. 13:03
  • "Ну для меня во первых важно знать - есть ли более грамотный способ это все реализовать" - реализовать что? Если вызов медода в множестве потоков, то тут каких либо проблем нет. Только учтите, что слишком большое количество потоков - это тоже зло. "С многопоточностью, с тех пор как я поставил Semaphore на заголовки проблем не стало." -  а какие проблемы были с вязанные с многопоточностью? "очень важно, чтобы все это работало очень быстро. " - ну это уже не только от многопоточности зависит, но и от массы факторов, например скорости сети, и работы самих серверов (если будет большое количество запросов, обработают ли они их).
    • Помечено в качестве ответа Abolmasov Dmitry 30 августа 2012 г. 13:11
    10 августа 2012 г. 13:24
    Модератор
  • После возвращения HttpWebResponse нужно не забыть его закрыть. Иначе будут утечки памяти, да и вообще класс HttpWebRequest не сможет повторно использовать себя (он хитро сделан, если запросы к одному домену идут, то между запросами подключение не разрывается, а повторно используется).

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


    Для связи [mail]

    17 августа 2012 г. 13:03
  • Какая у вас операционная система? в не сервеных ос есть ограничение на кол-во одновременных запросов.

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

    да. и не забывайте делать закрытие

    HttpWebRequest frequest = WebRequest.Create(url) as HttpWebRequest;

    using (var fresponse = frequest.GetResponse()) { // ..... fresponse.Close(); }



    20 августа 2012 г. 7:39