Производительность 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.

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

Ответ 1

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

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

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

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

Ответ 2

System.Web.Hosting.UnsafeIISMethods.MgdSyncReadRequest()

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

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

Саймон

Ответ 3

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

Я искал sourcesource, получил его "RequestTimeoutManager":

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

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

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