Usando ThreadPool.Equipo de trabajo en línea ASP.NET en un escenario de alto tráfico


Siempre he tenido la impresión de que el uso del ThreadPool para tareas en segundo plano (digamos no críticas) de corta duración se consideraba una mejor práctica, incluso en ASP.NET, pero entonces me encontré con este artículo que parece sugerir lo contrario, el argumento es que debe dejar el ThreadPool para lidiar con ASP.NET solicitudes relacionadas.

Así que así es como he estado haciendo pequeñas tareas asíncronas hasta ahora:

ThreadPool.QueueUserWorkItem(s => PostLog(logEvent))

Y el artículo sugiere en su lugar crear un hilo explícitamente, similar a:

new Thread(() => PostLog(logEvent)){ IsBackground = true }.Start()

El primer método tiene la ventaja de ser administrado y limitado, pero existe el potencial (si el artículo es correcto) de que las tareas en segundo plano compitan por subprocesos con ASP.NET manejadores de solicitudes. El segundo método libera el ThreadPool, pero a costa de ser ilimitado y, por lo tanto, potencialmente agotando demasiados recursos.

Así que mi pregunta es, ¿es correcto el consejo en el artículo?

Si su sitio se estaba poniendo así mucho tráfico que su ThreadPool se estaba llenando, entonces es mejor salir de banda, o un ThreadPool completo implicaría que está llegando al límite de sus recursos de todos modos, en cuyo caso no debería estar tratando de iniciar sus propios hilos?

Aclaración: Solo estoy preguntando en el ámbito de pequeñas tareas asíncronas no críticas (por ejemplo, registro remoto), no elementos de trabajo costosos que requerirían un proceso separado (en estos casos estoy de acuerdo en que necesitará una solución más robusta).

Author: deostroll, 2009-08-25

10 answers

Otras respuestas aquí parecen omitir el punto más importante:{[16]]}

A menos que esté tratando de paralelizar una operación de uso intensivo de CPU con el fin de hacerlo más rápido en un sitio de baja carga, no tiene sentido usar un subproceso de trabajo en absoluto.

Que va para ambos hilos libres, creados por new Thread(...), y hilos de trabajo en el ThreadPool que responden a las solicitudes QueueUserWorkItem.

Sí, es cierto, usted puede morir de hambre el ThreadPool en un ASP.NET proceso haciendo cola también muchos artículos de trabajo. Se evitará ASP.NET de procesar más solicitudes. La información en el artículo es precisa en ese sentido; el mismo grupo de subprocesos utilizado para QueueUserWorkItem también se utiliza para servir solicitudes.

Pero si realmente estás haciendo cola suficientes elementos de trabajo para causar esta inanición, entonces deberías estar muriendo de hambre el grupo de hilos! Si está ejecutando literalmente cientos de operaciones intensivas en CPU al mismo tiempo, ¿ de qué serviría tener otro hilo de trabajo para servir an ASP.NET solicitud, cuando la máquina ya está sobrecargada? Si se está ejecutando en esta situación, es necesario rediseñar por completo!

La mayoría de las veces veo o escucho que el código multihilo se usa inapropiadamente en ASP.NET, no es para hacer cola de trabajo intensivo de CPU. Es para hacer cola en el trabajo de E / S. Y si quieres hacer trabajo de E/S, entonces deberías usar un hilo de E/S (Puerto de Finalización de E/S).

Específicamente, debería usar las devoluciones de llamada asincrónicas compatible con cualquier clase de biblioteca que esté utilizando. Estos métodos siempre están claramente etiquetados; comienzan con las palabras Begin y End. Como en Stream.BeginRead, Socket.BeginConnect, WebRequest.BeginGetResponse, y así sucesivamente.

Estos métodos usan el ThreadPool, pero usan IOCPs, que no interfieren con ASP.NET peticiones. Son un tipo especial de hilo ligero que puede ser "despertado" por una señal de interrupción del sistema de E/S. Y en un ASP.NET aplicación, normalmente tiene un hilo de E/S para cada hilo de trabajo, por lo que cada solicitud puede tener una operación asíncrona en cola. Eso es literalmente cientos de operaciones asincrónicas sin ninguna degradación significativa del rendimiento (suponiendo que el subsistema de E/S pueda mantenerse al día). Es mucho más de lo que necesitarás.

