Поделиться через


Проблемы с производительностью при вызове веб-служб из приложения ASP.NET

В этой статье приведена помощь в решении проблем с производительностью, возникающих при вызове веб-служб из приложения Microsoft ASP.NET.

Исходная версия продукта: ASP.NET
Исходный номер базы знаний: 821268

Симптомы

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

При вызове метода может появиться следующее сообщение об ошибке HttpWebRequest.GetResponse исключения:

"System.InvalidOperationException: недостаточно свободных потоков в объекте ThreadPool для завершения операции".

В браузере также может появиться следующее сообщение об ошибке исключения:

"HttpException (0x80004005): истекло время ожидания запроса".

Примечание.

Эта статья также относится к приложениям, которые выполняют HttpWebRequest запросы напрямую.

Причина

Эта проблема может возникнуть, так как ASP.NET ограничивает количество рабочих потоков и потоков портов завершения, которые вызов может использовать для выполнения запросов.

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

Например, предположим, что ThreadPool число рабочих потоков ограничено 10 рабочими потоками и что все 10 рабочих потоков в настоящее время выполняют код, ожидающий выполнения обратного вызова. Обратный вызов никогда не может выполняться, так как все рабочие элементы, в очереди которых находятся в очереди, ThreadPool блокируются до тех пор, пока поток не станет доступным.

Другой потенциальный источник состязания — maxconnection это параметр, который System.Net пространство имен использует для ограничения количества подключений. Как правило, это ограничение работает должным образом. Однако если многие приложения пытаются выполнить много запросов к одному IP-адресу одновременно, потоки могут ждать доступного подключения.

Решение

Чтобы устранить эти проблемы, можно настроить следующие параметры в файле Machine.config , чтобы лучше всего соответствовать вашей ситуации:

  • maxWorkerThreads
  • minWorkerThreads
  • maxIoThreads
  • minFreeThreads
  • minLocalRequestFreeThreads
  • maxconnection
  • executionTimeout

Чтобы успешно устранить эти проблемы, выполните следующие действия:

  • Ограничить количество запросов ASP.NET, которые могут выполняться одновременно, примерно 12 на ЦП.
  • Разрешить обратным вызовам веб-службы свободно использовать потоки в .ThreadPool
  • Выберите соответствующее значение параметра maxconnections . На основе выбранного количества IP-адресов и используемых доменов приложений.

Примечание.

Рекомендация ограничить количество запросов ASP.NET до 12 на ЦП немного произвольно. Однако это ограничение хорошо работает для большинства приложений.

MaxWorkerThreads и maxIoThreads

ASP.NET использует следующие два параметра конфигурации, чтобы ограничить максимальное количество рабочих потоков и потоков завершения, которые используются:

<processModel maxWorkerThreads="20" maxIoThreads="20">

Параметр maxWorkerThreads и maxIoThreads параметр неявно умножаются на число ЦП. Например, если у вас есть два процессора, максимальное количество рабочих потоков равно 2 * maxWorkerThreads.

MinFreeThreads и minLocalRequestFreeThreads

ASP.NET также содержит следующие параметры конфигурации, определяющие, сколько рабочих потоков и потоков портов завершения должно быть доступно для запуска удаленного запроса или локального запроса:

<httpRuntime minFreeThreads="8" minLocalRequestFreeThreads="8">

Если нет достаточных потоков, запрос помещается в очередь до тех пор, пока достаточно потоков не будет свободно выполнять запрос. Таким образом, ASP.NET не будет выполняться больше следующего числа запросов одновременно:

(maxWorkerThreads * количество ЦП) — minFreeThreads

Примечание.

Параметр minFreeThreads и minLocalRequestFreeThreads параметр неявно умножаются на число ЦП.

MinWorkerThreads

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

<processModel minWorkerThreads="1">

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

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

Значение по умолчанию для minWorkerThreads параметра равно 1. Рекомендуется задать для minWorkerThreads параметра следующее значение:

minWorkerThreads = maxWorkerThreads / 2

По умолчанию minWorkerThreads параметр отсутствует в файле web.config или файле Machine.config . Этот параметр неявно умножается на число ЦП.

Maxconnection

