Nano Hash - криптовалюты, майнинг, программирование

HttpWebResponse не масштабируется для одновременных исходящих запросов

У меня есть серверное приложение ASP.NET 3.5, написанное на C #. Он выполняет исходящие запросы к REST API с помощью HttpWebRequest и HttpWebResponse.

Я установил тестовое приложение для отправки этих запросов в отдельные потоки (чтобы смутно имитировать параллелизм с сервером).

Обратите внимание, что это больше вопрос Mono / Environment, чем вопрос кода; поэтому имейте в виду, что приведенный ниже код не является дословным; просто вырезать / вставить функциональные биты.

Вот какой-то псевдокод:

// threaded client piece
int numThreads = 1;
ManualResetEvent doneEvent;

using (doneEvent = new ManualResetEvent(false))
        {

            for (int i = 0; i < numThreads; i++)
            {

                ThreadPool.QueueUserWorkItem(new WaitCallback(Test), random_url_to_same_host);

            }
            doneEvent.WaitOne();
        }

void Test(object some_url)
{
    // setup service point here just to show what config settings Im using
    ServicePoint lgsp = ServicePointManager.FindServicePoint(new Uri(some_url.ToString()));

        // set these to optimal for MONO and .NET
        lgsp.Expect100Continue = false;
        lgsp.ConnectionLimit = 100;
        lgsp.UseNagleAlgorithm = true;
        lgsp.MaxIdleTime = 100000;        

    _request = (HttpWebRequest)WebRequest.Create(some_url);


    using (HttpWebResponse _response = (HttpWebResponse)_request.GetResponse())
    {
      // do stuff
    } // releases the response object

    // close out threading stuff

    if (Interlocked.Decrement(ref numThreads) == 0)
    {
        doneEvent.Set();
    }
}

Если я запускаю приложение на своем локальном компьютере для разработки (Windows 7) на веб-сервере Visual Studio, я могу увеличить numThreads и получить такое же среднее время отклика с минимальными вариациями, будь то 1 «пользователь» или 100.

При публикации и развертывании приложения на Apache2 в среде Mono 2.10.2 время отклика масштабируется почти линейно. (т.е. 1 поток = 300 мс, 5 потоков = 1500 мс, 10 потоков = 3000 мс). Это происходит независимо от конечной точки сервера (другое имя хоста, другая сеть и т. Д.).

При использовании IPTRAF (и других сетевых инструментов) создается впечатление, что приложение открывает только 1 или 2 порта для маршрутизации всех соединений, а оставшиеся ответы должны ждать.

Мы создали аналогичное приложение PHP и развернули его в Mono с теми же запросами и соответствующим масштабированием ответов.

Я прошел через каждый отдельный параметр конфигурации, который я мог придумать для Mono и Apache, и ТОЛЬКО параметр, который отличается между двумя средами (по крайней мере, в коде), заключается в том, что иногда ServicePoint SupportsPipelining = false в Mono, в то время как это верно из моего машина.

Кажется, что ConnectionLimit (по умолчанию 2) по какой-то причине не изменяется в Mono, но я устанавливаю его на более высокое значение как в коде, так и в web.config для указанного хоста (ов).

Либо я и моя команда упускаем из виду что-то существенное, либо это какая-то ошибка в Mono.


  • Вы нашли решение? 07.02.2013

Ответы:


1

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

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

Во-вторых, проблема с детализацией блокировки в самом классе ServicePoint. Если вы декомпилируете и посмотрите на источник ключевого слова lock, вы обнаружите, что он использует сам экземпляр для синхронизации и делает это во многих местах. Поскольку экземпляр точки обслуживания используется совместно с веб-запросами для данного хоста, по моему опыту, это имеет тенденцию к возникновению узких мест, поскольку открывается больше HttpWebRequests, что приводит к его плохому масштабированию. Второй момент - в основном личное наблюдение и поиск источника, так что отнеситесь к нему с недоверием; Я бы не стал считать это авторитетным источником.

К сожалению, в то время, когда я работал с ним, я не нашел разумной замены. Теперь, когда выпущен веб-API ASP.NET, вы можете предоставить HttpClient взгляд. Надеюсь, это поможет.