Solo tenga en cuenta que los delegados async no funcionan de esta manera - terminarán usando un hilo de trabajo, al igual que ThreadPool.QueueUserWorkItem. Solo los métodos asincrónicos integrados de las clases de biblioteca de. NET Framework son capaces de haciendo esto. Puede hacerlo usted mismo, pero es complicado y un poco peligroso y probablemente más allá del alcance de esta discusión.

La mejor respuesta a esta pregunta, en mi opinión, es no utilice el ThreadPool or a background Thread instance in ASP.NET. No es en absoluto como girar un hilo en una aplicación de Windows Forms, donde lo haces para mantener la interfaz de usuario sensible y no te importa lo eficiente que es. En ASP.NET, su preocupación es throughput, y todo ese contexto cambiando en todos esos hilos de trabajo es absolutamente va a matar su rendimiento si se utiliza el ThreadPool o no.

Por favor, si te encuentras escribiendo código de enhebrado en ASP.NET -considere si podría o no ser reescrito para usar métodos asíncronos preexistentes, y si no puede, entonces considere si realmente necesita o no el código para ejecutarse en un subproceso en segundo plano. En la mayoría de los casos, probablemente esté agregando complejidad para ningún beneficio neto.

 101
Author: Aaronaught,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-05 03:16:23

Por Thomas Marquadt de la ASP.NET equipo en Microsoft, es seguro utilizar el ASP.NET ThreadPool (QueueUserWorkItem).

Del artículo :

Q) Si mi ASP.NET La aplicación utiliza roscas CLR ThreadPool, no me moriré de hambre ASP.NET, que también utiliza el ThreadPool CLR para ejecutar solicitudes? Blockquote

A) [T] o resumir, no se preocupe acerca de hambriento ASP.NET de hilos, y si ¿crees que hay un problema aquí vamos me conocen y nos encargaremos.

Q) Debería crear mis propios hilos (nuevo Hilo)? No sería mejor para ASP.NET, ya que utiliza el CLR ThreadPool.

A) Por favor no. O para ponerlo a manera diferente, ¡no!!! Si realmente eres inteligente, mucho más inteligente que yo-entonces usted puede crear sus propios hilos; de lo contrario, ni siquiera lo pienses. Aquí hay algunas razones por las que debe no es frecuente crear nuevos hilos:

1) Lo es muy caro, en comparación con QueueUserWorkItem...By la forma, si usted puede escribir un ThreadPool mejor que el CLR, le animo a solicitar un trabajo en Microsoft, porque definitivamente estamos buscando personas como usted!.

 45
Author: Tim P.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-05-17 21:41:55

Los sitios web no deben ir por ahí generando hilos.

Normalmente mueve esta funcionalidad a un Servicio de Windows con el que luego se comunica (yo uso MSMQ para hablar con ellos).

Edit Editar

Describí una implementación aquí: Procesamiento en segundo Plano Basado en colas en ASP.NET Aplicación web MVC

Edit Editar

Para expandir por qué esto es incluso mejor que solo hilos:

Usando MSMQ, puede comunicarse con otro servidor. Puede escribir a un hacer cola entre máquinas, así que si determina, por alguna razón, que su tarea en segundo plano está consumiendo demasiado los recursos del servidor principal, puede cambiarla bastante trivialmente.

También le permite procesar por lotes cualquier tarea que esté tratando de hacer (enviar correos electrónicos/lo que sea).

 4
Author: Noon Silk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:34:29

Definitivamente creo que la práctica general para el trabajo asíncrono rápido y de baja prioridad en ASP.NET sería usar el grupo de subprocesos. NET, particularmente para escenarios de alto tráfico, ya que desea que sus recursos estén limitados.

