Patrón de convoy secuencial

Agrupa los mensajes relacionados por una clave de categoría y procesa cada grupo secuencialmente, un mensaje cada vez, mientras procesa grupos diferentes en paralelo.

Este patrón resuelve la tensión entre mantener la corrección de primero en entrar, primero en salir (FIFO) dentro de cada grupo lógico y ampliar el procesamiento concurrente entre grupos. El diseño garantiza que las restricciones de ordenación no se conviertan en un cuello de botella a nivel de todo el sistema.

Contexto y problema

A menudo, las aplicaciones necesitan procesar mensajes relacionados en el orden en que llegan mientras siguen escalando horizontalmente para controlar el aumento de la carga. En una arquitectura distribuida, este requisito es difícil de cumplir porque los procesos de trabajo recogen mensajes de forma independiente de una cola compartida. Cuando varios trabajadores compiten por mensajes, como en el patrón De consumidores competidores, la ordenación se desglosa.

Considere un sistema de seguimiento de pedidos que recibe una secuencia de operaciones, como crear un pedido, agregar una transacción, modificar una transacción pasada y eliminar un pedido. Las operaciones de cada orden deben procesarse en orden FIFO, ya que aplicarlas fuera de orden corrompería el estado de la orden. Sin embargo, la cola entrante intercala las operaciones en muchos pedidos. Un único consumidor que impone el orden global se convierte en un cuello de botella, y varios consumidores pueden procesar las operaciones del mismo pedido sin respetar la secuencia.

Los enfoques sencillos de este problema se desglosan de una manera diferente:

  • Consumidor único. Un único consumidor conserva el orden de los mensajes porque procesa un mensaje cada vez, pero no se puede escalar para controlar el aumento del rendimiento.

  • Varios consumidores competidores. Varios consumidores escalan el rendimiento mediante la extracción de mensajes en paralelo, pero pierden garantías de ordenación por grupo. Dos trabajos pueden extraer mensajes consecutivos para el mismo orden y procesarlos simultáneamente o fuera de secuencia, lo que daña el estado de orden.

Solución

El patrón Convoy secuencial divide los mensajes relacionados en categorías y procesa cada categoría secuencialmente, un mensaje cada vez, mientras que las categorías se procesan en paralelo.

El patrón funciona asignando a cada mensaje una clave de categoría que identifica el grupo al que pertenece. Un agente de mensajes usa esta clave para particionar mensajes en grupos lógicos. Dentro de cada grupo, el broker aplica el orden FIFO para que un consumidor que obtiene un bloqueo sobre un grupo reciba los mensajes estrictamente en la secuencia en la que se pusieron en cola. Los distintos grupos pueden procesarse simultáneamente por distintos consumidores, por lo que el sistema se escala horizontalmente entre grupos sin sacrificar la ordenación dentro de ningún único grupo.

En Azure, Azure Service Bus sesiones de mensajes proporcionan una implementación integrada de este patrón.

En el diagrama siguiente se muestra el patrón general de convoy secuencial.

Diagrama del patrón convoy secuencial. Muestra un productor, una cola central y tres consumidores.

En la cola, los mensajes de diferentes categorías se pueden intercalar, como se muestra en el diagrama siguiente.

Diagrama que muestra cuatro categorías de mensajes intercalados en una sola cola. Cada categoría ocupa su propio carril horizontal.

Este patrón proporciona varias ventajas clave:

  • Procesamiento ordenado por grupo. Los mensajes dentro de cada categoría se procesan estrictamente de forma secuencial, lo que evita las condiciones de carrera, las mutaciones del estado fuera de orden y la necesidad de aplicar soluciones alternativas de reordenación.

  • Escala horizontal entre grupos. Cada categoría es una unidad independiente de concurrencia. Añadir consumidores aumenta el rendimiento de forma proporcional al número de categorías activas, sin comprometer las garantías de orden.

  • Desacoplamiento de productor-consumidor. Los productores envían mensajes sin conocimiento de qué consumidor los procesará o cuándo. Los consumidores son escalables y reemplazables de forma independiente.

Problemas y consideraciones