03.04.2012
  • Джесси, спасибо за информацию. Установка ServicePointManager DefaultConnectionLimit по-прежнему просто устанавливает его для каждой точки ServicePoint / конечной точки, поэтому я не знаю, поможет ли это обойти проблему блокировки, которую вы описываете на уровне SP. Я, конечно, ожидал бы, что ServicePoint станет узким местом по мере роста потоков / запросов, но не так резко. И все еще кажется, что запросы уходят без проблем, но ответы ждут. В качестве альтернативы мне придется изучить HttpClient. 04.04.2012
  • Re: DefaultConnectionLimit - я не утверждаю, что он будет творить чудеса, но он обходит вызов блокировки (this) в установщике для ConnectionLimit в самом ServicePoint. Что касается масштабирования, то впечатление было такое же. Я до сих пор не могу утверждать, что по-настоящему понимаю, почему узкое место возникает так сильно. Есть несколько конструкций синхронизации для получения ответа и, опять же, для получения потоков. В вашем случае я бы предположил, что переход с локального на нелокальный происходит из-за дополнительной задержки с внешним сервером ... но, опять же, это чистое предположение. 04.04.2012
  • DefaultConnectionLimit ничего не изменил (и удаление ConnectionLimit на объекте SP вернуло его значение по умолчанию, равное 2). Различие от локального к нелокальному определенно связано с Mono / средой, поскольку у PHP-скрипта не было проблем - те же запросы. Это то, что я пытаюсь докопаться до сути, исходя из предположения, что это связано с тем, как Mono обрабатывает эти ответы. 04.04.2012
  • Для записи, мы (в настоящее время) не используем методы Async для BeginGetResponse и т.д., и я думаю, что это может быть проблемой. Поскольку неасинхронный GetResponse по-прежнему использует IOCP (порты завершения ввода-вывода), которые, похоже, различаются в зависимости от ОС, что объясняет различия в производительности нашей среды. Использование методов Async, похоже, сработает при беглом тесте. Ссылка: ссылка 04.04.2012
  • Интересный. Я не понимал, что неасинхронные методы все еще используют порты завершения ввода-вывода. Как вы упомянули, это должно быть то, что учитывает Mono, чего не учитывает стандартная структура. К сожалению, это избавляет меня от лишних идей, кроме как заглядывать в исходный код Mono. Если мне удастся выкроить немного свободного времени, я могу попытаться просто посмеяться, но я не жду моментов ах-ха. Думали ли вы об открытии заявки на это с командой разработчиков Mono? 04.04.2012
  • У меня нет - я хочу убедиться, что я все покрыл, прежде чем беспокоить команду разработчиков. Например, еще одна загвоздка в этом уравнении - это SSL, где наши стандартные HTTP-запросы масштабируются (через async) соответствующим образом, а HTTPS-вызовы - нет. Все еще пытаемся определить, является ли это проблемой Mono или проблемой сети с нашей стороны. Если я не могу изолировать его от нашей среды, я могу привязать группу Mono. Спасибо за вашу помощь в этом вопросе! 04.04.2012
  • Не за что. Извините, что я не смог найти окончательный ответ. Удачи. 04.04.2012
  • Я думаю, что ответ этого парня не принимает во внимание, что вопрос касается Mono, поэтому голосование против 01.08.2013
  • @knocte - Вы, конечно, имеете право на свое мнение, но я с уважением не согласен. Обсуждение было сосредоточено вокруг использования задокументированного открытого интерфейса класса, общего для Mono и CLR, для решения проблемы. Я не уверен, как бы вы ожидали, что это будет выглядеть, если бы я принял во внимание, что вопрос касается Mono. ИМХО, голосование "против" кажется неоправданным. 02.08.2013

  • 2

    Я знаю, что это довольно давно, но я помещаю это здесь на случай, если это может помочь кому-то еще, кто столкнется с этой проблемой. Мы столкнулись с той же проблемой с параллельными исходящими HTTPS-запросами. Есть несколько проблем.

    Во-первых, насколько я могу судить, ServicePointManager.DefaultConnectionLimit не изменил ограничение на количество подключений. Установка этого значения на 50, создание нового соединения, а затем проверка предела количества подключений в точке обслуживания для нового соединения говорит о 2. Установка его на этой точке обслуживания на 50 один раз работает и сохраняется для всех подключений, которые в конечном итоге будут проходить. этот пункт обслуживания.

    Вторая проблема, с которой мы столкнулись, была связана с потоками. Текущая реализация пула монопотоков создает не более 2 новых потоков в секунду. Это вечность, если вы выполняете много параллельных запросов, которые начинаются в одно и то же время. Чтобы противодействовать этому, мы попытались установить для ThreadPool.SetMinThreads более высокое значение. Похоже, что Mono создает только до 1 нового потока, когда вы делаете этот вызов, независимо от разницы между текущим количеством потоков и желаемым числом. Мы смогли обойти это, вызывая SetMinThreads в цикле до тех пор, пока в пуле потоков не будет желаемого количества незанятых потоков.

    Я обнаружил ошибку, касающуюся последней проблемы, потому что она, как я уверен, не работает должным образом: https://bugzilla.xamarin.com/show_bug.cgi?id=7055

    11.09.2012
  • Можно подтвердить, что ServicePointManager.DefaultConnectionLimit не действует в моно, ограничение по-прежнему равно 2 14.02.2013
  • Установка его в app.config или web.config работает ... однако оказывается контрпродуктивным в Mono с чем-либо, кроме 2, что значительно снижает пропускную способность ( ?!). Также ServicePoint.Connections всегда сообщает 0, тогда как Windows сообщает до и чуть выше ConnectionLimit ... 14.02.2013

  • 3

    Если @ jake-moshenko прав насчет того, что ServicePointManager.DefaultConnectionLimit не имеет никакого эффекта при изменении в Mono, сообщите об этом как об ошибке в http://bugzilla.xamarin.com/.

    Однако я бы попробовал кое-что, прежде чем полностью отбросить это как проблему Mono:

    1. Попробуйте использовать сборщик мусора SGen вместо старого boehm, передав --gc=sgen в качестве флага mono.
    2. Если вышеперечисленное не помогает, обновитесь до Mono 3.2 (который, по умолчанию, тоже SGEN GC), потому что с тех пор, как вы задали вопрос, было внесено много исправлений.
    3. Если вышеперечисленное не помогает, создайте свою собственную Mono (основную ветку), как этот важный запрос на перенос о многопоточности недавно было объединено.
    4. Если описанное выше не помогает, создайте свой собственный Mono с добавленным этим запросом на перенос. Если это решит вашу проблему, добавьте «+1» к запросу на перенос. Возможно, это исправление для ошибки 7055.
    31.07.2013
    Новые материалы

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

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

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

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

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..