2009-08-12 27 views
15

Soy un principiante de Sql Server Service Broker y estoy tratando de comprender la mejor manera de configurar Service Broker para un caso de uso (aparentemente) simple: quiero crear una cola de trabajo simple, donde una aplicación suelta elementos de trabajo en la cola, y la aplicación por separado recoge los elementos de trabajo de esa cola y los procesa. No es necesario que la primera aplicación recupere los mensajes de estado del segundo. Quiero que la cola viva en una sola instancia de servidor Sql.Sql Server Service Broker: ¿Cómo estructurar Conversations para un escenario de cola simple?

Lo que más me confunde es cómo las conversaciones/diálogos se relacionan con esta situación. Sé que solo puede enviar/recibir mensajes en el contexto de una conversación/diálogo, pero como no hay intercambio entre las dos aplicaciones, me siento perdido acerca de cuándo es la hora correcta para crear una nueva conversación. Las dos alternativas extremas parecen ser:

  • Cada vez que encola un elemento de trabajo, comienzo una nueva conversación. Entonces, cada conversación termina teniendo exactamente un mensaje.
  • En el momento del despliegue, creo manualmente una sola conversación de duración infinita. Cuando es hora de poner en cola un elemento de trabajo, siempre lo envío como parte de esa única conversación.

¿Cuáles serían las consecuencias de seguir cualquiera de estas rutas?

Además, en el primer caso, parece que necesito hacer algunas CONVERSACIONES FINALES, para que el Servidor SQL pueda limpiar los recursos internamente. ¿Hay alguna guía para saber cuándo sería el lugar correcto para colocarlos? (¿O es posible que sea mejor confiar en que las conversaciones se acaben?)

+0

Pareces estar hablando de una sola cola, pero ... http://stackoverflow.com/questions/14643015/why-do-i-need-two-sql-server-service-broker-colas-for-a-simple-task – cja

Respuesta

26

Debe comenzar con cada elemento de trabajo en su propia conversación. El productor (iniciador) comienza un diálogo y envía el mensaje que describe el elemento de trabajo y luego confirma. El consumidor (objetivo) recibe el mensaje (o se activa), inspecciona la carga útil para comprender los detalles del elemento de trabajo, ejecuta el trabajo, luego finaliza el diálogo y confirma. El mensaje EndDialog resultante se envía de vuelta a la cola del servicio del iniciador, y un procedimiento activado en la cola del iniciador responde al finalizar el diálogo en el lado del iniciador.

Esta es la implementación más simple y ponerla en funcionamiento garantizará que tenga una base sólida sobre la cual construir. No corte las esquinas y termine el diálogo en el lado del iniciador desde cuando el productor encola el elemento de trabajo, esto es fire-and-forget and has several draw backs.

Si tiene requisitos de alto rendimiento (más de 200 solicitudes por segundo), entonces deberá comenzar a administrar las conversaciones de manera más explícita. Tengo una entrada de blog en reusing conversations for performance reasons. En el lado de recepción, recomiendo leer Writing Service Broker Procedures.

También tengo una entrada de blog que hace bastante lo que necesita, aunque no planifica elementos de trabajo sino que en su lugar inicia un procedimiento personalizado: Asynchronous procedure execution.

Si decide consumir los elementos de trabajo desde un contexto activado, aprovechando las capacidades de auto-equilibrio de la activación, entonces necesita understand the EXECUTE AS context under which activation occurs.

+0

Otra ventaja de reutilizar conversaciones es que evita el problema descrito en "Solicitud de trabajo interno de Microsoft 642585" (no publico). A saber, cada conversación que creas y destruyas filtra una pequeña cantidad de espacio asignado en TempDB que no se libera hasta que rebotas la instancia. En aplicaciones de alto rendimiento, esto puede reducir el tamaño de TempDB y obligarlo a reiniciar la instancia para reducirla de nuevo. –

+0

Un problema con el uso de una conversación por separado con cada mensaje es que las conversaciones pueden aparecer en el otro extremo fuera de secuencia. Esto puede suceder incluso si solo tiene un hilo en el extremo receptor. Recuerde que Service Broker solo garantiza la secuencia dentro de una conversación. El motivo de las Conversaciones es gestionar la secuencia cuando hay varios hilos en el extremo de recepción de la cola. Si las conversaciones se mantuvieron en secuencia, así como los mensajes, prohibiría el uso de múltiples hilos de recepción. –

9

Me gusta mucho la respuesta de Remus, aunque no toca especialmente en por qué puede preferir iniciar una conversación por cada elemento de trabajo, en lugar de poner todos los elementos de trabajo en una conversación.Dos notas relacionadas con esto:

En primer lugar, poner todos los elementos de trabajo en una sola conversación probablemente provoque problemas de concurrencia si tiene múltiples hilos/procesos procesando elementos de trabajo. procesos de trabajo de agente de servicios tienden a tener este aspecto (en pseudocódigo):

begin transaction 
receive top n work items from queue 
process work items 
commit transaction 

(Al no haber cometido hasta que los elementos de trabajo se procesan correctamente, se asegura, por ejemplo, que si el proceso muere entonces los elementos de trabajo que ha recibido pero no procesado no se eliminará de la cola.)

El problema de concurrencia surgiría porque el intermediario de servicios está programado de manera que cada comando RECEIVE adquiere un bloqueo de lectura exclusivo en todos los mensajes de la cola que comparten la misma conversación (o grupo de conversación) como los que fueron RECIBIDOS. Ese bloqueo se mantiene hasta que se compromete la transacción. (Consulte Conversation Group Locks). De modo que si todos los elementos de trabajo en la cola están en una sola conversación, mientras un proceso de trabajador está en el paso "procesar elementos de trabajo", ningún otro proceso de trabajo puede estar haciendo ningún trabajo.

Un segundo problema al colocar muchos elementos en una sola conversación es que aumenta la cantidad de elementos de trabajo que podría perder o tener que volver a procesar en ciertas condiciones de error. Para describir esto propiamente, lo defero a Remus; vea su Recycling Conversations, especialmente la parte que dice "reutilizar un solo cuadro de diálogo para enviar todos sus mensajes [...] es como poner todos sus huevos en una sola canasta". Es posible que pueda recuperarse de algunas de estas situaciones de error, pero probablemente le aporte más complejidad a su código.

Probablemente haya algunos argumentos más contra la utilización de una sola conversación para todos los elementos de trabajo, pero no estoy tan familiarizado con ellos.

Esto no quiere decir que la solución correcta sea siempre iniciar una conversación por separado para cada elemento de trabajo. Después de haber leído las publicaciones de Remus, su consejo parece sólido; comience con un elemento de trabajo por conversación y luego agregue complejidad si es necesario. (Pero probablemente en ningún caso deberías ir al extremo de poner todos los mensajes en una sola conversación.)

Cuestiones relacionadas