Попытка запуска нескольких HTTP-запросов параллельно, но ограничена Windows (реестром)

Я разрабатываю приложение (winforms С#.NET 4.0), где я обращаюсь к функциональности поиска от стороннего пользователя с помощью простого HTTP-запроса. Я вызываю url с параметром, и взамен я получаю небольшую строку с результатом поиска. Достаточно просто.

Однако проблема заключается в том, что мне приходится делать много этих поисков (пару тысяч), и я хотел бы ограничить необходимое время. Поэтому я хотел бы запускать запросы параллельно (скажем, 10-20). Я использую ThreadPool для этого, а короткая версия моего кода выглядит так:

public void startAsyncLookup(Action<LookupResult> returnLookupResult)
{
    this.returnLookupResult = returnLookupResult;

    foreach (string number in numbersToLookup)
    {
        ThreadPool.QueueUserWorkItem(lookupNumber, number);
    }
}

public void lookupNumber(Object threadContext)
{
    string numberToLookup = (string)threadContext;
    string url = @"http://some.url.com/?number=" + numberToLookup;
    WebClient webClient = new WebClient();
    Stream responseData = webClient.OpenRead(url);
    LookupResult lookupResult = parseLookupResult(responseData);

    returnLookupResult(lookupResult);
}

Я заполняю numbersToLookup (a List<String>) из другого места, вызываю startAsyncLookup и предоставляю ему функцию обратного вызова returnLookupResult для возврата каждого результата. Это работает, но я обнаружил, что я не получаю пропускную способность, которую хочу.

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

Затем коллега сказал мне, что это может быть ограничением в Windows. Я немного искал googled и нашел среди других этот пост, говорящий, что по умолчанию Windows ограничивает количество одновременных запросов на один и тот же веб-сервер до 4 для HTTP 1.0 и до 2 для HTTP 1.1 (для HTTP 1.1 это фактически соответствует спецификации (RFC2068)).

То же самое сообщение, о котором говорилось выше, также предоставило возможность увеличить эти ограничения. Добавив два значения реестра в [HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings] (MaxConnectionsPerServer и MaxConnectionsPer1_0Server), я мог бы сам это контролировать.

Итак, я попробовал это (сидел до 20), перезапустил свой компьютер и снова попытался запустить свою программу. К сожалению, это ничуть не помогло. Я также следил за Монитором ресурсов (см. Снимок экрана) во время запуска пакетного поиска, и я заметил, что мое приложение (одно с заголовок затемнен) все еще использовал только два TCP-соединения.

Итак, вопрос в том, почему это не работает? Является ли сообщение, связанное с неправильными значениями реестра? Возможно, это невозможно "взломать" в Windows больше (я на Windows 7)?

Любые идеи будут высоко оценены:)

И на всякий случай, когда кто-то должен удивляться, я также пробовал с различными настройками MaxThreads на ThreadPool (от 10 до 100), и это, похоже, не повлияло на мою пропускную способность, поэтому проблема не должна быть там тоже.

Ответ 1

Это вопрос ServicePoint. Это обеспечивает управление соединениями для HTTP-соединений. Максимальное количество одновременных подключений по умолчанию, разрешенных объектом ServicePoint, равно 2. Поэтому, если вам нужно увеличить его, вы можете использовать свойство ServicePointManager.DefaultConnectionLimit. Просто проверьте ссылку в MSDN там, вы можете увидеть образец. И установите нужное значение.

Ответ 2

Для более быстрой ссылки для кого-то. Чтобы увеличить лимит подключения для каждого хоста, вы можете сделать это в своем Main() или в любое время, прежде чем начинать делать HTTP-запросы.

   System.Net.ServicePointManager.DefaultConnectionLimit = 1000; //or some other number > 4

Ответ 3

Огонь и забыть этот метод из основного метода. Пользователь Icognito прав, только два потока могут играть одновременно.

private static void openServicePoint()
{
    ServicePointManager.UseNagleAlgorithm = true;
    ServicePointManager.Expect100Continue = true;
    ServicePointManager.CheckCertificateRevocationList = true;
    ServicePointManager.DefaultConnectionLimit = 10000;
    Uri MS = new Uri("http://My awesome web site");
    ServicePoint servicePoint = ServicePointManager.FindServicePoint(MS);
}

Ответ 4

Для Internet Explorer 8: Запустите редактор реестра и перейдите к следующему ключу HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE_MAXCONNECTION SPERSERVER

и

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE_MAXCONNECTION SPER1_0SERVER

Если FEATURE_MAXCONNECTIONSPERSERVER и FEATURE_MAXCONNECTIONSPER1_0SERVER отсутствуют, создайте их. Теперь создайте значение DWORD, называемое iexplore.exe, для обоих вспомогательных ключей (см. Выше) и установите их значение в 10 или любой желаемый номер.