2009-02-06 10 views
13

La arquitectura de uno de nuestros productos es una solución típica de 3 niveles:Manejo web del Servicio de Tiempos de espera mientras se realiza a largo Ejecución de tareas de base de datos

  • C# cliente
  • servicio web WCF
  • base de datos de SQL Server

El cliente solicita información del servicio web. El servicio web accede a la base de datos para obtener la información y la devuelve al cliente.

Aquí está el problema. Algunas de estas consultas pueden llevar mucho, mucho tiempo, y no sabemos de antemano cuáles serán lentas. Sabemos que algunas son a menudo más lentas que otras, pero incluso las solicitudes más simples pueden ser lentas dado datos suficientes. A veces utiliza consultas o ejecuta informes en grandes cantidades de datos. Las consultas se pueden optimizar solo hasta el momento antes de que el volumen total de datos las ralentice.

Si una consulta en la base de datos llega al máximo tiempo de espera de consulta en el servidor SQL, la consulta de la base de datos finaliza y el servicio web devuelve un error al cliente. Esto es entendido Podemos manejar estos errores.

El cliente está esperando a que se complete la llamada del servicio web. Si la llamada a la base de datos tarda mucho tiempo, el cliente puede agotar el tiempo de espera en su llamada al servicio web. El cliente se da por vencido, pero la solicitud de la base de datos continúa el proceso. En este punto, el cliente no está sincronizado con la base de datos. La llamada a la base de datos puede tener éxito o no. Puede haber habido un error. El cliente nunca lo sabrá. En algunos casos, no deseamos que nuestros usuarios inicien otra solicitud que pueda dar como resultado un estado no válido dada la finalización de la solicitud anterior.

Tengo curiosidad por ver cómo otros han manejado este problema. ¿Qué estrategias ha utilizado para evitar que los tiempos de espera del servicio web afecten las llamadas a la base de datos?

Las mejores ideas que se me ocurren son: crear una capa de base de datos real en algún lugar, dentro del servicio web, adjunta a una cola de mensajes, algo. La descarga de cada consulta a otro proceso parece excesiva. (Por otra parte, no siempre sabemos si una solicitud determinada será rápida o lenta.)

Sería genial si pudiéramos separar el acto de realizar una solicitud HTTP desde el acto de iniciar y ejecutar un proceso de base de datos . He visto esto hecho con un servidor personalizado en una compañía anterior, pero estaba usando una comunicación directa de socket, y prefiero evitar reemplazar el servicio web con alguna aplicación personalizada.

Tenga en cuenta que dada la cantidad de datos que manejamos, estamos en la optimización de la consulta. La optimización de consultas, los índices, etc., solo lo lleva tan lejos cuando el volumen de datos es alto. A veces las cosas solo toman mucho tiempo.

Respuesta

2

Una de las soluciones que hemos utilizado últimamente es dividir los enormes procesos de bases de datos en operaciones paralelas separadas. Cada operación es mucho más pequeña y está diseñada para ser lo más eficiente posible. Los clientes inician las operaciones, engendran algunos hilos y hacen lo que pueden en paralelo.

Por ejemplo, hemos dividido algunos procesos enormes en una serie de pasos como Inicio, Procesar 1 fragmento de trabajo, Terminar y Recopilar datos de informe. Los pasos de trabajo de proceso pueden ejecutarse en paralelo, pero no pueden comenzar hasta que se complete el paso de inicio. El paso Finalizar debe esperar a que se completen todos los pasos del Proceso de trabajo.

Dado que el cliente está controlando el proceso, el cliente puede informar el progreso exactamente en qué paso está.

5

El servicio web podría ejecutar las consultas en un subproceso y si el subproceso no termina dentro de, digamos 5 segundos (vea Subproceso.Enlazar()), la llamada de servicio web le devuelve al cliente un ID de tarea en lugar del conjunto de resultados que el cliente puede usar para sondear el servidor cada pocos segundos para ver si su consulta finalizó. Cuando termina un hilo, los resultados se pueden almacenar en una tabla hash hasta que el cliente vuelva a sondear.

6

que he encontrado problemas parecidos en el pasado, y se utiliza uno de los siguientes 3 métodos para resolverlo:

  1. Agrega todas las consultas de larga ejecución de una cola y procesar estos secuencialmente.
    En mi caso, todos estos eran informes complicados que luego se enviaban por correo electrónico al cliente, o que se almacenaban en tablas permanentes "temporales", para que los clientes los pudieran ver después de haberlos notificado.
  2. Llamamos a un servicio web usando una llamada JQuery, que luego llamó a un método de devolución de datos de JavaScript cuando se completó.
    Esto funcionó bien cuando no queríamos que la carga de la página se sincronizara con lo que estaba haciendo el servicio web.
    Sin embargo, eso significaba que esa pieza de funcionalidad no estaba disponible hasta que se completó el proceso de larga ejecución.
  3. El más complicado.
    Aparece otra ventana que muestra una barra de progreso, que también sondea el servidor periódicamente.
    Esto usó una variable de sesión para determinar qué tan lejos mostrar la barra de progreso.
    Después de que se inició la barra de progreso, se inició un nuevo subproceso que actualizaba periódicamente la misma variable de sesión.
    Una vez que el valor de la variable de sesión se estableció en 100, la ventana emergente se cerró sola.
    A los clientes les encantó este método.

De todos modos, espero que uno de esos sea de alguna ayuda para usted.

0

Resolver el problema en trozos pequeños es sin duda una buena idea.

Además de eso y de lo que otros dijeron (y solo si tienes la mano en la implementación del servicio web) he estado usando las URL de devolución de llamada que se han pasado al servicio web. El WS debe llamarlo con errores o resultados en la cadena de consulta o datos de publicación.

Las URL generalmente contienen un token que sirve para permitir que la devolución de llamada vuelva a entrar al cliente, y que se correlaciona con toda la información relevante necesaria para realizar acciones después de que se recibe la devolución de llamada (almacenada en una base de datos o en memoria).

Es un poco pesado (especialmente si ya no se está ejecutando en el servidor web) pero garantiza un viaje de ida y vuelta exitoso en caso de que el cliente se agote, pero el servicio web recibió las instrucciones correctamente y su procesamiento es lento.

Una vez que está configurado, su servicio web está realmente más cerca de estar listo para ejecutarse de forma asíncrona y responder rápidamente al cliente: generalmente, comprueba si está bien o no, y engendra la operación lenta en una bucle separado, con la url de devolución de llamada para que pueda informar al cliente.

No estoy seguro de qué tan ortodoxo es esto, por cierto, pero resolvió problemas reales.

Cuestiones relacionadas