Параметр maxconnection определяет количество подключений к конкретному IP-адресу. Параметр отображается следующим образом:

<connectionManagement>
    <add address="*" maxconnection="2">
    <add address="http://65.53.32.230" maxconnection="12">
</connectionManagement>

Если код приложения ссылается на приложение по имени узла вместо IP-адреса, параметр должен отображаться следующим образом:

<connectionManagement>
    <add address="*" maxconnection="2">
    <add address="http://hostname" maxconnection="12">
</connectionManagement>

Наконец, если приложение размещено на порту, отличном от 80, параметр должен включить нестандартный порт в URL-адрес, как показано ниже:

<connectionManagement>
    <add address="*" maxconnection="2">
    <add address="http://hostname:8080" maxconnection="12">
</connectionManagement>

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

ExecutionTimeout

ASP.NET использует следующий параметр конфигурации, чтобы ограничить время выполнения запроса:

<httpRuntime executionTimeout="90"/>

Это ограничение также можно задать с помощью Server.ScriptTimeout свойства.

Примечание.

При увеличении executionTimeout значения параметра также может потребоваться изменить processModelresponseDeadlockInterval параметр.

Рекомендации

Рекомендуемые в этом разделе параметры могут не работать для всех приложений. Однако следующие дополнительные сведения помогут вам внести соответствующие корректировки.

Если вы вызываете одну веб-службу на одну IP-адрес из каждой страницы ASPX, корпорация Майкрософт рекомендует использовать следующие параметры конфигурации:

  • Задайте значения maxWorkerThreads параметра и maxIoThreads параметра значение 100.
  • Задайте для параметра значение maxconnection 12*N (где N — число ЦП, которое у вас есть).
  • Задайте для параметра значение minFreeThreads 88*N, а minLocalRequestFreeThreads параметр — 76*N.
  • Задайте значение minWorkerThreads50. Помните, что minWorkerThreads по умолчанию не находится в файле конфигурации. Его необходимо добавить.

Некоторые из этих рекомендаций включают простую формулу, которая включает количество ЦП на сервере. Переменная, представляющая количество ЦП в формулах, — N.

Для этих параметров, если у вас включена гиперпоточность, необходимо использовать количество логических ЦП вместо числа физических ЦП. Например, если у вас есть четырехпроцессорный сервер с поддержкой гиперпоточности, то значение N в формулах будет 8 вместо 4.

Примечание.

При использовании этой конфигурации можно выполнять не более 12 ASP.NET запросов на ЦП одновременно, так как 100-88=12. Поэтому для других вариантов использования доступны по крайней мере 88*N рабочих потоков и 88*N портов завершения (например, для обратных вызовов веб-службы).

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

<system.web>
    <processModel maxWorkerThreads="100" maxIoThreads="100" minWorkerThreads="50"/>
    <httpRuntime minFreeThreads="704" minLocalRequestFreeThreads="608"/>
</system.web>
<system.net>
    <connectionManagement>
        <add address="[ProvideIPHere]" maxconnection="96"/>
    </connectionManagement>
</system.net>

Кроме того, при использовании этой конфигурации 12 подключений доступны для каждого IP-адреса на ЦП для каждого домена приложения. Таким образом, в следующем сценарии очень мало конфликта возникает, когда запросы ожидают подключений и ThreadPool не исчерпаны:

  • Веб-сайт размещает только одно приложение (AppDomain).
  • Каждый запрос на страницу ASPX выполняет один запрос веб-службы.
  • Все запросы относятся к одному IP-адресу.

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

  • Запросы относятся к нескольким IP-адресам.
  • Запросы перенаправляются (код состояния 302).
  • Запросы требуют проверки подлинности.
  • Запросы выполняются из нескольких доменов приложений.

В этих сценариях рекомендуется использовать более низкое значение для maxconnection параметра и более высоких значений для minFreeThreads параметра и minLocalRequestFreeThreads параметра.

Дополнительная информация

Дополнительные сведения см. в разделе "Улучшение ASP.NET производительности".

Если вы столкнулись с низкой производительностью и спором в IIS вместе с ASP.NET, перейдите к следующим блогам Майкрософт: