2010-10-06 25 views
5

El tiempo de ejecución de ASP.NET está pensado para cargas de trabajo breves que se pueden ejecutar en paralelo. Necesito poder programar eventos periódicos y tareas en segundo plano que pueden o no ejecutarse por períodos mucho más largos.Diseño de una biblioteca de tareas asíncrona para ASP.NET

Teniendo en cuenta lo anterior tengo los siguientes problemas a tratar:

  • El dominio de aplicación puede apagar debido a los cambios (Web.config, BIN, App_Code, etc.)
  • IIS recicla el AppPool en una con regularidad (diaria)
  • IIS sí podría reiniciar, o para el caso el servidor puede bloquearse

no estoy convencido de que la ejecución de este código dentro de ASP.NET no es lo que hay que hacer, becuase permitiría un modelo de programación más simple. Pero hacerlo requeriría que un servicio externo realice periódicamente solicitudes a la aplicación para que la aplicación se mantenga en funcionamiento y todas las tareas en segundo plano se programen con la máxima atención. Tendrán que poder pausar y reanudar su trabajo, en el caso de un error inesperado.

Mi actual línea de pensamiento es algo como esto:

Si todos los puestos de trabajo están registrados en la base de datos, debe ser posible utilizar la base de datos como un mecanismo de contabilidad. En el caso de un error, la base de datos contendría todo el estado necesario para reanudar la operación en la próxima oportunidad dada.

Realmente recomiendo algunos comentarios/consejos sobre este asunto. He estado considerando ejecutar un servicio de Windows y también usar alguna solución RPC, pero no tiene el mismo atractivo para mí. Y en cambio, tendría muchos problemas de implementación y tareas de sincronización y código para cruzar varias aplicaciones. Debido a las necesidades de mi negocio, esto es menos que óptimo.

Respuesta

4

Esto es un tiro en la oscuridad ya que no sé qué base de datos utiliza, pero le recomiendo que considere dialog timers y activation. Suponiendo que más de los puestos de trabajo tienen que hacer alguna manipulación de datos, y es probable que todo tienen que ver única manipulación de datos, aprovechando la activación y temporizadores dar una solución de planificación de tareas extremadamente fiable, totalmente integrado en la base de datos (sin necesidad de un proceso/servicio externo, no dependencias fuera de los límites de la base de datos como msdb), y es una solución que garantiza que los trabajos programados puedan sobrevivir a reinicios, eventos de conmutación por error e incluso restauraciones de recuperación de desastres. En pocas palabras, una vez que se programa un trabajo, se ejecutará incluso si la base de datos se restaura una semana más tarde en una máquina diferente.

Eche un vistazo a Asynchronous procedure execution para un ejemplo relacionado.

Y si esto es demasiado radical, al menos échele un vistazo a Using Tables as Queues ya que el almacenamiento de los elementos programados en la base de datos a menudo cae dentro del caso de 'cola pendiente'.

+0

+1 para el enlace al artículo sobre la ejecución del procedimiento asíncrono. –

+0

Eso es asombroso, desafortunadamente no todas las tareas en segundo plano pueden escribirse solo en T-SQL, muchas de ellas probablemente podrían hacerlo, pero ahora, tenemos soporte de depuración limitado para T-SQL, así como, cosas que tienen que estar en C# código, como enviar correos electrónicos. Además, algunas de estas transformaciones que hacemos realmente se ven torpes en SQL y, a menudo, nos resultan más fáciles de mantener usando el código C#. Sobre las tablas como colas, hice algo similar en el pasado, pero no he visto estas variaciones antes, gracias por los enlaces. –

+0

La activación también puede iniciar procedimientos CLR, y también hay un activador externo que puede iniciar procesos normales (.exe): http://blogs.msdn.com/b/sql_service_broker/archive/2008/11/21/announcing- service-broker-external-activator.aspx –

2

Le recomiendo que eche un vistazo a Quartz.Net. Es de código abierto y te dará algunas ideas.

+1

Más que darte algunas ideas, hará prácticamente lo que quieras. – badbod99

+0

Excepto que no responde a mi mayor preocupación sobre la viabilidad de usar ASP.NET como entorno de alojamiento para tareas asincrónicas. Quartz, qué increíble podría ser, no ayudará aquí. –

+0

5 años después y aquí todavía estoy buscando un planificador de tareas de fondo amigable y confiable de asp.net con ejecución de trabajo asincrónica –

1

Te digo lo que tengo que hacer.

He creado una clase llamada Atzenta que tiene un temporizador (disparador de 1-2 segundos). También he creado una tabla en mi base de datos temporal que conserva los trabajos. La tabla conoce el ID de trabajo, otros parámetros, prioridad, estado del trabajo, mensajes.

Puedo agregar o eliminar un trabajo en esta clase. Cuando no hay que hacer ninguna acción, el cronómetro se detiene. Cuando agrego un trabajo, el temporizador comienza de nuevo. (el temporizador es un hilo por él mismo que puede hacer un trabajo paralelo). Yo uso System.Timers and not other timers for this.

Los trabajos pueden tener una prioridad diferente.

Ahora supongamos que coloco un trabajo en esta tabla usando la clase Atzenta. La próxima vez que se active el temporizador, verifique la consulta en esta tabla y busque el primer trabajo disponible y simplemente ejecútelo. No se ejecutarán otros trabajos hasta que este finalice.

