Что ограничивает количество одновременных подключений, которые мое приложение ASP.NET может установить с веб-службой?

90

У меня есть приложение ASP.NET 4.0, работающее поверх IIS 7.5 на 64-битной машине Windows Server 2008 R2 Enterprise с огромным количеством ОЗУ, ЦП, диска и т. Д.

С каждым веб-запросом приложение ASP.NET подключается к серверной веб-службе (через необработанные сокеты), которая работает на том же компьютере.

Проблема: похоже, что-то ограничивает количество одновременных подключений к серверной веб-службе. Подозрительно, но количество одновременных подключений достигает 16.

Я нашел эту ключевую статью от Microsoft, в которой объясняется, как настроить параметры IIS для размещения приложений ASP.NET, которые делают множество запросов веб-служб: http://support.microsoft.com/?id=821268#tocHeadRef

Я следил за рекомендациями статьи, но все равно не повезло. Настройка, которая особенно интересна, - это maxconnectionнастройка, которую я даже повысил до 999.

Есть идеи, что еще может дросселировать соединения?

Примечание. Когда я исключил IIS из смеси и заставил клиентов подключаться напрямую к серверной веб-службе, она с радостью откроет столько соединений, сколько мне нужно, поэтому я уверен, что серверная часть не является узким местом. Это должно быть что-то в области IIS / ASP.NET.

Вот соответствующий раздел, machine.configкоторый, я уверен, читается приложением (проверено appcmd.exe):

<system.web>
    <processModel autoConfig="false" maxWorkerThreads="100" maxIoThreads="100" minWorkerThreads="50" />
    <httpRuntime minFreeThreads="176" minLocalRequestFreeThreads="152"/>

    <httpHandlers />

    <membership>
        <providers>
            <add name="AspNetSqlMembershipProvider"
                type="System.Web.Security.SqlMembershipProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
                connectionStringName="LocalSqlServer"
                enablePasswordRetrieval="false"
                enablePasswordReset="true"
                requiresQuestionAndAnswer="true"
                applicationName="/"
                requiresUniqueEmail="false"
                passwordFormat="Hashed"
                maxInvalidPasswordAttempts="5"
                minRequiredPasswordLength="7"
                minRequiredNonalphanumericCharacters="1"
                passwordAttemptWindow="10"
                passwordStrengthRegularExpression="" />
        </providers>
    </membership>

    <profile>
        <providers>
            <add name="AspNetSqlProfileProvider" connectionStringName="LocalSqlServer" applicationName="/"
                type="System.Web.Profile.SqlProfileProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
        </providers>
    </profile>

    <roleManager>
        <providers>
            <add name="AspNetSqlRoleProvider" connectionStringName="LocalSqlServer" applicationName="/"
                type="System.Web.Security.SqlRoleProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
            <add name="AspNetWindowsTokenRoleProvider" applicationName="/"
                type="System.Web.Security.WindowsTokenRoleProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
        </providers>
    </roleManager>
</system.web>
<system.net>
    <connectionManagement>
        <add address="*" maxconnection="999"/>
    </connectionManagement>
</system.net>
Роб Соберс
источник
У @DanB есть хороший момент - как вы измеряете количество одновременных подключений?
Джереми МакГи,
@JeremyMcGee Я измеряю количество одновременных подключений, запустив TCPView на сервере, чтобы узнать, сколько внутренних подключений выполняется рабочими процессами IIS.
Роб Соберс,
Веб-клиенты работают на независимых компьютерах или на одном компьютере? (Проверка отсутствия троттлинга на стороне клиента.)
Джереми МакГи,
3
@JeremyMcGee Отдельные машины. 1 клиент-серверное соединение на машину. Кроме того, мы знаем, что где-то в сети нет дросселирования, потому что, когда мы напрямую попадаем на серверную часть (что также происходит через HTTP), мы не сталкиваемся с узким местом.
Роб Соберс,
1
Роб, ты когда-нибудь находил окончательное решение этой проблемы?
electronicKT

Ответы:

104

Большинство ответов, представленных здесь, относятся к количеству входящих запросов к вашей серверной веб-службе, а не к количеству исходящих запросов, которые вы можете сделать из своего приложения ASP.net в свою внутреннюю службу.

