Patrón de comprobante

Azure Event Grid
Azure Blob Storage

Divida un mensaje grande en un comprobante y una carga. Envíe el comprobante a la plataforma de mensajería y almacene la carga en un servicio externo. Este patrón permite el procesamiento de mensajes de gran tamaño, a la vez que protege el bus de mensajes y el cliente para que no se sobrecarguen o se ralenticen. Este patrón también ayuda a reducir los costos, ya que el almacenamiento es normalmente más barato que las unidades de recursos utilizadas por la plataforma de mensajería.

Este patrón también se conoce como mensajería basada en referencias y originalmente fue descrito en el libro Patrones de integración empresarial de Gregor Hohpe y Bobby Woolf.

Contexto y problema

Una arquitectura basada en mensajería en algún momento debe ser capaz de enviar, recibir y manipular mensajes grandes. Estos mensajes pueden contener cualquier cosa, incluidas imágenes (por ejemplo, exámenes de resonancia magnética), archivos de sonido (por ejemplo, llamadas de un centro de llamadas), documentos de texto o cualquier tipo de datos binarios de tamaño arbitrario.

No se recomienda el envío de mensajes de gran tamaño directamente al bus de mensajes, ya que requieren el consumo de más recursos y ancho de banda. Los mensajes grandes también pueden ralentizar toda la solución, ya que las plataformas de mensajería suelen estar optimizadas para controlar grandes cantidades de mensajes pequeños. Además, la mayoría de las plataformas de mensajería tienen límites en el tamaño de los mensajes, por lo que puede que tenga que solucionar estos límites para los mensajes de gran tamaño.

Solución

Almacene toda la carga del mensaje en un servicio externo, como una base de datos. Obtenga la referencia a la carga almacenada y envíe solo esa referencia al bus de mensajes. La referencia actúa como los comprobantes que se usan para recuperar una maleta de equipaje; de ahí el nombre del patrón. Los clientes interesados en procesar ese mensaje específico pueden utilizar la referencia obtenida para recuperar la carga, si es necesario.

Diagrama del patrón de comprobante.

  1. Enviar mensaje
  2. Almacenar el mensaje en el almacén de datos
  3. Poner en cola la referencia del mensaje
  4. Leer la referencia del mensaje
  5. Recuperar el mensaje
  6. Procesar el mensaje

Problemas y consideraciones

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

  • Considere la posibilidad de eliminar los datos del mensaje después de consumirlos, si no necesita archivar los mensajes. Aunque el almacenamiento de blobs es relativamente barato, supone un costo significativo a largo plazo, especialmente si hay muchos datos. La eliminación del mensaje se puede realizar sincrónicamente por parte de la aplicación que recibe y procesa el mensaje o de forma asincrónica en un proceso dedicado independiente. El enfoque asincrónico elimina los datos antiguos sin afectar al rendimiento y al procesamiento de mensajes de la aplicación receptora.

  • El almacenamiento y recuperación del mensaje provoca una sobrecarga y una latencia adicionales. Puede que desee implementar una lógica en la aplicación de envío para usar este patrón solo cuando el tamaño del mensaje supera el límite de datos del bus de mensajes. El patrón se omitirá para los mensajes más pequeños. Este enfoque daría como resultado un patrón condicional de comprobante.

Cuándo usar este patrón

Este patrón se puede usar siempre que un mensaje no se ajuste a los límites de mensajes admitidos de la tecnología de bus de mensajes elegida. Por ejemplo, Service Bus actualmente tiene un límite de 100 MB (nivel Premium), mientras que Event Grid admite hasta 1 MB de mensajes.

También se puede usar el patrón si solo deben tener acceso a la carga los servicios que están autorizados para verla. Al descargar la carga en un recurso externo, se pueden aplicar reglas de autenticación y autorización más estrictas para asegurarse de que se aplica la seguridad cuando se almacenan datos confidenciales en la carga.