Cada sincronización y banderas se hacen desde la tabla. En la tabla, tengo banderas para cada trabajo que muestran si es | esperar a ejecutar | solicitar ejecutar | ejecutar | pausa | finalizar | matar |

Todos los trabajos son todos conocidos funciones o clases (por ejemplo, la creación de estadísticas).

Para detener y comenzar, utilizo global.asax y Application_Start, Application_End para iniciar y poner en pausa el objeto que mantiene las tareas. Por ejemplo, cuando hago un trabajo, y obtengo el éter Application_End, espero terminar y luego detengo la aplicación, echo detengo la acción, notifico la tabla y comienzo de nuevo en application_start.

Así que digo, Atzenta.RunTheJob (Jobs.StatisticUpdate, ProductID); y luego agrego este trabajo en la tabla, abro el temporizador, y luego en el disparador se ejecuta este trabajo y actualizo las estadísticas para la identificación del producto.

Utilizo una tabla en una base de datos para sincronizar muchos grupos que ejecutan la misma aplicación web y, de hecho, su trabajo de esa manera. Con una tabla común, la sincronización de los trabajos es fácil y evita que 2 grupos ejecuten el mismo trabajo al mismo tiempo.

En mi back office tengo una vista de tabla simple para ver el estado de todos los trabajos.

+0

Me gusta esto, ¿ha tenido algún problema relacionado con la interrupción o la interrupción inesperada de la aplicación? –

+0

@John No, no tengo ningún problema especial. No apago el servicio web, pero abro el app_offline.htm cuando realizo la actualización, luego espero ver en el registro que todas las aplicaciones se han completado, así que no las obligo a detenerse. Además, no está fallando: si lo veo, lo veo en el registro y hago un bloqueo de prueba/captura, y así sucesivamente. Si el proceso sobre la mesa ha fallado por algún motivo, lo entiendo por el hecho de que el estado está en ejecución, pero no estoy ejecutando nada en este momento. Es una bandera más simple guardada en la base de datos que corro algo. – Aristos

+0

@John uno de los procesos es un índice personalizado de mi texto en la base de datos. El primer día se ejecutó durante más de 28 h para completar sin problemas. Más tarde corrijo una forma de marcarlo y pausar este indexador. – Aristos

2

Usar la base de datos como un mecanismo de mantenimiento del estado es una idea completamente válida. Cuán complejo será depende de qué tan lejos lo quiera tomar. En muchos casos, terminará emparejando su lógica de base de datos con un servicio de Windows para lograr el resultado deseado.

FWIW, normalmente no es una buena práctica usar manualmente el grupo de subprocesos dentro de una aplicación ASP.Net, aunque (al contrario de lo que puede leer) en realidad funciona muy bien, aparte de la gran advertencia de que no se puede garantía funcionará.

Si necesitabas un hilo de fondo que examinara el estado de un objeto cada 30 segundos y no te preocupara si se disparaba cada 30 segundos o 29 segundos o 2 minutos (como en un largo reciclaje de grupo de aplicaciones), un subproceso generado por ASP.Net es una solución rápida y muy sucia.

Las devoluciones de llamadas disparadas de forma asíncrona (como en el objeto ASP.Net Cache) también pueden realizar una especie de función "detrás de escena".

Me he enfrentado a desafíos similares y finalmente opté por un servicio de Windows que utiliza una combinación de bloques de construcción para una flexibilidad máxima.Es decir, que utilizo:

1) WCF con tipos específicos de la implementación O

2) Los tipos que tienen el propósito de transportar y manejar objetos que envuelven un trabajo o

3), objetos serializables completamente genéricos contenida en una envoltura personalizada. Como solo son una carga binaria, esto permite que cualquier objeto pase al servicio. Una vez en el servicio, el contenedor define lo que le debería suceder al objeto (por ejemplo, invocar un método, recopilar un resultado y, opcionalmente, hacer que ese resultado esté disponible para su devolución).

En última instancia, el sitio web es responsable de consultar el servicio acerca de su estado. Esta consulta puede ser tan simple como una encuesta o puede usar devoluciones de llamada asincrónicas con WCF (aunque creo que esto también utiliza algún tipo de sondeo entre bastidores).

+0

Gracias por la respuesta, estoy considerando serializar tipos (enviando el código IL) para su ejecución en un entorno remoto. Si uso el enfoque de servicio de Windows, entonces necesitaré un mecanismo remoto o de invocación remota realmente flexible, tal vez WCF podría facilitar esto, pero todavía habrá muchas pequeñas tareas que solo existirán en ciertas bases de código y estas necesitan de alguna manera trabajar con el servicio –

+0

Encontré que las restricciones de DataContract usando WCF son difíciles de manejar cuando necesita enviar numerosos tipos de objetos a un servicio para su ejecución remota. Me salvé esto al declarar algunos objetos envoltorios capaces de transportar mis árboles de objetos (como matrices de bytes) e instrucciones simples sobre cómo usar esos objetos. Entonces WCF solo necesita estar al tanto de las interfaces de esos objetos de envoltura, y se elimina una de las grandes barreras (IMO). Cuando dice "solo existe en ciertas bases de código", ¿quiere decir que el servidor de ejecución no podría hacer referencia a esos tipos? –

+0

Obviamente, el host de ejecución tiene que poder hacer referencia a esos tipos, pero nunca es un conjunto fijo de cosas que deba hacerse. Esto varía mucho. Sutil pero existen diferencias. No creo que esté creando una serie de servicios que se ejecutarán en nombre de alguna otra aplicación. –

Cuestiones relacionadas