c# - ¿Hay algún peligro no obvio al usar subprocesos en ASP.NET?
multithreading asp.net-mvc-2 (4)
Esto es algo así como una cuestión de hermanos a la pregunta de este programador .
Brevemente, estamos buscando impulsar "apropiadamente" un trabajo que ha estado respaldando las solicitudes de los usuarios en segundo plano. La pregunta vinculada me ha dado muchas ideas si tomamos la ruta del servicio, pero realmente no ha proporcionado ningún argumento convincente sobre por qué, exactamente, deberíamos.
Voy a admitir que, para mí, la capacidad de hacer el equivalente moral de
WorkQueue.Push(delegate(object context) { ... });
es realmente convincente, así que si es un poco difícil (en lugar de inherentemente impracticable), me inclino por el enfoque del hilo de fondo.
Entonces, los problemas con los hilos de fondo que conozco (en el contexto de una AppPool):
- Pueden morir en cualquier momento debido a que la AppPool se recicla
- Solución: realizar un seguimiento cuando se está ejecutando una tarea, por lo que se puede volver a ejecutar * si se necesita un nuevo hilo
- El ThreadPool se utiliza para responder a las consultas HTTP entrantes, por lo que su uso puede privar a IIS
- Solución: construya nuestro propio grupo de subprocesos, limitando también el número de subprocesos.
Mi pregunta es, ¿qué me estoy perdiendo? ¿Qué más puede salir malǂ con los hilos de fondo en ASP.NET?
* La tarea en las preguntas ya es segura para volver a ejecutar, por lo que esto no es un problema.
ǂ Supongamos que no estamos haciendo nada realmente tonto, como lanzar excepciones en los hilos de fondo.
Déjame que te cuente sobre un peligro no obvio :)
Usé hilos para recopilar Actualizar algunas fuentes RSS en mi base de datos para un sitio web que estaba alojando con GoDaddy. Los hilos funcionaron bien (si se cancelaran, se reiniciarían automáticamente debido a algunos controles que había creado en algunas páginas web).
Funcionaba de manera excelente y estaba muy contento, hasta que GoDaddy (mi anfitrión) comenzó a matar los hilos y luego los bloqueó por completo. ¡Entonces mi aplicación acaba de morir!
Si eso no fuera obvio, ¿qué es?
Un peligro con el que me encontré personalmente es el CallContext. Estábamos usando el CallContext para establecer los datos de identidad del usuario, porque el mismo código se compartió en nuestra aplicación web y en nuestros servicios de aplicación basados en .NET Remoting (que está diseñado para usar el CallContext para almacenar datos específicos de llamada), así que no estábamos usando el HttpContext.
Notamos que, a veces, una nueva solicitud terminaría con una identidad no nula en el CallContext. En otras palabras, ASP .NET no anulaba los datos almacenados en el CallContext entre solicitudes ... y, por lo tanto, un usuario no autenticado podría ingresar a la aplicación si recogían un hilo que todavía tenía el CallContext que contenía información de identidad de usuario validada.
Uno podría ser que está complicando demasiado su arquitectura sin obtener ningún beneficio.
Su programa será más costoso de escribir, más costoso de mantener y tendrá más posibilidades de tener errores.
Me mantendría alejado de iniciar subprocesos desde dentro de su AppDomain de IIS para . No tengo ninguna evidencia sólida que respalde lo que voy a decir, pero trabajando con IIS durante 10 años, sé que funciona mejor cuando es el único juego de la ciudad.
También hay una alternativa, sé que esto va a ser una especie de despegue en mi respuesta sobre el hilo de programadores. Pero, según tengo entendido, ya tienes una solución que funciona respaldando el trabajo de las solicitudes de los usuarios. ¿Por qué no usar ese código, pero solo iniciarlo cuando se llama a una API interna especial? Luego use Task Scheduler
para llamar un comando CURL
que llame a esa API cada 30 segundos o más para iniciar las tareas. De esta forma, permite que IIS maneje el subprocesamiento y su código maneja algo que ya hace fácilmente.