Estamos tratando de hacer que Service Broker trabaje en nuestro entorno para resolver un caso de negocios. No sé si el título del mensaje es bueno, pero mi pregunta está a continuación. Pero puede que no sea una buena pregunta, así que después de eso es lo que estamos haciendo y por qué creo que es la pregunta correcta.
¿Cuántos mensajes se deben enviar en una conversación antes de finalizarla?
Queremos usar Service Broker para actualizar asincrónicamente una tabla de resultados. La tabla de resultados es aplanada y rápida. Tenemos activadores en las tablas base que envían un mensaje con su tabla y clave principal. Tenemos tres colas:
- Baja latencia: el objetivo es procesar 15 segundos. Maneja elementos que cambian en relación con un elemento específico.
- Cola masiva: el objetivo es procesar 5 minutos. Se maneja cuando algo cambia que afecta a muchos cientos (o miles) de elementos. Desglosa la lista de elementos afectados y los alimenta a la Cola de baja latencia diferida
- Baja latencia diferida: el objetivo es procesar 30 minutos. Esto procesa elementos pero solo desde la cola masiva.
Básicamente, si la información de un cliente se actualiza; eso afecta a muchos productos, por lo que se envía a la cola masiva para un procesamiento más lento. Sin embargo, si un producto se actualiza, se envía a la cola de baja latencia.
Reutilizamos conversaciones similares al blog de Remus Rusanu http://rusanu.com/2007/04/25/reusing-conversations/ , con la excepción de que lo hacemos en función del módulo de la clave primaria. Esto tiene el beneficio secundario de ayudar en la desduplicación de las claves primarias.
Por lo tanto, estamos reutilizando conversaciones y estamos dentro de nuestras pautas. Con dos hilos, pude grabar 125 mensajes / segundo (caída artificial de varios miles de mensajes), que es más que capaz de mantenerse al día con la producción (est. 15 mensajes / segundo).
Sin embargo, el problema que estamos experimentando es que después de un período de tiempo, ~ 4 horas o mensajes de 120K, comenzamos a ver bloques y una alta contención en sysdesend y la tabla de colas. Los bloqueos son LCK_M_U y son bloqueos CLAVE. A veces, la resolución resuelve enviar sysdesend y otras veces a la tabla de cola específica (queue_).
Tenemos un proceso en marcha que finalizará las conversaciones después de 24 horas o 30 minutos de inactividad, por lo que podríamos aumentar el tiempo antes de pasar de una conversación a otra.
Estamos utilizando SQL 2016 Enterprise (13.0.4001.0)
- Disparar incendios (enviar a baja latencia o en masa)
- Busque o cree un identificador de conversación.
- enviar mensaje
- Procedimiento activado en cola
- Actualizar tabla de resultados
El proceso de limpieza se ejecuta cada 10 minutos para ver si hay conversaciones inactivas. Si los encuentra más de tres veces seguidas, lo marca como inactivo y finaliza las conversaciones.
Avíseme si hay algún detalle adicional que pueda ser beneficioso. No tengo mucha experiencia con Service Broker, así que no sé si nuestros mensajes / segundo son bajos, altos o indiferentes.
ACTUALIZAR
Así que lo intentamos nuevamente hoy y encontramos el mismo problema. Cambiamos la duración de la conversación a 2 horas y eso no tuvo ningún efecto. Entonces implementamos el truco 150; que tenía el mismo problema
Toneladas de espera en ENVIAR CONVERSACIÓN, esperando en sysdesend. ¿Alguien tiene alguna idea más?
ACTUALIZACIÓN 2
Corrimos la prueba durante más tiempo hoy y durante uno de los períodos de muestra de 17 minutos, procesamos 41K mensajes en 4 identificadores de conversación. Pudimos mantener el ritmo, excepto hacia el final cuando las cerraduras en el sysdesend y la mesa de la cola se volvieron demasiado y comenzamos a retroceder antes de detenerlo. Parece que no tenemos problemas para procesar mensajes, sin elementos que entran en la cola, podemos sacarlos y procesarlos al menos 5 veces más rápido. Nuestra velocidad parece estar limitada en función de agregar mensajes.
En una prueba posterior, eliminamos uno de los desencadenantes que representaban el 80% de los mensajes. Incluso con esta carga muy reducida, comenzamos a ver las mismas esperas.
ACTUALIZACIÓN 3
Gracias, Remus por tu consejo (y gracias por publicar tan excelentes artículos de blog sobre el tema, fueron fundamentales para llegar a este punto).
Lo volvimos a ejecutar hoy y lo hicimos mejor (ya que pasamos más tiempo antes de ver las esperas y aún más antes de que nos paralizara). Entonces, los detalles.
Cambiamos: * Aumentamos el número de conversaciones mantenidas por hilo de 1: 1 a 2: 1. Básicamente, teníamos 8 identificadores de conversación para 4 hilos.
- consolidó la cola masiva (porque un mensaje entrante podría significar cientos de mensajes salientes) para consolidar en menos mensajes más grandes.
Notas sobre este intento:
deshabilitando el procedimiento de activación de la cola objetivo. no hubo cambios en el bloqueo (esperamos 5 minutos) y los mensajes se enviaron a sys.transmission_queues.
Supervisión de sys.conversation_endpoints. Este número pasó de 0 a 13K muy rápidamente, y luego aumentó más lentamente durante todo el día y terminó alrededor de 25K después de ~ 5 horas. El bloqueo no comenzó a ocurrir hasta que alcanzó 16K +/-
Entré en el DAC y ejecuté los comandos DBREINDEX para las colas, aunque a partir de una consulta, los registros fantasma nunca superaron los 200 antes de que apareciera la limpieza y reduje el recuento a 0.
sysdesend y sysdercv tenían conteos idénticos de 24,932 cuando terminé la prueba.
procesamos ~ 310K mensajes en 5 horas.
Pasamos tanto tiempo antes de que las cosas se derrumbaran que realmente pensé que lo haríamos esta vez. Mañana intentaremos obligar a los mensajes a pasar por el cable.
sys.conversation_endpoints
durante la prueba (constante o está aumentando, y qué tan grande es cuando ocurre el bloqueo). 2) Cuando ocurre el bloqueo, la desactivación de la cola objetivo hace una diferencia en el bloqueo de ENVIAR (la desactivación de la cola debe enrutar SEND a sys.transmission_queue). y 3) Obligar a los mensajes a ir al cable, incluso localmente (configurar el punto final SSB, agregar rutas) cambia el comportamiento a largo plazo
ALTER QUEUE ... REBUILD
hace una diferencia una vez que comienza el bloqueo?
we started seeing blocks and high contention on sysdesend and the queue table.
-> ¿Cuál es el tipo de espera -PAGELATCH_EX/SH and WRITELOG
? ¿Has usado el truco 150 ? Si las tablas del sistema son su punto de contención, el truco de 150 será muy útil.