Я пишу приложение для парсинга сайта букмекера. Итоговая цель - получать как можно чаще и быстрее свежую html сайта (в ней содержится нужная мне информация). Так как букмекер банит ip, если с него делать слишком много запросов к сайту, я пользуюсь коллекцией прокси (от 50 до 100 штук), чтобы распределить запросы между.
Язык программы - C#. Я использую асинхронные запросы (httpwebrequest) следующим образом:
ServicePointManager.DefaultConnectionLimit = 1000;
ServicePointManager.Expect100Continue = false;
ServicePointManager.UseNagleAlgorithm = false;
for (var i = 0; i < proxyCollection.Count; i++)
{
var proxyLocal = proxyCollection[i];
var iLocal = i;
Task.Run(async () =>
{
var httpWebRequest = (HttpWebRequest) WebRequest.Create(String.Format("https://bookmaker.com/page{0}", iLocal));
httpWebRequest.Proxy = proxyLocal;
httpWebRequest.PreAuthenticate = true;
httpWebRequest.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
using (var httpWebResponse = (HttpWebResponse) await httpWebRequest.GetResponseAsync())
using (var responseStream = httpWebResponse.GetResponseStream())
using (var streamReader = new StreamReader(responseStream))
{
var stringContent = await streamReader.ReadToEndAsync();
//Тут я обрабатываю данные, которые получил с сайта. Обработка идет очень быстро - проблема не в ней
ProcessStringContent(stringContent);
}
});
}
Все настройки, что я использую для ServicePointManager и для отдельного запроса я указал в коде.
Во-первых, почему-то все запросы не стартуют одновременно. Даже если посмотреть в диспетчер задач и нагрузку сети, то я наблюдаю два или больше пика запросов, между которыми может пройти до нескольких секунд молчания. Очевидно, что я никаких задержек не ставлю нигде и такое поведение странно. Также это поведение проявляется в том, что у меня есть несколько очень быстрых прокси, с которых запрос идет не больше 200мс, но если я запускаю все запросы одновременно, то частенько, по прошествию 5 секунд, запросы с быстрых прокси даже еще не начались.
Во-вторых, суммарное время выполнения всех запросов довольно велико. Наверняка, это связано с первой проблемой, но тем не менее, на это нужно тоже обратить внимание. Если я делаю запрос с каждой прокси по отдельности, синхронно, то наблюдаю время запроса 100-1000мс. Отсюда я ожидаю, что суммарное время всех запросов (100 штук), отправленных одновременно не должно превышать ну, скажем, 2 секунд. Ведь все они обрабатываются асинхронно!
В третьих, что больше всего странно - вышепоказанный код заставляет лагать интерфейс. У меня WPF приложение и я довольно хорошо знаком с понятием потока диспетчера и всем с этим связанным. И все равно у меня вызывает недоумение, почему код, вызванный в новом Task-е и при этом асинхронный может тормозить UI.
Есть только одна мысль, что синхронная операция WebRequest.Create может занимать какое-то время (об этом иногда пишут в интернете, мол для настройки использования прокси и для поиска dns требуется сколько то времени). И получается, что все потоки забиваются созданием запросов и это приводит к лагам. Можно ли как-то все это ускорить (убрать поиск настроек прокси, ускорить поиск днс) и избежать лагов?
Я перепробовал разные комбинации настроек ServicePointManager и не нашел победной.
Я ищу любой помощи в данном вопросе. Интересуют любые мнения по поводу, как правильно организовать в .Net решение нужной мне задачи? В интернете критически мало информации, может быть кто-нибудь поделится опытом? Ведь наверняка существуют решения для частого и быстрого сбора информации с различных сайтов поставщиков.
Заранее спасибо.