Además, la implementación de subprocesos está oculta: si comienzas a generar tus propios subprocesos, también tienes que administrarlos correctamente. No digo que no pudieras hacerlo, pero ¿por qué reinventar esa rueda?

Si el rendimiento se convierte en un problema, y puede establecer que el grupo de subprocesos es el factor limitante (y no las conexiones de base de datos, las conexiones de red salientes, la memoria, los tiempos de espera de las páginas, etc.). A continuación, se modifica la configuración del grupo de subprocesos para permitir más subprocesos de trabajo, solicitudes en cola más altas, etc.

Si no tiene un problema de rendimiento, elija generar nuevos hilos para reducir la contención con el ASP.NET la cola de solicitudes es una optimización prematura clásica.

Lo ideal sería que no necesitara usar un subproceso separado para realizar una operación de registro sin embargo, solo habilite el hilo original para completar la operación lo más rápido posible, que es donde MSMQ y un hilo / proceso de consumo separado entran en la imagen. Estoy de acuerdo en que esto es más pesado y más trabajo para implementar, pero realmente necesita la durabilidad aquí: la volatilidad de una cola compartida en memoria desgastará rápidamente su bienvenida.

 4
Author: Sam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-08-25 05:32:09

Debes usar QueueUserWorkItem, y evitar crear nuevos hilos como evitarías la plaga. Para un visual que explica por qué no te morirás de hambre ASP.NET, ya que utiliza el mismo ThreadPool, imagina a un malabarista muy hábil usando dos manos para mantener media docena de bolos, espadas o lo que sea en vuelo. Para tener una idea visual de por qué crear tus propios hilos es malo, imagina lo que sucede en Seattle en la hora punta cuando las rampas de entrada a la carretera muy utilizadas permiten que los vehículos entren en el tráfico inmediatamente en lugar de usar una luz y limitar el número de entradas a una cada pocos segundos. Finalmente, para una explicación detallada, por favor vea este enlace:

Http://blogs.msdn.com/tmarq/archive/2010/04/14/performing-asynchronous-work-or-tasks-in-asp-net-applications.aspx

Gracias, Thomas

 2
Author: Thomas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-15 04:04:44

Ese artículo no es correcto. ASP.NET tiene su propio grupo de subprocesos, subprocesos de trabajo administrados, para servir ASP.NET peticiones. Este grupo es generalmente unos pocos cientos de hilos y está separado del grupo ThreadPool, que es un múltiplo más pequeño de procesadores.

Usando ThreadPool en ASP.NET no interferirá con ASP.NET hilos de trabajo. Usar ThreadPool está bien.

También sería aceptable configurar un solo hilo que es solo para registrar mensajes y usar patrón productor / consumidor para pasar mensajes de registro a ese hilo. En ese caso, dado que el subproceso es de larga duración, debe crear un único subproceso nuevo para ejecutar el registro.

Usar un hilo nuevo para cada mensaje es definitivamente excesivo.

Otra alternativa, si solo está hablando de registro, es usar una biblioteca como log4net. Maneja el registro en un subproceso separado y se encarga de todos los problemas de contexto que podrían surgir en ese escenario.

 1
Author: Samuel Neff,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-14 15:44:46

Yo diría que el artículo está equivocado. Si está ejecutando una tienda. NET grande, puede usar el grupo de forma segura en varias aplicaciones y varios sitios web (utilizando grupos de aplicaciones separados), simplemente basándose en una instrucción en la documentación ThreadPool:

Hay un grupo de subprocesos por proceso. El grupo de subprocesos tiene un tamaño predeterminado de 250 hilos por procesador y terminación de 1000 E/S hilo. El número de hilos en el el grupo de hilos se puede cambiar por utilizar el método SetMaxThreads. Cada hilo utiliza el tamaño de pila predeterminado y se ejecuta en la prioridad predeterminada.

 1
Author: Christopher Nobles,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-14 21:25:38