Diseño de cargas de trabajo

El arquitecto debe evaluar cómo se puede usar el patrón de comprobación de notificaciones en el diseño de su carga de trabajo para abordar los objetivos y principios tratados en los pilares del Marco de la Well-Architected de Azure. Por ejemplo:

Fundamento Cómo apoya este patrón los objetivos de los pilares
Las decisiones de diseño de la fiabilidad ayudan a que la carga de trabajo sea resistente a los errores y a garantizar que se recupere a un estado de pleno funcionamiento después de que se produzca un error. Los buses de mensajes no ofrecen la misma fiabilidad y recuperación ante desastres que suelen tener los almacenes de datos dedicados, por lo que separar los datos del mensaje puede proporcionar más fiabilidad a los datos subyacentes. Esta separación también permite un enfoque de recuperación de la cola de mensajes tras un desastre.

- RE:03 Análisis del modo de error
- RE:09 Recuperación ante desastres
Las decisiones de diseño de seguridad ayudan a garantizar la confidencialidad, integridad y disponibilidad de los datos y sistemas de su carga de trabajo. Este patrón permite mantener los datos confidenciales fuera de los cuerpos de los mensajes, gestionándolos en un almacén de datos seguro. Esta configuración le permite establecer una autorización más estricta para admitir el acceso a los datos confidenciales desde los servicios que se espera que utilicen los datos, pero elimina la visibilidad de los servicios auxiliares, como las soluciones de supervisión de colas.

- SE:03 Clasificación de datos
- SE:04 Segmentación
La optimización de costos se centra en mantener y mejorar el retorno de la inversión de la carga de trabajo. Los sistemas de mensajería suelen imponer límites al tamaño de los mensajes y el aumento de los límites de tamaño suele ser una característica adicional. Reducir el tamaño de los cuerpos de los mensajes puede permitirle utilizar una solución de mensajería más barata.

- CO:07 Costos de componentes
- CO:09 Costos de flujo
La eficiencia del rendimiento ayuda a que la carga de trabajo satisfaga eficazmente las demandas mediante optimizaciones en el escalado, los datos y el código. Este patrón mejora la eficiencia y el rendimiento de los editores de mensajes, los suscriptores y el propio bus de mensajes cuando el sistema maneja grandes cargas de datos. Funciona disminuyendo el tamaño de los mensajes y garantizando que los consumidores recuperen los datos de la carga útil solo si es necesario y en el momento oportuno.

- PE:05 Escapado y particiones
- PE:12 Optimización continua del rendimiento

Al igual que con cualquier decisión de diseño, hay que tener en cuenta las ventajas y desventajas con respecto a los objetivos de los otros pilares que podrían introducirse con este patrón.

Ejemplos

En Azure, este patrón se puede implementar de varias maneras y con tecnologías diferentes, pero hay dos categorías principales. En ambos casos, el receptor tiene la responsabilidad de leer el comprobante de la notificación y utilizarlo para recuperar la carga.

  • Generación automática de comprobantes de notificaciones. Este enfoque usa Azure Event Grid para generar automáticamente el comprobante de la notificación e insertarlo en el bus de mensajes.

  • Generación manual de comprobantes. En este enfoque, el remitente es responsable de administrar la carga. El remitente almacena la carga mediante el servicio adecuado, obtiene o genera el comprobante y envía este al bus de mensajes.

Event Grid es un servicio de enrutamiento de eventos e intenta entregar los eventos dentro de una cantidad de tiempo configurable de hasta 24 horas. Después de ese tiempo, los eventos se descartan o se insertan en una cola de mensajes fallidos. Si necesita archivar las cargas de los eventos o reproducir el flujo de eventos, puede agregar una suscripción de Event Grid a Event Hubs o Queue Storage, donde se puedan conservar los mensajes durante períodos más largos y se admita el archivado de los mensajes. Para más información acerca de cómo optimizar la entrega de mensajes y los reintentos de Event Grid y la configuración de los mensajes fallidos, consulte Mensajes fallidos y directivas de reintento.