Tenga en cuenta los puntos siguientes al decidir cómo implementar este patrón:

  • Categoría y unidad de escala. Defina en qué propiedad de los mensajes entrantes se puede escalar horizontalmente. La clave de categoría define la unidad de paralelismo: cada valor de clave distinto se convierte en un grupo procesable de forma independiente. En el escenario de seguimiento de pedidos, esta propiedad es el identificador de pedido. Elegir una clave demasiado gruesa (por ejemplo, un identificador de cliente único para todos los pedidos) limita el paralelismo, mientras que elegir una clave demasiado fina no proporciona una ventaja significativa de ordenación.

  • Límites de rendimiento. Evalúe el rendimiento del mensaje de destino. Dado que este patrón aplica el procesamiento secuencial dentro de cada categoría, el rendimiento por categoría está limitado por el tiempo para procesar un solo mensaje. Optimice el tiempo de procesamiento por mensaje, por ejemplo, usando E/S asíncrona o agrupando en lotes las escrituras posteriores, ya que ese tiempo determina directamente el rendimiento máximo de cada categoría. Si su requisito global de capacidad de procesamiento es muy alto, reconsidere si es necesario un orden FIFO estricto a lo largo de todo el ciclo de vida del mensaje. Entre las alternativas se incluyen la aplicación de un mensaje de inicio y un mensaje final para corchete una secuencia, o la ordenación de mensajes por marca de tiempo dentro de una ventana por lotes y, a continuación, el envío del lote para el procesamiento paralelo.

  • Funcionalidades de servicio. Compruebe si la elección del agente de mensajes admite el procesamiento de mensajes de uno a uno dentro de una cola o categoría de una cola. No todos los servicios de mensajería proporcionan garantías de bloqueo de nivel de sesión o FIFO dentro de una partición. Si el agente no admite de forma nativa esta funcionalidad, el consumidor debe implementar su propia lógica de coordinación, lo que agrega complejidad y riesgos de procesamiento duplicado, mensajes perdidos o ejecución desordenado. La compatibilidad con sesiones también puede restringir la elección del nivel de mensajería o la SKU, lo que afecta al costo.

  • Capacidad de evolución. Planee cómo agregará nuevas categorías de mensajes al sistema. El patrón debe dar cabida al crecimiento en la cardinalidad de categorías sin necesidad de cambios estructurales en los consumidores. Por ejemplo, supongamos que el sistema de libro de contabilidad descrito anteriormente es específico de un cliente. Si necesita incorporar un nuevo cliente, debe poder agregar un conjunto de procesadores de libro de contabilidad que distribuyan el trabajo por identificador de cliente sin rediseñar la topología de cola.

  • Entrega de mensajes desordenados. Los mensajes pueden llegar desordenados debido a la latencia de red variable entre el productor y el agente, antes de que el orden de sesión del agente surta efecto. Considere la posibilidad de usar números de secuencia para comprobar la ordenación dentro de cada categoría. También puede incluir una marca de fin de secuencia en el último mensaje de una transacción para que los consumidores puedan detectar cuándo se completa una secuencia.

  • Control de mensajes dudosos. Un mensaje que produce un error en el procesamiento repetidamente dentro de una sesión bloquea todos los mensajes posteriores de esa sesión porque el patrón aplica un orden secuencial estricto. Diseñe una estrategia para detectar mensajes problemáticos, por ejemplo, realizando un seguimiento del número de intentos de entrega, y muévalos a una cola de mensajes fallidos una vez superado un umbral de reintentos definido, para que los mensajes restantes de la sesión puedan seguir procesándose.

  • Disponibilidad del agente. El agente de mensajes es una dependencia compartida para todas las categorías. Su disponibilidad y durabilidad afectan directamente a las garantías de confiabilidad del patrón. Evalúe las características de resistencia de nivel de agente, como las zonas de disponibilidad y la recuperación ante desastres geográficas en función de los requisitos de disponibilidad y el presupuesto de la carga de trabajo, ya que las configuraciones de mayor durabilidad suelen aumentar el costo.

  • Corrección de la clave del productor. El patrón supone que los productores establecen correctamente la clave de categoría (identificador de sesión) en cada mensaje. Si un productor establece una clave incorrecta, ya sea accidentalmente o debido a un error, el mensaje se enruta a la sesión incorrecta y daña el estado del grupo. Valida que los productores asignen claves de categoría de forma consistente y considera añadir lógica de validación de claves en el consumidor si las consecuencias de un mensaje mal enrutado son graves.

  • Complejidad operativa. La monitorización del procesamiento basado en sesiones supone una sobrecarga operativa adicional a la que implica el consumo estándar de colas. Los operadores necesitan visibilidad de los trabajos pendientes de sesión (el número de sesiones activas y la profundidad de los mensajes que esperan en cada sesión) para identificar las categorías que se están retrasando. Las sesiones con mensajes fallidos requieren un flujo de trabajo de supervisión y corrección independientes para investigar los mensajes con errores, resolver la causa principal y reproducir los mensajes corregidos en la sesión.

  • Contención y latencia de bloqueo de sesión. El bloqueo de sesión añade una sobrecarga de latencia porque cada consumidor debe adquirir un bloqueo exclusivo de una sesión antes de procesar los mensajes. Cuando un consumidor contiene un bloqueo de sesión, ningún otro consumidor puede procesar mensajes de esa sesión, incluso si el consumidor está lento o temporalmente detenido. Si la duración del bloqueo es demasiado corta, la expiración del bloqueo puede provocar el reprocesamiento de mensajes. Si la duración del bloqueo es demasiado larga, un consumidor detenido retrasa la recuperación. Ajuste la duración del bloqueo de sesión en función del tiempo esperado de procesamiento de mensajes e implemente la renovación del bloqueo para operaciones de ejecución más larga.

  • Escalabilidad y coste del lado del consumidor. El paralelismo entre sesiones se traduce en instancias de consumidor simultáneas. En un modelo sin servidor, como Azure Functions, cada sesión activa se asigna a una ejecución simultánea y, en un modelo dedicado, se asigna a una instancia o subproceso. Por tanto, el número de sesiones activas influye directamente en el coste de computación. Planifique los límites de escalado de los consumidores y los controles de concurrencia para equilibrar la capacidad de procesamiento frente al coste.

