2010-12-07 2 views
9

Я пишу приложение для определения того, как быстро я могу загружать веб-страницы с помощью C#. Я предоставляю список уникальных доменных имен, затем я создаю X число потоков и выполняю HTTPWebRequests до тех пор, пока не будет уничтожен список доменов. Проблема в том, что независимо от того, сколько потоков я использую, я получаю только 3 страницы в секунду.Ограничение параллелизма на HttpWebRequest

Я обнаружил, что System.Net.ServicePointManager.DefaultConnectionLimit равно 2, но у меня создалось впечатление, что это связано с количеством подключений на домен. Поскольку каждый домен в списке уникален, это не должно быть проблемой.

Затем я обнаружил, что метод GetResponse() блокирует доступ ко всем остальным процессам до закрытия WebResponse: http://www.codeproject.com/KB/IP/Crawler.aspx#WebRequest, я не нашел никакой другой информации в Интернете, чтобы вернуть эту заявку, однако я применил HTTP-запрос, используя и я заметил значительную скорость (4x - 6x).

Так что мои вопросы: кто-нибудь знает, как работают объекты HttpWebRequest ?, есть ли обходное решение помимо того, что было упомянуто выше ?, или есть примеры высокоскоростных веб-сканеров, написанных на C# в любом месте?

+0

Вы можете настроить лимит подключения для каждого домена, но по умолчанию ограничение соединения является глобальным. https://msdn.microsoft.com/en-us/library/fb6y0fyc.aspx – Todd 2016-12-05 01:37:45

ответ

8

Вы пытались использовать методы async, такие как BeginGetResponse()?

Если вы используете .net 4.0, вы можете попробовать этот код. По существу, я использую задачи, чтобы сделать 1000 запросов на определенном сайте (я использую это сделать нагрузочное тестирование приложения на моем Dev машине и я не вижу никаких ограничений как таковые, поскольку мое приложение видит эти запросы в быстрой последовательности)

public partial class Form1 : Form 
    { 
    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     for (int i = 0; i < 1000; i++) 
     { 
     var webRequest = WebRequest.Create(textBox1.Text); 
     webRequest.GetReponseAsync().ContinueWith(t => 
     { 
      if (t.Exception == null) 
      { 
      using (var sr = new StreamReader(t.Result.GetResponseStream())) 
      { 
       string str = sr.ReadToEnd(); 
      } 
      } 
      else 
      System.Diagnostics.Debug.WriteLine(t.Exception.InnerException.Message); 
     }); 
     } 
    } 
    } 

    public static class WebRequestExtensions 
    { 
    public static Task<WebResponse> GetReponseAsync(this WebRequest request) 
    { 
     return Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null); 
    } 
    } 

Поскольку рабочая нагрузка здесь связана с вводом-выводом, нерестовые потоки для выполнения заданий не требуются и на самом деле могут повредить производительность. Использование методов Async в классе WebClient использует порты завершения ввода-вывода и, следовательно, будет намного более производительным и менее ресурсоемким.

3

Вы должны использовать метод BeginGetResponse, который не блокирует и не асинхронен.

При работе с асинхронной привязкой ввода-вывода, только потому, что вы создаете поток для работы ввода-вывода, этот поток по-прежнему будет заблокирован, ожидая, пока аппаратное обеспечение (в данном случае сетевая карта) ответит. Если вы используете встроенный BeginGetResponse, то этот поток будет просто помещать его в очередь на сетевой карте и затем будет доступен для работы. Когда аппаратное обеспечение будет завершено, оно уведомит вас, после чего будет вызван ваш обратный вызов.

1

Я хотел бы отметить, что BeginGetResponse метод не является полностью асинхронно (от MSDN)

BeginGetResponse метод требует некоторых синхронных задач настройки для завершения (разрешение DNS, прокси обнаружения и TCP сокет соединение, например), прежде чем этот метод станет асинхронным. В результате этот метод никогда не следует вызывать в потоке пользовательского интерфейса (UI), потому что это может занять некоторое время, обычно несколько секунд.

Смежные вопросы