Me hicieron una pregunta similar en el trabajo la semana pasada y te daré la misma respuesta. ¿Por qué multi threading aplicaciones web por solicitud? Un servidor web es un sistema fantástico optimizado en gran medida para proporcionar muchas solicitudes de manera oportuna (es decir, multi threading). Piense en lo que sucede cuando solicita casi cualquier página en la web.

  1. Se hace una solicitud para alguna página
  2. Html se devuelve
  3. El Html le dice al cliente que haga solicitudes adicionales (js, css, images, sucesivamente..)
  4. Se devuelve más información

Usted da el ejemplo de registro remoto, pero eso debería ser una preocupación de su registrador. Un proceso asincrónico debe estar en su lugar para recibir mensajes de manera oportuna. Sam incluso señala que su registrador (log4net) ya debería soportar esto.

Sam también tiene razón en que usar el grupo de subprocesos en el CLR no causará problemas con el grupo de subprocesos en IIS. Lo que hay que tener en cuenta aquí, sin embargo, es que usted es no desovando hilos de un proceso, estás desovando nuevos hilos de hilos de IIS threadpool. Hay una diferencia y la distinción es importante.

Hilos vs Proceso

Tanto los subprocesos como los procesos son métodos de paralelizar una aplicación. Sin embargo, los procesos son independientes unidades de ejecución que contienen su propia estado información, utilizar su propia espacios de dirección, y solo interactuar con entre sí a través de interproceso comunicar mecanismos (generalmente gestionado por el sistema operativo). Las aplicaciones suelen dividirse en los procesos durante el diseño fase, y un proceso maestro explícitamente genera subprocesos cuando hace sentido para separar lógicamente funcionalidad significativa de la aplicación. Procesos, en otras palabras, son un construcción arquitectónica.

Por el contrario, un hilo es una codificación construcción que no afecta a la arquitectura de una aplicación. Un un solo proceso podría contener multiple hilos; todos los hilos dentro de un proceso compartir el mismo estado y la misma memoria espacio, y puede comunicarse con cada uno otros directamente, porque comparten la mismas variables.

Fuente

 1
Author: Ty.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-15 16:08:29

No estoy de acuerdo con el artículo referenciado(C#feeds.com). Es fácil crear un nuevo hilo pero peligroso. El número óptimo de hilos activos para ejecutarse en un solo núcleo es sorprendentemente bajo, menos de 10. Es demasiado fácil hacer que la máquina pierda tiempo cambiando hilos si los hilos se crean para tareas menores. Los subprocesos son un recurso que REQUIERE administración. La abstracción de WorkItem está ahí para manejar esto.

Hay un compromiso entre reducir el número de hilos disponibles para solicitudes y creando demasiados hilos para permitir que cualquiera de ellos se procese de manera eficiente. Esta es una situación muy dinámica, pero creo que debe ser gestionada activamente (en este caso por el grupo de subprocesos) en lugar de dejar que el procesador se mantenga por delante de la creación de subprocesos.

Finalmente, el artículo hace algunas declaraciones bastante amplias sobre los peligros de usar ThreadPool, pero realmente necesita algo concreto para respaldarlos.

 0
Author: Timbo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-03 19:00:12

Si IIS usa o no el mismo ThreadPool para manejar las solicitudes entrantes parece difícil obtener una respuesta definitiva, y también parece haber cambiado las versiones. Por lo que parece una buena idea no usar hilos ThreadPool excesivamente, por lo que IIS tiene muchos de ellos disponibles. Por otro lado, generar tu propio hilo para cada pequeña tarea parece una mala idea. Presumiblemente, tiene algún tipo de bloqueo en su registro, por lo que solo un hilo podría progresar a la vez, y el resto solo tomaría turnos para programar y no programar (sin mencionar la sobrecarga de generar un nuevo hilo). Esencialmente, te encuentras con los problemas exactos que el ThreadPool fue diseñado para evitar.

Parece que un compromiso razonable sería que su aplicación asigne un solo hilo de registro al que pueda pasar mensajes. Usted querrá tener cuidado de que el envío de mensajes es lo más rápido posible para que no ralentizar su aplicación.

 0
Author: bmm6o,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-05 22:58:55