2011-05-04 10 views
11

Utilicé un HttpHandler para implementar un servicio web ligero destinado a un alto rendimiento. Requiere un POST con contenido tipo application/x-www-form-urlencoded. El servicio web realiza muchas tareas, como el descifrado, el trabajo de bases de datos, la lógica de negocios, etc. Durante la prueba de carga, el monitor de rendimiento (ANTS y ​​Visual Studio) apunta a una única línea de código que está ocupando la mayoría del tiempo, de hecho 67%.ASP.NET Request.Form Performance

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

En la parte inferior de la pila de llamadas para esta línea de código, el monitor de rendimiento, dice esta llamada:

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

es el culpable.

¿Alguien puede ayudarme por favor explique ?! La aplicación se encuentra en .Net 4, publicada como la liberación, IIS 7, en Windows Server 2008.

Gracias, Joey J. Barrett

+4

Me sorprendería mucho si el cuello de botella es el indexador Request.Form. Comparado con todo el trabajo que describiste, esto debería ser insignificante. –

+0

Quizás esté haciendo referencia a context.Request.Form demasiadas veces, en su lugar ... puede que necesite clonar sus valores en las variables locales –

+1

Considere enviar como un encabezado en lugar de una variable de Formulario. Sospecho que la colección de Formularios tiene más valores y recuperarlos hace que la llamada sea voluminosa. También puede verificar la CPU de destino cuando construya la solución. A veces, al cambiar a x86 se elimina el cuello de botella en System.Web.Hosting.UnsafeIISMethods.MgdSyncReadRequest() ... – sajoshi

Respuesta

2

la

System.Web.Hosting.UnsafeIISMethods.MgdSyncReadRequest() 

es una función de IIS importado (como habrás adivinado). Desde http.sys, el bit que hace todo el trabajo de http para IIS, es código no administrado, en algún momento su aplicación necesitará hablar con él, aunque no directamente.

Lo que supongo que sucede es que cuando lee la colección de formularios, .net está leyendo esto desde la solicitud sin procesar de IIS. Si está demostrando ser un cuello de botella, refactorizaría su código para leer los datos del formulario de forma asíncrona y almacenar los valores que necesita en una estructura de datos nativa.

Simon

6

retardo de tiempo se debe a que IIS intenta leer petición de flujo desde el cliente para recuperar los valores del formulario. Esta transmisión está sujeta a la conexión del cliente y en algunas causas ni siquiera regresará. He visto casos en los que Request.Form se bloqueaba durante más de 5 minutos y ocasionaría que IIS eventualmente lanzara ThreadAbortException.

En nuestro caso, teníamos un HttpModule que debía leer los valores de Request.Form (o request ["key"] que itera sobre los valores de formulario también) y se bloqueaba aleatoriamente en el servidor y nunca volvería. Usé este HttpModule para rastrear el rendimiento de las aplicaciones en el lado del servidor, lo que me hizo darme cuenta de que todo lo que sigo usando este módulo también dependerá de la conectividad del cliente, lo que sesgaría los resultados de mi ejecución en el servidor.

Para resolver este problema, puede instalar el proxy HTTP inverso en frente de su aplicación. El proxy inverso descargará la responsabilidad de leer el flujo del cliente (y bloquear un hilo costoso en su aplicación) y enviar una solicitud completa a su servidor. Esto reducirá la carga en su aplicación, ya que puede guardar sus preciosos hilos de aplicación para manejar su carga de trabajo principal en lugar de bloquearlos para que lean las secuencias de clientes.

Además, puede descargar HTTPs, equilibrar la carga e incluso almacenar en caché contenido estático en su proxy inverso (dependiendo de cuál use).

0

MgdSyncReadRequest método bloqueado interno no gestionado-IIS API. Pero planteó administrado ThreadAbortException.
Eso significa que otro hilo administrado puede llamarse al Thread.Abort().

busqué referencesource, lo consiguió "RequestTimeoutManager":

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

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

solución (no inspeccionar, puede ser): Implementa por el lector basado en asíncrono, y el mango de tiempo de espera de forma manual ..