2011-05-25 5 views
9

Cuando ASP.NET recibe una solicitud, ¿cómo determina si la sirve o la pone en cola? Lo pregunto porque estoy monitoreando los contadores de rendimiento en un servidor y la CPU no está al máximo y hay una gran cantidad de subprocesos de trabajo disponibles, pero sigo viendo que hay hasta 200 solicitudes puestas en cola.¿Cómo determina ASP.NET si debe poner en cola una solicitud o no?

+0

Sospecho que no usará la carga de subprocesos, ya que eso no ayuda necesariamente a su rendimiento. Para maximizar el rendimiento, es preferible usar una proporción de hilos de 1: 1 a ninguna de las CPU. No estoy seguro de las funciones internas de ASP .NET –

+0

Los subprocesos están bloqueados en las operaciones de E/S. En este caso, mantenerlos 1: 1 con las CPU no ayuda a la producción. Y no creo que ASP.NET suponga que las solicitudes están vinculadas a la CPU tampoco. También veo solicitudes simultáneas hasta 20, que es mayor que la cantidad de procesadores en la máquina. – RandomEngy

+0

@RandomEnergy: es por eso que dije 'principalmente', y si bloquean las operaciones de E/S, están ** bloqueando **, lo que significa que tienen que esperar, si el hilo no está desactivado en ese momento. momento, perderá CPU. Una operación de E/S sin bloqueo permitirá que otros subprocesos tomen CPU, mientras se está realizando la E/S. –

Respuesta

15

que he estado haciendo la investigación y creo que he llegado a una respuesta aceptable. Mi fuente principal es este artículo: http://blogs.msdn.com/b/tmarq/archive/2007/07/21/asp-net-thread-usage-on-iis-7-0-and-6-0.aspx

Como tengo entendido, hay dos formas principales en que se acelera el procesamiento de solicitudes. La primera es la propiedad MaxConcurrentRequestsPerCPU. Antes de .NET 4 esto se estableció en 12 de forma predeterminada. En .NET 4 se cambió a 5000. Para las solicitudes de sincronización quisieron permitir mucho, y para las solicitudes sincrónicas creen que el ThreadPool de ASP.NET acelerará las solicitudes sincrónicas lo suficientemente bien. El segundo, por supuesto, es el ThreadPool en sí mismo. Después de que ASP.NET publique la solicitud allí, puede decidir cuándo irá.

Si está realizando un proceso de sincronización, es probable que sus factores limitantes sean la CPU, la red y el disco, y no cualquier limitación de solicitudes de ASP.NET. Posiblemente podría alcanzar el límite MaxConcurrentRequestsPerCPU, pero ese límite es realmente alto.

Si está realizando un procesamiento sincrónico y bloqueando llamadas web durante largos períodos de tiempo, es mucho más probable que se tope con estos límites. MaxConcurrentRequestsPerCPU es algo a lo que hay que tener cuidado antes de .NET 4, pero todavía hay ThreadPool.

pruebas de rendimiento
Redacté una sencilla prueba para ver cómo funcionaba esta limitación. Tengo una página simple con una llamada Thread.Sleep() de 500ms. Una máquina host realiza 800 solicitudes asíncronas simultáneas y una máquina de trabajo que ejecuta ASP.NET las procesa todas. Los resultados fueron interesantes:

.NET 3.5, sin modificaciones: 46 segundos. Vi 9 hilos de trabajo con el explorador de procesos.
.NET 3.5, con MaxConcurrentRequestsPerCPU establecido en 5000: 46 segundos. 9 hilos de trabajo.
.NET 4: 42 segundos, o 13 segundos cuando está funcionando en caliente. Vimos crear gradualmente alrededor de 35 subprocesos de trabajo.
.NET 4, asincrónico: 3 segundos

Algunas observaciones:

  • MaxConcurrentRequestsPerCPU no fue ser golpeado. Parece que fue la limitación del ThreadPool en sí mismo.
  • .NET 3.5 parece bastante reacio a crear nuevos subprocesos para procesar solicitudes sincrónicas. .NET 4 hace un trabajo mucho mejor para aumentar la carga.
  • Async sigue siendo el mejor en una milla de país.
+0

+1 vale la pena leerlo, gracias –

+1

Este es un resultado interesante, pero debe ejecutarlo en un SO del servidor. Obviamente, lo ejecutó en un sistema operativo cliente (como Windows 7) porque se encontró con el límite de 10 solicitudes simultáneas. IIS no tiene esta limitación en un sistema operativo de servidor. – Flavien

+0

¿Cómo determinó que había "alcanzado el límite de 10 solicitudes simultáneas"? Si ese fuera el caso, ¿por qué mi prueba de .NET 4 tomó solo 3 segundos para procesar 800 solicitudes? ¿Puede vincular a cualquier documentación que sugiera que realmente hay un límite de 10 solicitudes simultáneas en sistemas operativos que no son de servidor? – RandomEngy

2

IIS no utiliza todos los subprocesos disponibles antes de que comience las solicitudes de cola, ya que estos subprocesos deben permanecer disponibles para que una solicitud en ejecución necesite subprocesos adicionales. IIS está optimizado para dar preferencia a la ejecución de solicitudes y no desea que una solicitud en ejecución se bloquee porque el proceso de trabajo se quedó sin hilos disponibles.

El grupo de subprocesos máximo predeterminado 20, con un mínimo libre de 8, lo que significa que el sistema solo irá a 12 solicitudes que se ejecutan antes de que las nuevas solicitudes se pongan en cola. Maximum Threads se multiplica por el número de núcleos, pero el mínimo de hilos no lo es, por lo que el valor predeterminado permitirá 32 solicitudes en un cuadro de doble núcleo antes de poner en cola.

Y en cuanto a que queda CPU, ASP.NET no controla eso. Es puramente sobre la cantidad de hilos en uso. Esos hilos pueden ser bloqueados por el acceso al disco, el acceso a la red transfiriendo los resultados de la base de datos, o simplemente un Thread.Sleep, que seguiría contribuyendo a que las nuevas solicitudes vayan a la cola aunque la CPU no esté al máximo.

Más información está disponible en MS Patterns & Libro de prácticas sobre el rendimiento. Se aplica a IIS6/.NET 1.1, pero los conceptos aún permanecen. http://msdn.microsoft.com/en-us/library/ff647787.aspx#scalenetchapt06_topic8

Reconfiguración de IIS7/.NET 2+: http://msdn.microsoft.com/en-us/library/e1f13641.aspx

+0

Estoy leyendo la documentación en ThreadPool (http://msdn.microsoft.com/en-us/library/system.threading.threadpool.aspx) "A partir de .NET Framework versión 4, el tamaño predeterminado del grupo de subprocesos para un proceso depende de varios factores, como el tamaño del espacio de direcciones virtual. Un proceso puede llamar al método GetMaxThreads para determinar el número de subprocesos ". - Me está devolviendo 400. – RandomEngy

Cuestiones relacionadas