Здесь не ваш серверный веб-сервис регулирует частоту запросов, а количество открытых соединений, которые ваше вызывающее приложение желает установить с той же конечной точкой (с тем же URL).

Вы можете снять это ограничение, добавив следующий раздел конфигурации в файл machine.config:

<configuration>
  <system.net>
    <connectionManagement>
      <add address="*" maxconnection="65535"/>
    </connectionManagement>
  </system.net>
</configuration>

Вы, конечно, можете выбрать более разумное число, если хотите, например, 50 или 100 одновременных подключений. Но приведенное выше откроет его вплоть до макс. Вы также можете указать конкретный адрес для правила ограничения открытия, указанного выше, вместо символа «*», обозначающего все адреса.

Документация MSDN для System.Net.connectionManagement

Еще один отличный ресурс для понимания ConnectManagement в .NET

Надеюсь, это решит вашу проблему!

РЕДАКТИРОВАТЬ: Ой, я вижу, что у вас есть управление подключением, упомянутое в вашем коде выше. Я оставлю приведенную выше информацию, поскольку она актуальна для будущих тех, кто столкнется с той же проблемой. Однако обратите внимание, что в настоящее время на большинстве современных серверов есть 4 разных файла machine.config!

Существует .NET Framework v2, работающий как под 32-битной, так и с 64-битной версиями, а также .NET Framework v4, также работающий как под 32-битной, так и с 64-битной версиями. В зависимости от выбранных вами настроек для пула приложений вы можете использовать любой из этих 4 разных файлов machine.config! Пожалуйста, проверьте все 4 файла machine.config, которые обычно находятся здесь:

  • C: \ Windows \ Microsoft.NET \ Framework \ v2.0.50727 \ CONFIG
  • C: \ Windows \ Microsoft.NET \ Framework64 \ v2.0.50727 \ CONFIG
  • C: \ Windows \ Microsoft.NET \ Framework \ v4.0.30319 \ Config
  • C: \ Windows \ Microsoft.NET \ Framework64 \ v4.0.30319 \ Config
БенСуэйн
источник
Ага, я прикрыл эту базу. В любом случае спасибо, @BenSwayne! Я убедился, что модифицировал правильный machine.config(64-битный 4.0).
Роб Соберс,
@RobSobers: В этом случае я бы немного подозрительно отнесся к коду реализации. Возможно, у вас заканчиваются потоки или что-то в этом роде? Можете ли вы добавить код вызова веб-службы TcpClient в консольное приложение и посмотреть, сможете ли вы добиться более высокой скорости запросов? Это докажет, является ли это конкретной конфигурацией IIS или более широкой конфигурацией .NET или вашим кодом.
BenSwayne
Эта линия идет на клиентской машине?
Ури Абрамсон
спасибо, ваши настройки в сочетании с настройкой processModel из codeproject.com/Articles/133738/… исправлено "ISAPI 'C: \ windows \ Microsoft.Net \ Framework \ v2.0.050727 \ aspnet_isapi.dll' сообщил о себе как о нездоровом по следующей причине : Проблема «Обнаружен тупик»
Закос
@BenSwayne применима ли та же концепция к SMTP-соединениям? Я разрабатываю приложение для массовой рассылки электронной почты, поэтому будет ли это свойство ConnectionManagement также полезно при отправке массовых рассылок (с использованием многопоточности для функции mail.send )?
vibs2006
7

Я понимаю, что вопрос может быть довольно старым, но вы говорите, что серверная часть работает на том же сервере. Это означает, что на другом порту, возможно, отличном от порта по умолчанию 80.

Я читал, что когда вы используете элемент конфигурации «connectionManagement», вам необходимо указать номер порта, если он отличается от 80 по умолчанию.

ССЫЛКА: параметр maxConnection может не работать даже autoConfig = false в ASP.NET

Во-вторых, если вы решите использовать конфигурацию по умолчанию (address = "*"), расширенную вашим собственным значением, специфичным для серверной части, вы можете подумать о том, чтобы сначала указать конкретное значение! В противном случае, если сделан запрос, сначала будет совпадать *, а по умолчанию - 2 соединения. Как и при использовании раздела в web.config.

ССЫЛКА: <remove> Элемент управления подключением (Настройки сети)

Надеюсь, это кому-то поможет.

Себастьян Хек
источник
5

Возможно ли, что вы используете ссылку на веб-службу на основе WCF? По умолчанию ServiceThrottlingBehavior.MaxConcurrentCalls - 16.

