Me encanta modificar el código de SQL Server para mejorar el rendimiento, pero ocasionalmente hay escenarios en los que, incluso después de ajustar el código, indexar y diseñar, una tarea de usuario desde la aplicación tarda más en completarse que la experiencia esperada del usuario final. Cuando esto sucede, la interfaz de usuario tiene que esperar a que se complete el proceso o tenemos que encontrar una forma alternativa de manejar la tarea. El procesamiento asíncrono proporcionado por Service Broker es una buena opción para muchos de estos escenarios y permite que el procesamiento en segundo plano de la tarea de ejecución prolongada se realice por separado de la interfaz de usuario, lo que permite que el usuario continúe trabajando de inmediato sin esperar a que la tarea se realice realmente. . En mis próximos artículos, espero crear una serie sobre cómo puede aprovechar Service Broker con las explicaciones adecuadas y ejemplos de código a lo largo del camino para que sea más fácil aprovechar las capacidades de Service Broker sin problemas de implementación.
Métodos para realizar el procesamiento asíncrono
Hay varias formas de lidiar con un proceso de larga ejecución, pero ya ajustado. El código de la aplicación también se puede reescribir para usar un BackgroundWorker, el ThreadPool de fondo o una solución basada en subprocesos escrita manualmente en .NET que realiza la operación de forma asíncrona. Sin embargo, esto permite que la aplicación envíe un número ilimitado de estos procesos de ejecución prolongada, a menos que se realice un trabajo de codificación adicional para rastrear y limitar el número de procesos activos. Esto significa que la aplicación tendrá un impacto potencial en el rendimiento, o bajo carga alcanzará un límite y volverá a la espera anterior que intentábamos evitar originalmente.
También he visto este tipo de procesos convertidos en trabajos del Agente SQL vinculados a una tabla que se utiliza para almacenar la información a procesar. Luego, el trabajo está programado para ejecutarse periódicamente o la aplicación lo inicia usando sp_start_job
cuando se almacena un cambio para su procesamiento. Sin embargo, esto solo permite una ejecución en serie de los procesos de ejecución prolongada, ya que el Agente SQL no permite que un trabajo se ejecute varias veces al mismo tiempo. El trabajo también tendría que estar diseñado para manejar escenarios en los que ingresan varias filas a la tabla de procesamiento para que se produzca el orden de procesamiento correcto y los envíos posteriores se procesen por separado.
Aprovechar Service Broker para el procesamiento asincrónico en SQL Server en realidad aborda las limitaciones con los métodos mencionados anteriormente para manejar el procesamiento asincrónico. La implementación del intermediario permite poner en cola nuevas tareas para el procesamiento asincrónico en segundo plano y también permite el procesamiento paralelo de las tareas que se han puesto en cola hasta un límite configurado. Sin embargo, a diferencia del nivel de aplicación que tiene que esperar cuando se alcanza el límite, la solución de intermediario simplemente pone en cola el nuevo mensaje que se recibe y permite que se procese cuando se completa una de las tareas de procesamiento actuales; esto permite que la aplicación continúe sin esperar.
Configuración de agente de servicio de base de datos único
Si bien las configuraciones de Service Broker pueden volverse complejas, para un procesamiento asíncrono simple, solo necesita conocer los conceptos básicos para crear una configuración de base de datos única. Una única configuración de base de datos solo requiere:
- Creación de dos tipos de mensajes
- Uno para solicitar el procesamiento asíncrono
- Uno para el mensaje de respuesta cuando finaliza el procesamiento
- Un contrato que utiliza los tipos de mensaje
- Define qué tipo de mensaje envía el servicio iniciador y qué tipo de mensaje devuelve el servicio de destino
- Una cola, un servicio y un procedimiento de activación para el objetivo
- La cola proporciona el almacenamiento de mensajes enviados al servicio de destino por el servicio iniciador
- El procedimiento de activación automatiza el procesamiento de mensajes de la cola
- Devuelve un mensaje completo al servicio de iniciador cuando completa el procesamiento de una tarea solicitada
- Administra los tipos de mensajes del sistema http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog y http://schemas.microsoft.com/SQL/ServiceBroker/Error
- Una cola, un servicio y un procedimiento de activación para el iniciador
- La cola proporciona el almacenamiento de mensajes enviados al servicio
- El procedimiento de activación es opcional pero automatiza el procesamiento de mensajes de la cola
- Procesa el mensaje completo al servicio de destino y finaliza la conversación
- Administra los tipos de mensajes del sistema http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog y http://schemas.microsoft.com/SQL/ServiceBroker/Error
Además de estos componentes básicos, prefiero usar un procedimiento almacenado de contenedor para crear una conversación y enviar mensajes entre los servicios de intermediario para mantener el código limpio y facilitar la escala según sea necesario mediante la implementación de la reutilización de conversaciones o el truco de 150 conversaciones explicado en el documento técnico del equipo SQLCAT. Para muchas de las configuraciones de procesamiento asíncrono simples, es posible que no sea necesario implementar estas técnicas de ajuste de rendimiento. Sin embargo, al usar un procedimiento almacenado contenedor, se vuelve mucho más fácil cambiar un solo punto en el código, en lugar de cambiar cada procedimiento que envía un mensaje en el futuro, en caso de que sea necesario.
Si no le ha dado un vistazo a Service Broker, podría proporcionar un método alternativo para realizar el procesamiento desacoplado de forma asincrónica para resolver una serie de escenarios posibles. En mi próxima publicación, revisaremos el código fuente para una implementación de ejemplo y explicaremos dónde se deben realizar cambios específicos para aprovechar el código para el procesamiento asíncrono.