Производительность ASP.NET Request.Form

Я использовал HttpHandler для реализации облегченного веб-сервиса, ориентированного на высокую производительность. Требуется POST с типом содержимого application/x-www-form-urlencoded. Веб-служба выполняет множество задач, включая расшифровку, работу с базой данных, бизнес-логику и так далее. Во время нагрузочного тестирования монитор производительности (ANTS и Visual Studio) указывает на одну строку кода, которая занимает большую часть времени, фактически 67%.

string value = context.Request.Form[MY_FORM_KEY];

В нижней части стека вызовов для этой строки кода монитор производительности произносит этот вызов:

System.Web.Hosting.UnsafeIISMethods.MgdSyncReadRequest();

является виновником.

Может кто-нибудь помочь, пожалуйста, объясните?! Приложение находится в .Net 4, опубликовано как выпуск IIS 7 для Windows Server 2008.

Спасибо, Джоуи Дж. Барретт.


person Joey J. Barrett    schedule 04.05.2011    source источник
comment
Я был бы очень удивлен, если бы узким местом был индексатор Request.Form. По сравнению со всей работой, которую вы описали, это должно быть незначительным.   -  person Darin Dimitrov    schedule 04.05.2011
comment
Возможно, вы ссылаетесь на context.Request.Form слишком много раз, вместо этого... вам может потребоваться клонировать ваши значения в локальные переменные   -  person Ahmed Khalaf    schedule 04.05.2011
comment
Рассмотрите возможность отправки в качестве заголовка вместо переменной формы. Я подозреваю, что коллекция Form имеет больше значений, и ее получение делает вызов громоздким. Также вы можете проверить целевой ЦП при создании решения. Иногда переход на x86 устраняет узкое место вокруг System.Web.Hosting.UnsafeIISMethods.MgdSyncReadRequest()...   -  person sajoshi    schedule 04.05.2011


Ответы (3)


Задержка возникает из-за того, что IIS пытается прочитать поток запросов от клиента, чтобы получить значения формы. Этот поток зависит от подключения клиента и по некоторым причинам даже не возвращается. Я видел случаи, когда Request.Form блокировался более 5 минут, и это приводило к тому, что IIS в конечном итоге выбрасывал ThreadAbortException.

В нашем случае у нас был HttpModule, который должен был считывать значения Request.Form (или request["key"] который также перебирает значения формы), и он случайным образом блокировался на сервере и никогда не возвращался. Я использовал этот HttpModule для отслеживания производительности приложения на стороне сервера, что заставило меня понять, что все, что я отслеживаю с помощью этого модуля, также будет зависеть от подключения клиента, что исказило бы мои результаты выполнения на стороне сервера.

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

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

person saver    schedule 10.10.2012

То

System.Web.Hosting.UnsafeIISMethods.MgdSyncReadRequest()

— это импортированная функция IIS (как вы могли догадаться). Поскольку http.sys, часть, которая выполняет всю работу http для IIS, представляет собой неуправляемый код, в какой-то момент вашему приложению потребуется взаимодействовать с ним, хотя и не напрямую.

Я предполагаю, что происходит, когда вы читаете коллекцию форм, .net читает это из необработанного запроса от IIS. Если это окажется узким местом, я бы реорганизовал ваш код для асинхронного чтения данных формы и сохранения необходимых значений в собственной структуре данных.

Саймон

person Simon Halsey    schedule 19.05.2011

Метод MgdSyncReadRequest заблокировал внутренний API неуправляемого IIS. Но поднял управляемый ThreadAbortException.
Это означает, что другой управляемый поток может вызывать Thread.Abort().

Я искал справочный источник, нашел "RequestTimeoutManager":

http://referencesource.microsoft.com/#System.Web/RequestTimeoutManager.cs,177

thread.Abort(new HttpApplication.CancelModuleException(true));

Решение (не проверять, может быть): реализуется асинхронным считывателем и обрабатывает тайм-аут вручную...

person Kouji Matsui    schedule 24.02.2016