2010-11-12 10 views
6

Tengo una función .NET que realiza algunos cálculos complejos. En función de los parámetros que se pasan en la función:Recomendaciones para diseñar un servicio web de larga duración y uso intensivo de recursos

  • lleva a cualquier lugar desde varios minutos a varias horas para ejecutar
  • utiliza el 100% de un solo núcleo durante el cálculo
  • requiere en cualquier lugar de 100s de MB a varios GB de memoria
  • Escribe desde varios MB a varios GB de datos en el disco
  • puede producir una excepción, incluyendo un OutOfMemoryException

La cantidad de datos que se escribirán en el disco se puede predecir con precisión a partir de la parametrización de la función. No hay una manera fácil de predecir los otros requisitos de recursos a partir de la parametrización de funciones.

Necesito exponer esta función a través de un servicio web. Este servicio tiene que ser:

  • resiliant y con gracia reportar cualquier problema durante el cálculo
  • Capaz de manejar peticiones concurrentes, siempre y cuando hay recursos suficientes para atender la solicitud sin degradación significativa del rendimiento, y negar con gracia la solicitud de lo contrario.

Tengo la intención de manejar la naturaleza de larga ejecución haciendo que la solicitud inicial devuelva un recurso de estado que se pueda sondear para el progreso. Una vez que se complete el cálculo, este recurso proporcionará la ubicación de los datos de salida, que el cliente puede descargar (probablemente a través de FTP).

No estoy tan seguro de cuál es la mejor manera de manejar los demás requisitos. Estoy considerando una especie de "grupo de cálculo" que mantiene las instancias de la calculadora y realiza un seguimiento de las que se están utilizando actualmente, pero no he descubierto los detalles.

¿Alguien con experiencia en situaciones similares tiene alguna sugerencia? Siempre que la solución se pueda ejecutar en una caja de Windows, se pueden considerar todas las opciones de tecnología.

+0

Tanto VladV como Steven han brindado respuestas muy útiles. Solo puedo marcar una respuesta como aceptada, así que elegí la de VladV según el número de votos al momento de escribir este comentario. – Akash

Respuesta

4

Le sugiero que divida su aplicación en dos partes.

  1. El servicio web en sí.Funcionalidad:
    • Obtiene un elemento de trabajo de un cliente;
    • Transfiera este trabajo a un servicio de back-end que realice el trabajo real;
    • Informe el progreso y el resultado;
  2. El servicio de back-end. Funcionalidad:
    • Procese las solicitudes desde el servicio web;
    • Realice el cálculo real.

Las razones de este diseño son
1) que es relativamente difícil de manejar la carga de trabajo en la aplicación alojada (ASP.NET) porque el servidor (IIS) gestionará los recursos, mientras que en una separada aplicación tienes más control directo;
2) el diseño de dos niveles es más escalable; por ejemplo, más adelante podría mover fácilmente el servidor a otra máquina física (o varias máquinas).

El servicio web debe ser sin estado; por ejemplo, después de que se acepta una solicitud, el usuario recibe una identificación y utiliza esta ID para sondear el servicio para obtener el resultado.

El servidor de back-end, probablemente, tiene que mantener una cola de las solicitudes de proceso y un conjunto de subprocesos de trabajo que las procesan. Los trabajadores deben supervisar los recursos disponibles y tener cuidado de no sobrecargar la máquina (y, por supuesto, manejar todas las condiciones de error posibles).

+0

Gracias, la idea de un servicio de back-end parece ser la clave. Ahora necesito pensar en cómo aislar las instancias de cálculo de modo que una falla en una no mate todo el servicio. – Akash

+1

Simplemente cree un controlador de excepción catch-all en cada hilo utilizado para el cálculo, de modo que un hilo de fondo nunca arroje una excepción al exterior. También podría usar AppDomains para aislar instancias entre sí, pero no creo que tenga mucho sentido aquí. Y si le preocupa que se quede sin memoria virtual, simplemente cambie al sistema operativo x64. – VladV

2

Si bien es posible que desee proporcionar una interfaz de servicio web, los servicios web generalmente no están diseñados para este tipo de procesos. Lo que podría querer hacer es reenviar la solicitud a un servicio de Windows (en una máquina dedicada) que pueda manejar esto. Los servicios de Windows no se reciclarán y tendrá mucho más control sobre el proceso.

Acerca del grupo de cálculo: lo que puede intentar es crear una cola de cálculo (por ejemplo, una tabla en la base de datos). De esta forma, puede tener múltiples servicios de Windows en máquinas dedicadas que procesan los cálculos. Esto puede permitirle escalar más fácilmente.

+0

Gracias, la idea de un servicio de backend parece ser la clave. Ahora necesito pensar en cómo aislar las instancias de cálculo de modo que una falla en una no mate todo el servicio. – Akash

+1

Lo que puede hacer es dejar que un servicio de Windows ejecute siempre un cálculo a la vez y cuando un cálculo (o el servicio) falla, puede marcar ese cálculo como fallido y registrar el error. Lo que hicimos en caso de falla dependía de la tarea en cuestión, pero normalmente reprogramábamos la tarea para que volviera a activarse más adelante. Por supuesto, debes asegurarte de que las tareas sean atómicas. Cuando una tarea tiene éxito, se marcará como 'hecho'. Los administradores tenían una interfaz de usuario que les permitía ver qué tareas estaban programadas, cuáles se estaban ejecutando, cuáles fallaban y por qué razón. – Steven

Cuestiones relacionadas