En este artículo se describen los diferentes tipos de mensajes y las entidades que participan en una infraestructura de mensajería. En función de los requisitos de cada tipo de mensaje, el artículo recomienda algún servicio de mensajería de Azure. Las opciones incluyen Mensajería de Azure Service Bus, Azure Event Grid y Azure Event Hubs. Para ver la comparación de productos, consulte Comparación de los servicios de mensajería.
En el nivel de arquitectura, un mensaje es un datagrama creado por una entidad (productor) para distribuir información de forma que otras entidades (consumidores) puedan tenerlo en cuenta y actúen en consecuencia. El productor y el consumidor pueden comunicarse directa u opcionalmente a través de una entidad intermediaria (agente de mensajes). Este artículo se centra en la mensajería asincrónica mediante un agente de mensajes.
Podemos clasificar los mensajes en dos categorías principales: Si el productor espera una acción del consumidor, ese mensaje es un comando. Si el mensaje informa al consumidor de que se ha realizado una acción, dicho mensaje es un evento.
Comandos:
El productor envía un comando con la intención de que los consumidores realicen una operación dentro del ámbito de una transacción comercial.
Un comando es un mensaje de alto valor y debe entregarse al menos una vez. Si se pierde un comando, puede producirse un error en toda la transacción comercial. Además, un comando no debe procesarse más de una vez. Si eso sucede, podría producirse una transacción errónea. Un cliente puede recibir pedidos o cargos duplicados.
Los comandos se suelen usar para administrar el flujo de trabajo de una transacción comercial de varios pasos. En función de la lógica de negocios, el productor puede esperar que el consumidor confirme el mensaje e informe de los resultados de la operación. En función de ese resultado, el productor puede elegir el plan de acción adecuado.
Eventos
Un evento es un tipo de mensaje que el productor genera para anunciar datos.
El productor (conocido como publicador en este contexto) no espera que los eventos produzcan ninguna acción.
Los consumidores interesados pueden suscribirse, escuchar eventos y tomar medidas en función de su escenario de consumo. Los eventos pueden tener varios suscriptores o ninguno. Dos suscriptores diferentes pueden reaccionar a un evento con diferentes acciones sin detectar al otro.
El productor y el consumidor están acoplados de forma flexible y se administran de forma independiente. El productor no espera que el consumidor confirme el evento. Un consumidor que ya no esté interesado en los eventos puede cancelar la suscripción, lo que quita al consumidor de la canalización sin que esto afecte al productor ni a la funcionalidad general del sistema.
Existen dos categorías de eventos:
El productor genera eventos para anunciar datos discretos. Un caso de uso común es la notificación de eventos. Por ejemplo, Azure Resource Manager genera eventos cuando crea, modifica o elimina recursos. Un suscriptor de esos eventos podría ser una aplicación lógica que envíe alertas por correo electrónico.
El productor genera eventos relacionados en una secuencia, o flujo de eventos, durante un período. Normalmente, un flujo se consume para la evaluación estadística. La evaluación se puede realizar durante un intervalo de tiempo o cuando llegan los eventos. La telemetría es un caso de uso común; por ejemplo, para la supervisión del estado y la carga de un sistema. Otro caso es la emisión de eventos desde dispositivos IoT.
El patrón Publisher-Subscriber se usa comúnmente para implementar la mensajería de eventos.
Rol y ventajas de un agente de mensajes
Un agente de mensajes intermedio ofrece la funcionalidad de mover los mensajes del productor al consumidor, además de ventajas adicionales.
Desacoplamiento
Un agente de mensajes desacopla al productor del consumidor en la lógica que genera y usa los mensajes, respectivamente. En un flujo de trabajo complejo, el agente puede fomentar el desacoplamiento de las operaciones empresariales y coordinar el flujo de trabajo.
Por ejemplo, una única transacción comercial requiere operaciones distintas que se realizan en una secuencia de lógica de negocios. El productor emite un comando que indica a un consumidor que inicie una operación. El consumidor confirma el mensaje en una cola independiente reservada para alistar las respuestas para el productor. Solo después de recibir la respuesta, el productor envía un nuevo mensaje para iniciar la siguiente operación de la secuencia. Un consumidor diferente procesa ese mensaje y envía un mensaje de finalización a la cola de respuesta. Mediante la mensajería, los servicios coordinan el flujo de trabajo de la transacción entre ellos.
Un agente de mensajes proporciona desacoplamiento temporal. No es necesario que el productor y el consumidor se ejecuten de forma simultánea. Un productor puede enviar un mensaje al agente de mensajes, independientemente de la disponibilidad del consumidor. Por otro lado, al consumidor no lo restringe la disponibilidad del productor.
Por ejemplo, la interfaz de usuario de una aplicación web genera mensajes y usa una cola como agente de mensajes. Cuando el consumidor está listo, puede recuperar los mensajes de la cola y realizar el trabajo. El desacoplamiento temporal ayuda a que la interfaz de usuario siga respondiendo. No se bloquea mientras los mensajes se administren de forma asincrónica.
Algunas operaciones pueden tardar en completarse. Después de emitir un comando, el productor no debería esperar hasta que el consumidor lo complete. Un agente de mensajes ayuda a procesar asincrónicamente los mensajes.
Equilibrio de carga
Los productores pueden publicar un gran número de mensajes que se envían a muchos consumidores. Use un agente de mensajes para distribuir el procesamiento entre servidores y mejorar el rendimiento. Los consumidores pueden ejecutarse en servidores diferentes para distribuir la carga. Los consumidores se pueden agregar de forma dinámica para escalar horizontalmente el sistema cuando sea necesario, o quitarse.
El patrón Competing Consumers explica cómo procesar varios mensajes simultáneamente a fin de optimizar el rendimiento, mejorar la escalabilidad y disponibilidad, y equilibrar la carga de trabajo.
Redistribución de la carga
El volumen de mensajes que genera el productor o un grupo de productores puede variar. En ocasiones, puede haber un gran volumen que cause picos la cantidad de mensajes. En lugar de agregar consumidores para encargarse de este trabajo, un agente de mensajes puede actuar como un búfer, y los consumidores agotarán gradualmente los mensajes a su propio ritmo sin esforzar al sistema.
El artículo Patrón Queue-based Load Leveling ofrece más información.
Mensajería de confianza
Un agente de mensajes ayuda a garantizar que los mensajes no se perderán, incluso si se produce un error de comunicación entre el productor y el consumidor. El productor puede publicar mensajes en el agente de mensajes y el consumidor puede recuperarlos cuando se restablezca la comunicación. El productor no se bloquea a menos que pierda la conexión con el agente de mensajes.
Mensajería resistente
Un agente de mensajes puede ofrecer resistencia a los consumidores del sistema. Si se produce un error en un consumidor durante el procesamiento de un mensaje, otra instancia de dicho consumidor puede procesar ese mensaje. Es posible volver a procesarlo porque el mensaje persiste en el agente.
Opciones de tecnología para un agente de mensajes
Azure proporciona varios servicios de agente de mensajes, cada uno con varias características. Antes de elegir un servicio, determine la intención y los requisitos del mensaje.
Mensajería de Azure Service Bus
Las colas de Mensajería de Azure Service Bus son adecuadas para transferir comandos de los productores a los consumidores. A continuación, se indican algunas consideraciones.
Modelo de extracción
El consumidor de una cola de Service Bus sondea constantemente a Service Bus para comprobar si hay nuevos mensajes disponibles. Los SDK de cliente y el desencadenador de Azure Functions para Service Bus abstraen ese modelo. Cuando está disponible un nuevo mensaje, se invoca la devolución de llamada del consumidor y el mensaje se envía al consumidor.
Entrega garantizada
Service Bus permite que un consumidor inspeccione la cola y bloquee un mensaje de otros consumidores.
Es responsabilidad del consumidor notificar el estado de procesamiento del mensaje. Service Bus quita el mensaje de la cola solo cuando el consumidor lo ha marcado como consumido. Si se produce un error, un bloqueo o se agota el tiempo de espera, Service Bus desbloquea el mensaje para que otros consumidores puedan recuperarlo. De este modo, los mensajes no se pierden durante la transferencia.
Un productor podría enviar el mismo mensaje dos veces por accidente. Por ejemplo, una instancia de productor genera un error después de enviar un mensaje. Otro productor reemplaza a la instancia original y envía el mensaje de nuevo. Las colas de Azure Service Bus proporcionan una funcionalidad de eliminación de duplicados integrada que detecta y quita los mensajes duplicados. Todavía existe la posibilidad de que un mensaje se entregue dos veces. Por ejemplo, si un consumidor produce un error durante el procesamiento, el mensaje se devuelve a la cola y el mismo u otro consumidor lo recuperan. La lógica de procesamiento de mensajes en el consumidor debe ser idempotente, de modo que incluso si el trabajo se repite, el estado del sistema no se modifique.
Orden de los mensajes
Si quiere que los consumidores reciban los mensajes en el orden en el que se envían, las colas de Service Bus usan sesiones para garantizar la entrega ordenada de tipo primero en entrar, primero en salir (FIFO). Una sesión puede tener uno o varios mensajes. Los mensajes se correlacionan con la propiedad SessionId. Los mensajes que forman parte de una sesión nunca expiran. Una sesión se puede bloquear para un consumidor; de este modo, se evita que un consumidor diferente administre los mensajes.
Para más información, consulte Sesiones de mensajes.
Persistencia de los mensajes
Las colas de Service Bus admiten el desacoplamiento temporal. Incluso cuando un consumidor no está disponible o no puede procesar el mensaje, este permanece en la cola.
Puntos de control para las transacciones de larga duración
Las transacciones comerciales se pueden ejecutar durante mucho tiempo. Cada operación de la transacción puede tener varios mensajes. Use los puntos de control para coordinar el flujo de trabajo y proporcionar resistencia en caso de que se produzca un error en una transacción.
Las colas de Service Bus permiten la creación de puntos de control a través de la capacidad del estado de sesión. La información de estado se registra de forma incremental en la cola (SetState) para los mensajes que pertenecen a una sesión. Por ejemplo, un consumidor puede supervisar el progreso al comprobar el estado (GetState) de vez en cuando. Si se produce un error en un consumidor, otro puede usar la información del estado para determinar el último punto de control conocido y reanudar la sesión.
Cola de mensajes fallidos (DLQ)
Las colas de Service Bus tienen una subcola predeterminada, denominada cola de mensajes fallidos (DLQ) para almacenar los mensajes que no se pudieron entregar o procesar. Service Bus o la lógica de procesamiento de mensajes del consumidor pueden agregar mensajes a la cola DLQ. Esta conserva los mensajes hasta que se recuperan de la cola.
Estos son algunos ejemplos en los que un mensaje puede enviarse a la cola DLQ:
Un mensaje dudoso es un mensaje que no se puede administrar porque tiene un formato incorrecto o contiene información inesperada. En las colas de Service Bus, puede detectar los mensajes dudosos al establecer la propiedad MaxDeliveryCount de la cola. Si el número de veces que se recibe el mismo mensaje supera el valor de la propiedad, Service Bus mueve el mensaje a la cola de mensajes fallidos.
Es posible que un mensaje ya no sea relevante si no se procesó en un plazo determinado. Las colas de Service Bus permiten que el productor publique mensajes con un atributo de período de vida. Si este período expira antes de que se reciba el mensaje, este se coloca en la cola de mensajes fallidos.
Examine los mensajes en la cola DLQ para determinar el motivo del error.
Solución híbrida
Service Bus une sistemas en el entorno local y en la nube. Suele ser difícil comunicarse con los sistemas en el entorno local debido a las restricciones del firewall. Tanto el productor como el consumidor (pueden ser en el entorno local o en la nube) pueden usar el punto de conexión de la cola de Service Bus como ubicación de recogida y entrega de los mensajes.
El patrónpuente de mensajería es otra manera de manipular estos escenarios.
Temas y suscripciones
Service Bus admite el patrón Publisher-Subscriber a través de los temas y suscripciones de Service Bus.
Esta característica permite que el productor difunda mensajes a varios consumidores. Cuando un tema recibe un mensaje, se reenvía a todos los consumidores suscritos. Una suscripción también puede tener criterios de filtro para permitir que el consumidor obtenga un subconjunto de mensajes. Cada consumidor recupera los mensajes de una suscripción de forma similar a como lo hace una cola.
Para obtener más información, consulte Temas de Azure Service Bus.
Azure Event Grid
Se recomienda Azure Event Grid para los eventos discretos. Event Grid usa el patrón Publisher-Subscriber. Cuando los orígenes de eventos desencadenan eventos, estos se publican en los temas de Event Grid. Los consumidores de esos eventos crean suscripciones a Event Grid al especificar los tipos de eventos y controladores de eventos que procesarán a los eventos. Si no hay ningún suscriptor, los eventos se descartan. Cada evento puede tener varias suscripciones.
Modelo de inserción
Event Grid propaga los mensajes a los suscriptores con un modelo de inserción. Supongamos que tiene una suscripción a Event Grid con un webhook. Cuando llega un nuevo evento, Event Grid envía el evento al punto de conexión del webhook.
Integración con Azure
Elija Event Grid si quiere recibir notificaciones sobre los recursos de Azure. Muchos servicios de Azure actúan como orígenes de eventos con temas de Event Grid integrados. Event Grid también admite varios servicios de Azure que se pueden configurar como controladores de eventos. Suscribirse a esos temas para enrutar eventos a los controladores de eventos de su elección es sencillo. Por ejemplo, puede usar Event Grid para invocar una instancia de Azure Functions cuando se cree o elimine un almacenamiento de blob.
Temas personalizados
Si quiere enviar eventos desde su aplicación o un servicio de Azure que no esté integrado con Event Grid, cree temas de Event Grid personalizados.
Por ejemplo, para ver el progreso de una transacción comercial completa, querrá que los servicios participantes generen eventos a medida que procesen sus operaciones comerciales individuales. Una aplicación web muestra dichos eventos. Una forma de realizar esta tarea consiste en crear un tema personalizado y agregar una suscripción con la aplicación web registrada a través de un webhook HTTP. A medida que los servicios de negocio envíen eventos al tema personalizado, Event Grid los insertará en la aplicación web.
Eventos filtrados
Puede especificar filtros en una suscripción para indicar a Event Grid que enrute solo un subconjunto de los eventos a un controlador de eventos específico. Especifique los filtros en el esquema de suscripción. Todos los eventos que se hayan enviado al tema con valores que coincidan con el filtro se reenviarán automáticamente a esa suscripción.
Por ejemplo, se carga contenido de varios formatos a Blob Storage. Cada vez que se agrega un archivo, se genera un evento y se publica en Event Grid. La suscripción de eventos podría tener un filtro que solo envíe eventos para las imágenes, para que un controlador de eventos pueda generar las miniaturas.
Para más información sobre el filtrado, consulte Filtrado de eventos para Event Grid.
Alto rendimiento
Event Grid puede enrutar 10 millones de eventos por segundo por región. Los 100 000 primeras operaciones al mes son gratis. En cuanto a las consideraciones de costos, consulte ¿Cuánto cuesta Event Grid?
Entrega resistente
Aunque la entrega correcta de los eventos no es tan importante como los comandos, es posible que quiera alguna garantía según el tipo de evento. Event Grid ofrece características que puede habilitar y personalizar, como directivas de reintentos, tiempo de expiración y colas de mensajes fallidos. Para más información, vea Entrega y reintento de entrega de mensajes de Event Grid.
El proceso de reintento de Event Grid puede ayudar a la resistencia, pero no es a prueba de errores. En el proceso de reintento, Event Grid podría enviar el mensaje más de una vez, omitirlo o retrasar algunos reintentos si el punto de conexión no responde durante mucho tiempo. Para más información, consulte Programación de reintentos.
Puede conservar los eventos que no se hayan entregado a una cuenta de almacenamiento de blobs al habilitar la cola de mensajes fallidos. Hay un retraso al entregar el mensaje al punto de conexión del almacenamiento de blobs y, si ese punto de conexión no responde, Event Grid descartará el evento. Para más información, consulte Establecimiento de una ubicación para los eventos fallidos y de una directiva de reintentos.
Azure Event Hubs
Cuando se trabaja con un flujo de eventos, Azure Event Hubs es el agente de mensajes recomendado. Básicamente, es un búfer de gran tamaño capaz de recibir grandes volúmenes de datos con baja latencia. Los datos recibidos se pueden leer rápidamente mediante operaciones simultáneas. Puede transformar los datos recibidos con cualquier proveedor de análisis en tiempo real. Event Hubs también proporciona la capacidad de almacenar los eventos en una cuenta de almacenamiento.
Ingesta rápida
Event Hubs es capaz de ingerir millones de eventos por segundo. Los eventos solo se anexan al flujo y se ordenan por hora.
Modelo de extracción
Como Event Grid, Event Hubs también ofrece capacidades para publicador y suscriptor. Una diferencia fundamental entre Event Grid y Event Hubs es la forma en que los datos del evento se ponen a disposición de los suscriptores. Event Grid envía los datos ingeridos a los suscriptores, mientras que Event Hubs hace que los datos estén disponibles según un modelo de extracción. A medida que se reciben eventos, Event Hubs los anexa al flujo. Cada suscriptor administra su cursor y puede avanzar y retroceder en el flujo, seleccionar un desplazamiento de tiempo y reproducir una secuencia a su propio ritmo.
Los procesadores del flujo son suscriptores que extraen datos de Event Hubs con fines de transformación y análisis estadístico. Use Azure Stream Analytics y Apache Spark para el procesamiento complejo, como la agregación en intervalos de tiempo o la detección de anomalías.
Si quiere tomar medidas con cada evento por partición, puede extraer los datos mediante el host de procesamiento de eventos o mediante un conector integrado, como Azure Logic Apps, para proporcionar la lógica de transformación. Otra opción es usar Azure Functions.
Creación de particiones
Una partición es una parte del flujo de eventos. Los eventos se dividen mediante una clave de partición. Por ejemplo, varios dispositivos IoT que envían datos del dispositivo a un centro de eventos. La clave de partición es el identificador del dispositivo. A medida que los eventos se ingieren, Event Hubs los mueve a particiones independientes. En cada partición, todos los eventos se ordenan por hora.
Un consumidor es una instancia de código que procesa los datos del evento. Event Hubs sigue un patrón de consumidores particionados. Cada consumidor lee únicamente una partición específica. Tener varias particiones ocasiona un procesamiento más rápido, ya que varios consumidores pueden leer el flujo simultáneamente.
Las instancias del mismo consumidor componen un único grupo de consumidores. Varios grupos de consumidores pueden leer el mismo flujo con intenciones diferentes. Supongamos que un flujo de eventos contiene datos de un sensor de temperatura. Un grupo de consumidores puede leer el flujo para detectar anomalías, como un pico de temperatura. Otro, puede leer el mismo flujo para calcular una temperatura media móvil en un intervalo de tiempo.
Event Hubs es compatible con el patrón Publisher-Subscriber, ya que permite varios grupos de consumidores. Cada grupo de consumidores es un suscriptor.
Para más información sobre las particiones de Event Hubs, consulte Particiones.
Captura de Event Hubs
La característica Capture permite almacenar el flujo de eventos en una instancia de Azure Blob Storage o Data Lake Storage. Esta forma de almacenar eventos es de confianza, porque incluso si la cuenta de almacenamiento no está disponible, Capture mantiene los datos durante un plazo y, después, los escribe en el almacenamiento cuando esté disponible.
Los servicios de almacenamiento también pueden ofrecer características adicionales para analizar los eventos. Por ejemplo, si aprovecha los niveles de acceso de una cuenta de Blob Storage, puede almacenar los eventos en un nivel de acceso frecuente para los datos que necesiten un acceso frecuente. Puede usar esos datos para las visualizaciones. También puede almacenar datos en el nivel de archivo y recuperarlos ocasionalmente con fines de auditorías.
Capture almacena todos los eventos que ingiere Event Hubs y resulta útil para el procesamiento por lotes. Puede generar informes sobre los datos mediante una función MapReduce. Los datos capturados también pueden servir como fuente fiable. Si se han perdido ciertos datos al agregar otros, puede consultar los datos capturados.
Para obtener información sobre esta característica, consulte Captura de eventos a través de Azure Event Hubs en Azure Blob Storage o Azure Data Lake Storage.
Compatibilidad con clientes de Apache Kafka
Event Hubs proporciona un punto de conexión para los clientes de Apache Kafka. Los clientes existentes pueden actualizar su configuración para que apunte al punto de conexión y pueden comenzar a enviar eventos a Event Hubs. No es necesario hacer ningún cambio de código.
Para obtener más información, consulte Event Hubs para Apache Kafka.
Escenarios cruzados
En algunos casos, es mejor combinar dos servicios de mensajería.
La combinación de servicios puede aumentar la eficacia del sistema de mensajería. Por ejemplo, en la transacción comercial, se usan las colas de Azure Service Bus para controlar los mensajes. Las colas que más bien están inactivas y reciben mensajes ocasionalmente son ineficaces, porque el consumidor sondea constantemente la cola en busca de nuevos mensajes. Puede configurar una suscripción de Event Grid con una instancia de Azure Functions como controlador de eventos. Cada vez que la cola reciba un mensaje y no haya consumidores escuchando, Event Grid enviará una notificación que invocará a la instancia de Azure Functions que purga la cola.
Para obtener más información sobre cómo conectar Service Bus a Event Grid, consulte Introducción a la integración de Azure Service Bus en Event Grid.
La arquitectura de referencia que se describe en Integración empresarial con colas de mensajes y eventos muestra una implementación de la integración de Service Bus en Event Grid.
Veamos otro ejemplo: Event Grid recibe un conjunto de eventos en el que algunos de los eventos requieren un flujo de trabajo, mientras que otros son para notificaciones. Los metadatos del mensaje indican el tipo de evento. Una manera de diferenciarlos es comprobar los metadatos mediante la característica de filtrado de la suscripción de eventos. Si el evento requiere un flujo de trabajo, Event Grid lo envía a la cola de Azure Service Bus. Los receptores de esa cola pueden tomar las medidas necesarias. Los eventos de notificación se envían a Logic Apps para enviar alertas por correo electrónico.
Patrones relacionados
Tenga en cuenta los siguientes patrones al implementar la mensajería asincrónica:
- Patrón de consumidores de la competencia. Es posible que varios consumidores deban competir para leer los mensajes de una cola. Este patrón explica cómo procesar varios mensajes simultáneamente a fin de optimizar el rendimiento, mejorar la escalabilidad y disponibilidad, y equilibrar la carga de trabajo.
- Patrón Priority Queue. En los casos en los que la lógica de negocios requiere que algunos mensajes se procesen antes que otros, este patrón describe el modo en que un consumidor puede recibir y procesar con mayor rapidez los mensajes del publicador con una prioridad más alta que los que tienen una prioridad más baja.
- Patrón Queue-Based Load Leveling. Este patrón usa un agente de mensajes que funciona como búfer entre un productor y un consumidor para minimizar el impacto en la disponibilidad y capacidad de respuesta de las cargas pesadas intermitentes para ambas entidades.
- Patrón Retry. Es posible que un productor o consumidor no pueda conectarse a una cola, pero los motivos de este error pueden ser temporales y solucionarse rápidamente. En este patrón se describe cómo controlar esta situación para proporcionar resistencia a una aplicación.
- Patrón Scheduler Agent Supervisor. La mensajería suele usarse como parte de una implementación de flujo de trabajo. Este patrón muestra el modo en que la mensajería puede coordinar un conjunto de acciones de un conjunto distribuido de servicios y otros recursos remotos, y cómo puede hacer que un sistema se recupere y reintente las acciones que producen un error.
- Patrón Choreography. Este patrón muestra cómo los servicios pueden usar la mensajería para controlar el flujo de trabajo de una transacción comercial.
- Patrón Claim-Check. Este patrón muestra cómo dividir un mensaje grande en un comprobante y una carga.
Recursos de la comunidad
Entrada de blog de Jonathon Oliver: Idempotencia
Entrada de blog de Martin Fowler: ¿Qué significa "controlado por eventos"?