Cuándo usar este patrón

Use este patrón cuando:

  • Los mensajes llegan en orden y deben procesarse en el mismo orden.
  • Los mensajes se pueden clasificar para que cada categoría se convierta en una unidad de escala independiente para el sistema.

Este patrón podría no ser adecuado cuando:

  • Espera escenarios de rendimiento extremadamente altos (millones de mensajes por minuto), ya que el requisito de FIFO limita el escalado que el sistema puede lograr.

  • No se requiere la ordenación de mensajes. Cuando los mensajes se pueden procesar de forma independiente en cualquier orden, el patrón De consumidores competidores proporciona un escalado horizontal más sencillo sin la sobrecarga de coordinación del bloqueo de sesión.

Diseño de cargas de trabajo

Evalúe el uso de Sequential Convoy en el diseño de una carga de trabajo para cumplir los objetivos y principios descritos en los pilares de Azure Well-Architected Framework. En la tabla siguiente se proporciona una guía sobre cómo este patrón apoya los objetivos de cada pilar.

Fundamento Cómo apoya este patrón los objetivos de los pilares
Las decisiones de diseño de fiabilidad ayudan a que su carga de trabajo sea resiliente a fallos y garantizan que se recupere a un estado de pleno funcionamiento después de que se produzca un fallo. Este patrón usa el orden FIFO basado en sesiones para eliminar las condiciones de carrera, la lógica de procesamiento de mensajes propensa a la contención y otras soluciones alternativas para mensajes mal ordenados que pueden provocar fallos.

- RE:02 Flujos críticos
- RE:07 Trabajos en segundo plano

Si este patrón introduce concesiones dentro de un pilar, considérelas en relación con los objetivos de los otros pilares.

Example

En Azure, puede implementar este patrón mediante Service Bus sesiones de mensajes. Para los consumidores, puede usar Logic Apps con el conector de inspección y bloqueo de Service Bus o Azure Functions con el desencadenador de Service Bus.

Cuando un productor establece la SessionId propiedad en un mensaje, Service Bus agrupa todos los mensajes que comparten el mismo identificador de sesión en una sola sesión lógica. Un consumidor acepta una sesión y recibe un bloqueo exclusivo. Este bloqueo garantiza que solo un consumidor procesa los mensajes de esa sesión en cualquier momento y que los mensajes llegan en orden FIFO. Otros consumidores pueden aceptar y procesar simultáneamente diferentes sesiones, lo que proporciona rendimiento paralelo entre grupos.

En el ejemplo de seguimiento de pedidos, el sistema procesa cada mensaje de libro de contabilidad en el orden en que se recibe y envía cada transacción a otra cola donde la categoría se establece en el identificador de pedido. Una transacción nunca se extiende a varios pedidos en este escenario, por lo que los consumidores procesan cada categoría en paralelo, pero siguiendo un orden FIFO dentro de cada categoría.

El procesador de libros de contabilidad distribuye los mensajes mediante la desagrupación del contenido de cada mensaje en la primera cola:

Diagrama de la arquitectura de ejemplo de Sequential Convoy. Muestra un productor, una cola de registro, un procesador de registro, una cola de transacciones y tres procesadores de órdenes.

