Попытка запустить несколько HTTP-запросов параллельно, но ограничена Windows (реестр) - PullRequest
62 голосов
/ 02 июня 2010

Я занимаюсь разработкой приложения (winforms C # .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 (List<String>) из другого места, звоню startAsyncLookup и предоставляю ему функцию обратного вызова returnLookupResult для возврата каждого результата. Это работает, но я обнаружил, что не получаю желаемую пропускную способность.

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

Затем коллега сообщил мне, что это может быть ограничением в Windows. Я немного погуглил и обнаружил среди прочего этот пост о том, что по умолчанию 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), и это никак не сказалось на моей пропускной способности, поэтому проблема не должна быть там тоже.

Ответы [ 4 ]

95 голосов
/ 02 июня 2010

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

28 голосов
/ 23 октября 2012

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

   System.Net.ServicePointManager.DefaultConnectionLimit = 1000; //or some other number > 4
2 голосов
/ 24 февраля 2015

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

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);
}
0 голосов
/ 02 июня 2010

Для 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 Value с именем iexplore.exe для обоих вложенных ключей (перечисленных выше) и установите для них значение 10 или любое другое желаемое число.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...