Вы можете попробовать обновить <serviceThrottling>элемент поведения ссылки на службу

<serviceThrottling
    maxConcurrentCalls="999" 
    maxConcurrentSessions="999" 
    maxConcurrentInstances="999" />

(Обратите внимание, что я бы рекомендовал указанные выше параметры.) См. MSDN для получения дополнительной информации о том, как настроить соответствующий <behavior>элемент.

Рубен
источник
Хотелось бы, чтобы мы были, но это не так. Используемая служба работает в Apache / Python / mod_wsgi на другом компьютере, и, как сказал Роб, проблема явно не в этом.
Бенджамин Поллак,
Ссылки на услуги находятся на клиенте. Как ваш клиент использует службу Apache?
Джон Сондерс,
Как сказал Джон: дросселирование установлено на клиенте, использующем веб-службу. Возможно, фраза «ваше служебное поведение» немного вводит в заблуждение. Имеет ли смысл выражение «поведение ссылки на вашу службу»?
Рубен
@john Он потребляется через TcpClient(служба продает пользовательские двоичные BLOB-объекты, а не WCF / SOAP или аналогичные). Эти параметры конфигурации , кажется , быть чисто воздействуя вас , если вы используете ServiceHost, не TcpClient; я что-то упускаю?
Бенджамин Поллак,
Почему бы не использовать «Добавить ссылку на службу»?
Джон Сондерс,
3

Вы пытались программно установить значение статического свойства DefaultConnectionLimit ?

Вот хороший источник информации об этой настоящей головной боли ... Использование потоков ASP.NET в IIS 7.5, IIS 7.0 и IIS 6.0 с обновлениями для framework 4.0.

Саймон Мурье
источник
Думаю, это не имеет значения, но я все равно попробую.
Роб Соберс,
Вот как мы это исправили несколько лет назад. У нас были проблемы с параллелизмом, и это, казалось, решило их. Net.ServicePointManager.DefaultConnectionLimit = 1000 - это то, что мы использовали. Вы должны установить его ДО создания классов подключения.
Brain2000 06
2

См. Раздел «Потоки» на этой странице: http://msdn.microsoft.com/en-us/library/ff647786.aspx вместе с разделом «Подключения».

Вы пробовали поднять атрибут maxconnection в настройке processModel?

Мэтт Эванс
источник
Да. Но в той статье, которую вы процитировали, указывается кое-что интересное, о чем не упоминалось ни в одной другой статье по этой теме: maxconnectionатрибут не применяется к вызовам локальных веб-служб. В этом конкретном случае веб-служба является локальной, но у нас есть та же проблема в другой среде, где служба не является локальной.
Роб Соберс,
@RobSobers - Я думаю, что ссылка выше заслуживает второго взгляда. Проверьте часть о minLocalRequestFreeThreads- этот рабочий процесс использует этот параметр для постановки в очередь запросов от localhost (где веб-приложение вызывает веб-службу на том же сервере ), если количество доступных потоков в пуле потоков падает ниже этого числа. Этот параметр аналогичен minFreeThreads, но применяется только к запросам, использующим localhost .
Ахмад
@Ahmad Yup, я тоже установил minLocalRequestFreeThreads(см. Мой machine.configв вопросе.
Роб Соберс,
0

Если он не определен в веб-службе, приложении или сервере (apache или IIS), на котором размещается расходный материал веб-службы, вы можете создавать бесконечные соединения до сбоя.

Фрэнк Тюдор
источник
0

при тестировании производительности я использую показатель RPS, то есть количество запросов в секунду, которые может обслужить сервер с приемлемой задержкой.

теоретически один сервер может выполнять одновременно столько запросов, сколько ядер на нем.

Не похоже, что проблема заключается в потоковой модели ASP.net, поскольку она потенциально может обслуживать тысячи запросов в секунду. Похоже, проблема в вашем приложении. Вы используете какие-нибудь примитивы синхронизации?

также какая задержка в ваших веб-сервисах, они очень быстро реагируют (в течение микросекунд), если нет, то вы можете рассмотреть асинхронные вызовы, чтобы вы не блокировали

Если это что-то не дает, вы можете профилировать свой код с помощью Visual Studio или профилировщика Redgate.

нп-жесткий
источник