El diagrama fluye de izquierda a derecha en cinco fases. En el extremo izquierdo hay una caja etiquetada como «producer». Una flecha apunta desde el productor hacia un recuadro con la etiqueta de cola del libro mayor. Una flecha va de la cola del registro a un recuadro etiquetado como "ledger processor". Una flecha va de la cola del registro a un recuadro etiquetado como "ledger processor". Desde la cola de transacciones, salen tres flechas hacia la derecha, cada una etiquetada con una categoría de sesión. La flecha superior está etiquetada con “transacciones del pedido A” y apunta a un cuadro etiquetado como “procesador de pedidos A”. La flecha central está etiquetada con “transacciones del pedido B” y apunta a un cuadro etiquetado como “procesador de pedidos B”. La flecha inferior está etiquetada con “transacciones del pedido C” y apunta a un cuadro etiquetado como “procesador de pedidos C”. El diagrama ilustra la transición de serie a paralelo: el productor envía todos los mensajes secuencialmente a través de la cola del libro mayor y del procesador del libro mayor, y el procesador del libro mayor establece en cada mensaje el identificador de sesión con el identificador de pedido correspondiente antes de encolarlo en la cola de transacciones. A continuación, la cola de transacciones enruta los mensajes de cada pedido exclusivamente al procesador de pedidos correspondiente, que permite al procesador de pedidos A, al procesador de pedidos B y al procesador de pedidos C consumir sus respectivas sesiones en paralelo y en orden FIFO.

El procesador del libro de contabilidad realiza tres pasos:

  1. Recorre el libro de contabilidad una transacción a la vez.
  2. Establece el identificador de sesión del mensaje para que coincida con el identificador de pedido.
  3. Envía cada transacción de libro de contabilidad a una cola secundaria con el id. de sesión establecido en el id. de pedido.

Los consumidores escuchan la cola secundaria y procesan todos los mensajes con identificadores de orden coincidentes en el orden FIFO. Los consumidores usan el modo de inspección y bloqueo.

La cola del libro mayor es un punto de transición de serie a paralelo: todas las transacciones pasan por ella de forma secuencial antes de distribuirse en un procesamiento paralelo basado en sesiones. Esta fase de serialización es el principal cuello de botella para la escalabilidad, porque condiciona el rendimiento de toda la canalización posterior. Sin embargo, después de que el procesador del libro mayor distribuya los mensajes a la cola secundaria, los consumidores pueden escalar de forma independiente en cada sesión, una por cada identificador de pedido.

Tecnologías auxiliares

  • Sesiones de mensajes de Service Bus: agrupa los mensajes por identificador de sesión y garantiza el procesamiento FIFO dentro de cada sesión. Las sesiones de mensajes son el principal mecanismo de Azure para implementar el patrón de convoy secuencial.

  • Desencadenador de Service Bus de Azure Functions: admite desencadenamiento basado en sesiones que permite a las instancias de función procesar mensajes de una sola sesión cada vez.

  • Conector de Service Bus de Logic Apps: Proporciona un conector de Service Bus con compatibilidad con peek-lock para consumir colas con sesiones habilitadas en el procesamiento basado en flujos de trabajo.

Colaboradores

Microsoft mantiene este artículo. Los siguientes colaboradores escribieron este artículo.

Autor principal:

Para ver los perfiles no públicos de LinkedIn, inicie sesión en LinkedIn.

  • Patrón de consumidores competidores: varios consumidores extraen mensajes de una cola compartida en paralelo, lo que aumenta el rendimiento, pero quita las garantías de ordenación por mensaje. El patrón convoy secuencial aborda la brecha de ordenación que introducen los consumidores competidores. Soluciona esta brecha mediante la creación de particiones de mensajes en sesiones con clave de categoría y procesando cada sesión secuencialmente.

  • Patrón de nivelación de carga basado en colas: una cola actúa como búfer de trabajo entre productores y consumidores para absorber picos de carga y suavizar una carga irregular. El patrón de convoy secuencial se basa en este almacenamiento en búfer mediante la incorporación de particiones basadas en sesiones, de modo que la cola equilibra la carga entre categorías y mantiene el orden FIFO dentro de cada categoría.

  • Patrón de cola de prioridad: los mensajes se enrutan a colas independientes o se asignan prioridad dentro de una cola para que el trabajo de prioridad más alta se procese antes del trabajo de prioridad inferior. Cuando también deba preservarse el orden dentro de un nivel de prioridad, el patrón de convoy secuencial puede combinarse con colas de prioridad para garantizar el procesamiento FIFO dentro de cada sesión identificada por prioridad.

  • Mensaje Peek-Lock (lectura no destructiva): Esta operación recupera y bloquea de forma atómica un mensaje de una cola o una suscripción para su procesamiento.

  • Para la entrega de mensajes correlacionados en Logic Apps mediante sesiones de Service Bus: en esta entrada de blog se describe la compatibilidad de Logic Apps con el patrón Convoy secuencial.