Pregunta

También he publicado esta pregunta en mi blog: http://www.sqldiablo.com/2012/04/15/service-broker-alwayson-availability-groups-odd-transmission-queue-behavior/.

He estado trabajando en un proyecto en los últimos meses que utilizará el corredor de servicios y siempre en grupos de disponibilidad para cumplir con algunos de los objetivos de HA y DR de la compañía para la que trabajo (más información: http://www.sqldiablo.com/service-broker-replication/). Recientemente, pude implementar la solución completa en mi laboratorio de desarrollo y señalar una instancia de nuestro sitio web. Mientras estábamos trabajando en algunos problemas en nuestra base de datos y un sitio web para que los dos funcionen bien con mi proyecto de replicación de corredores de servicio, comencé a notar un comportamiento extraño en el corredor de servicios cuando se usa con siempre grupos de disponibilidad, y quería bloguear sobre él Un intento de ver si alguien más ha visto este problema y podría tener una idea de cómo abordarlo.

La puesta en marcha:

Tengo un host Hyper-V que ejecuta 6 VMS R2 de Windows Server 2008 (BTDEVSQLVM1-BTDEVSQLVM6). Las máquinas virtuales se agrupan en WSFC de 2 nodos con Node y File Share Quorum. Instalé instancias independientes de la edición de desarrollador SQL 2012 en cada una de las máquinas virtuales, y creé un grupo de disponibilidad con un oyente en cada clúster (SBRepldistrib, SBRePL1 y SBREPL2).

A los efectos de esta publicación de blog, me centraré en la comunicación entre SBREPL1 y SBREPLDISTRIB. La siguiente ilustración muestra los objetos de corredor de servicio para cada lado de la conversación:

(Soy nuevo y no puedo publicar imágenes todavía, así que vea mi blog en la URL de arriba para la imagen)

Los puntos finales y las rutas del corredor de servicio están configurados por Este artículo de MSDN. La ruta Sbrepl_RECEive en MSDB es para el servicio del servidor local (// sbrePldistrib/sbrepl en sbrePldistrib, y // sbrepl1/sbreple en sbrepl1), y señala la instancia local. La ruta Sbrepl_Send en el servicio de mapas SBRepl1 // SBREPLDISTIB/SBREPL a TCP: // SBREPLDISTRIB: 4022, y la ruta SBREPL_SEND_SBREPL1 en SBREPLDISTITRIB es una asignación similar para el servicio en SBRepl1.

El comportamiento esperado:

Mi comprensión de cómo el corredor de servicio maneja el envío y la recepción de mensajes es, por lo tanto, (esto está bastante simplificado. Hay muchos más detalles sobre este proceso en el libro de Klaus Aschenbrenner "Pro SQL Server 2008 Service Broker")::

  1. La aplicación de iniciador crea un mensaje (en este caso, XML bien formado)
  2. Si hay una conversación de diálogo existente entre el servicio de iniciador y el servicio de destino que está en el estado de conversación, la aplicación simplemente puede enviar el mensaje en el mango de conversación existente. De lo contrario, la aplicación de iniciador debe comenzar una conversación de diálogo entre el servicio de iniciador y el servicio de destino y enviar el mensaje en ese manejo de conversación.
  3. El mensaje se coloca en la tabla del sistema SYS.TRANSMISSION_QUEUE y el corredor de servicios comienza a hacer intentos para entregar el mensaje al servicio de destino.
  4. Service Broker busca una ruta apropiada y la vinculación del servicio remoto y los utiliza para determinar la dirección a la que se conecte para entregar el mensaje.
  5. Service Broker abre una conexión al objetivo, se autentica y entrega el mensaje al corredor de servicio de destino.
  6. El corredor de servicio de destino intenta clasificar el mensaje y determinar qué servicio local manejará el mensaje (utiliza datos de ruta en la base de datos MSDB para esto).
  7. El corredor de servicio de destino entrega el mensaje a la cola del servicio de destino
  8. Una vez que el mensaje se entrega con éxito a la cola de destino, el corredor de servicio de destino busca información de ruta al iniciador e intenta entregar un reconocimiento de que se recibió el mensaje.
  9. El corredor de servicios del iniciador recibe el reconocimiento y utiliza información de enrutamiento en MSDB para determinar para qué servicio local es el reconocimiento.
  10. Tras el enrutamiento exitoso del reconocimiento al servicio de iniciación, el mensaje se elimina de la tabla del sistema SYS.TRANSMISSION_QUEUE.
  11. Si el iniciador no recibe un reconocimiento de que se recibió el mensaje, volverá a intentarlo entregando periódicamente el mensaje al objetivo. Si el objetivo ya ha recibido el mensaje, simplemente eliminará cualquier reintento de entrega adicional y les enviará reconocimientos para ellos.

El comportamiento extraño:

El paso 11 es donde estoy viendo un comportamiento muy extraño con el corredor de servicio y siempre. Veo que el mensaje se entrega al objetivo y se procesa con éxito, y también veo el reconocimiento que se envía de regreso al iniciador y recibió. Sin embargo, el mensaje permanece en sys.transmission_queue como si no se recibiera ningún reconocimiento. Para hacer las cosas aún más extrañas, Service Broker no intenta reenviar el mensaje como lo esperaría si no se recibiera el reconocimiento. En cambio, el mensaje simplemente permanece en el sys.transmission_queue, y a medida que se envían nuevos mensajes, se entregan, reconocen y también permanecen en el sys.transmission_queue. Me parece que el corredor de servicio está recibiendo los reconocimientos y, por lo tanto, deja de tratar de entregar el mensaje, pero no lo elimina del sys.transmission_queue por alguna razón. La transmisión_status para estos mensajes permanece en blanco, lo que debería indicar que el corredor de servicios aún no ha intentado entregarlos.

Verifiqué la configuración de retención en la cola de servicio, y está configurada, pero eso solo debería afectar la cola de servicio y no el sys.transmission_queue. También he rastreado ambos lados de la conversación usando SQL Profiler, y puedo ver el mensaje que se envía y el reconocimiento que se envía de regreso al iniciador y recibe datos de rastreo XML al final de esta publicación).

Sin embargo, una cosa extraña saltó hacia mí en las trazas. Noté que ambas partes parecían estar un poco confundidas acerca de las conexiones TCP, porque los mensajes se envían desde la dirección IP del nodo en sí, mientras que las rutas de servicio y los mensajes en sí apuntan al nombre/IP del oyente AG. Esta confusión parece estar causando que cada lado cierre la conexión existente entre los dos servicios y cree una nueva para entregar un mensaje o reconocimiento. No estoy seguro de si esto es normal o no o si tiene algo que ver con por qué los reconocimientos no se manejan correctamente, pero fue lo único que podría ver que podría explicar el comportamiento extraño.

La súplica de ayuda:

En este momento, no tengo una solución a este problema de retención de mensajes que no sea terminar manualmente la conversación con la limpieza en ambos lados, y eso no es realmente algo que quiero hacer. Si tiene alguna idea de por qué esto podría estar sucediendo o qué puedo hacer al respecto, déjeme un comentario y hágamelo saber. Si hay alguna información adicional que desea que proporcione sobre mi configuración o sobre el problema, hágamelo saber en los comentarios también. Publicaré un seguimiento de esta publicación si/cuando encuentro una solución a este problema.

Los datos de trazas:

Consulte mi publicación de blog (la URL está al comienzo de la pregunta).

¿Fue útil?

Solución

En los últimos meses, he estado trabajando con el equipo de soporte de productos de Microsoft, y han reconocido dos errores en SQL Server 2012 en relación con este problema. Lanzarán parches para esos errores como parte del próximo paquete de servicio para SQL Server 2012.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a dba.stackexchange
scroll top