Generación automática de comprobantes con Blob Storage y Event Grid

En este enfoque, el remitente coloca la carga del mensaje en un contenedor de Azure Blob Storage designado. Event Grid genera automáticamente una etiqueta o referencia y la envía a un bus de mensajes compatible, como las colas de Azure Storage. El receptor puede sondear la cola, obtener el mensaje y, a continuación, utilizar los datos de referencia almacenados para descargar la carga directamente desde Blob Storage.

El mismo mensaje de Event Grid puede ser consumido directamente por Azure Functions, sin necesidad de pasar por un bus de mensajes. Este enfoque aprovecha al máximo la naturaleza sin servidor de Event Grid y Functions.

Puede encontrar código de ejemplo para este enfoque aquí.

Event Grid con Event Hubs

De forma similar al ejemplo anterior, Event Grid genera automáticamente un mensaje cuando se escribe una carga en un contenedor de blobs de Azure. Pero en este ejemplo, el bus de mensajes se implementa mediante Event Hubs. Un cliente puede registrarse para recibir la secuencia de mensajes a medida que se escriben en el centro de eventos. El centro de eventos también se puede configurar para archivar los mensajes, por lo que estarán disponibles como un archivo Avro que se puede consultar mediante herramientas como Apache Spark, Apache Drill o cualquiera de las bibliotecas de Avro disponibles.

Puede encontrar código de ejemplo para este enfoque aquí.

Generación de comprobantes con Service Bus

Esta solución aprovecha un complemento específico de Service Bus, ServiceBus.AttachmentPlugin, que facilita la implementación del flujo de trabajo de comprobantes. El complemento convierte cualquier cuerpo de mensaje en un archivo adjunto que se almacena en Azure Blob Storage cuando se envía el mensaje.

using ServiceBus.AttachmentPlugin;
...

// Getting connection information
var serviceBusConnectionString = Environment.GetEnvironmentVariable("SERVICE_BUS_CONNECTION_STRING");
var queueName = Environment.GetEnvironmentVariable("QUEUE_NAME");
var storageConnectionString = Environment.GetEnvironmentVariable("STORAGE_CONNECTION_STRING");

// Creating config for sending message
var config = new AzureStorageAttachmentConfiguration(storageConnectionString);

// Creating and registering the sender using Service Bus Connection String and Queue Name
var sender = new MessageSender(serviceBusConnectionString, queueName);
sender.RegisterAzureStorageAttachmentPlugin(config);

// Create payload
var payload = new { data = "random data string for testing" };
var serialized = JsonConvert.SerializeObject(payload);
var payloadAsBytes = Encoding.UTF8.GetBytes(serialized);
var message = new Message(payloadAsBytes);

// Send the message
await sender.SendAsync(message);

El mensaje de Service Bus actúa como una cola de notificación, a la que un cliente puede suscribirse. Cuando el consumidor recibe el mensaje, el complemento hace posible leer directamente los datos del mensaje desde Blob Storage. A continuación, puede elegir cómo procesar el mensaje aún más. Una ventaja de este enfoque es que abstrae el flujo de trabajo de comprobantes del remitente y del receptor.

Puede encontrar código de ejemplo para este enfoque aquí.

Generación manual de comprobantes con Kafka

En este ejemplo, un cliente de Kafka escribe la carga en Azure Blob Storage. Después, envía un mensaje de notificación mediante Event Hubs habilitado para Kafka. El consumidor recibe el mensaje y puede acceder a la carga desde Blob Storage. En este ejemplo se muestra cómo se puede usar un protocolo de mensajería diferente para implementar el patrón de comprobante en Azure. Por ejemplo, puede que necesite admitir clientes de Kafka existentes.

Puede encontrar código de ejemplo para este enfoque aquí.

Pasos siguientes