Pub/Sub es un servicio de mensajería asíncrono diseñado para ser altamente fiable y escalable. El servicio se basa en un componente de infraestructura principal de Google en el que muchos productos de Google han confiado durante más de una década. Los productos de Google, como Google Ads, la Búsqueda y Gmail, usan esta infraestructura para enviar más de 500 millones de mensajes por segundo, lo que supone más de 1 TB/s de datos. En este artículo se describen las características de diseño destacadas que permiten a Pub/Sub ofrecer este tipo de escalado de forma fiable.
Evaluar el rendimiento de un servicio de mensajería
Un servicio de mensajería como Pub/Sub se puede evaluar en función de su rendimiento en tres aspectos: escalabilidad, disponibilidad y latencia. Estos tres factores suelen estar en conflicto entre sí, por lo que es necesario hacer concesiones en uno para mejorar los otros dos.
Los términos "escalabilidad", "disponibilidad" y "latencia" pueden hacer referencia a diferentes propiedades de un sistema, por lo que en las siguientes secciones se describe cómo se definen en Pub/Sub.
Escalabilidad
Un servicio escalable debe poder gestionar los aumentos de carga sin que se produzca una degradación notable de la latencia o la disponibilidad. "Carga" puede hacer referencia a varias dimensiones de uso en Pub/Sub:
Número de temas
Número de editores
Número de suscripciones
Número de suscriptores
Número de mensajes
Tamaño de los mensajes
Tasa de mensajes (rendimiento) publicados o consumidos
Tamaño de la cartera de pedidos de una suscripción determinada
Disponibilidad
En un sistema distribuido, los tipos y la gravedad de los problemas pueden variar considerablemente. La disponibilidad de un sistema se mide en función de cómo gestiona los diferentes tipos de problemas, de forma que los usuarios finales no perciban los errores. Los fallos pueden producirse en el hardware (por ejemplo, si las unidades de disco no funcionan o si hay problemas de conectividad de red), en el software y debido a la carga. Los fallos debidos a la carga pueden producirse cuando un aumento repentino del tráfico en el servicio (o en otros componentes de software que se ejecutan en el mismo hardware o en dependencias de software) provoca una escasez de recursos. La disponibilidad también puede verse afectada por errores humanos, como equivocaciones al crear o implementar software o configuraciones.
Latencia
La latencia es una medida basada en el tiempo del rendimiento de un sistema. Por lo general, un servicio quiere minimizar la latencia siempre que sea posible. En Pub/Sub, las dos métricas de latencia más importantes son las siguientes:
Tiempo que se tarda en confirmar la recepción de un mensaje publicado.
Tiempo que se tarda en enviar un mensaje publicado a un suscriptor.
Arquitectura básica de Pub/Sub
En esta sección se explica el diseño de Pub/Sub para mostrar cómo el servicio consigue escalabilidad y baja latencia sin dejar de estar disponible. El sistema se ha diseñado para que sea escalable horizontalmente, de forma que el aumento del número de temas, suscripciones o mensajes se pueda gestionar incrementando el número de instancias de servidores en ejecución.
Los servidores de Pub/Sub se ejecutan en todas las regiones de Google Cloud del mundo. De esta forma, el servicio puede ofrecer un acceso rápido a los datos a nivel mundial y, al mismo tiempo, los usuarios pueden controlar dónde se almacenan los mensajes. Cloud Pub/Sub ofrece acceso global a los datos, ya que los clientes editores y suscriptores no conocen la ubicación de los servidores a los que se conectan ni cómo enrutan los datos esos servicios.
Los mecanismos de balanceo de carga de Pub/Sub dirigen el tráfico de los editores al centro de datos de Google Cloud más cercano donde se permite el almacenamiento de datos, tal como se define en la sección Restricción de ubicación de recursos de la consola de administración de IAM. Esto significa que los editores de varias regiones pueden publicar mensajes en un solo tema con una latencia baja. Cada mensaje se almacena en una sola región. Sin embargo, un tema puede tener mensajes almacenados en muchas regiones. Cuando un cliente suscriptor solicita mensajes publicados en este tema, se conecta al servidor más cercano, que agrega datos de todos los mensajes publicados en el tema para enviarlos al cliente.
Pub/Sub se divide en dos partes principales: el plano de datos, que gestiona el movimiento de mensajes entre editores y suscriptores, y el plano de control, que gestiona la asignación de editores y suscriptores a servidores en el plano de datos. Los servidores del plano de datos se denominan reenviadores, y los del plano de control, routers. Cuando los editores y los suscriptores están conectados a los reenviadores que se les han asignado, no necesitan ninguna información de los routers (siempre que se pueda acceder a esos reenviadores). Por lo tanto, es posible actualizar el plano de control de Pub/Sub sin que afecte a los clientes que ya estén conectados y envíen o reciban mensajes.
Plano de control
El plano de control de Pub/Sub distribuye los clientes a los reenviadores de forma que se proporcione escalabilidad, disponibilidad y baja latencia a todos los clientes. Cualquier reenviador puede atender a los clientes de cualquier tema o suscripción. Cuando un cliente se conecta a Pub/Sub, el router decide a qué centros de datos debe conectarse en función de la distancia de red más corta, que es una medida de la latencia de la conexión entre dos puntos. En cualquier centro de datos, el router intenta distribuir la carga general entre el conjunto de reenviadores disponibles. El router debe equilibrar dos objetivos diferentes al realizar esta asignación: a) la uniformidad de la carga (es decir, lo ideal es que cada reenviador tenga la misma carga) y b) la estabilidad de las asignaciones (es decir, lo ideal es que un cambio en la carga o en el conjunto de reenviadores disponibles cambie el menor número de asignaciones posibles). El router usa una variante del hash coherente desarrollada por Google Research para conseguir un equilibrio ajustable entre la coherencia y la uniformidad. El router proporciona al cliente una lista ordenada de reenviadores a los que puede conectarse. Esta lista ordenada puede cambiar en función de la disponibilidad del reenviador y de la forma de la carga del cliente.
Un cliente toma esta lista de reenviadores y se conecta a uno o varios de ellos. El cliente prefiere conectarse a los reenviadores más recomendados por el router, pero también tiene en cuenta los errores que se hayan producido. Por ejemplo, puede decidir probar reenviadores de otro centro de datos si se han producido varios errores al intentar conectarse a los más cercanos. Para abstraer a los clientes de Pub/Sub de estos detalles de implementación, hay un proxy de servicio entre los clientes y los reenviadores que realiza esta optimización de la conexión en nombre de los clientes.
Plano de datos: el ciclo de vida de un mensaje
El plano de datos recibe mensajes de los editores y los envía a los clientes. Quizá la mejor forma de entender el plano de datos de Pub/Sub es analizar el ciclo de vida de un mensaje, desde el momento en que el servicio lo recibe hasta que deja de estar presente en él. Vamos a repasar los pasos para procesar un mensaje. A efectos de esta sección, damos por hecho que el tema en el que se publica el mensaje tiene al menos una suscripción asociada. Por lo general, un mensaje sigue estos pasos:
Un editor envía un mensaje.
El mensaje se escribe en el almacenamiento.
Pub/Sub envía una confirmación al editor de que ha recibido el mensaje y garantiza su entrega a todas las suscripciones asociadas.
Al mismo tiempo que escribe el mensaje en el almacenamiento, Pub/Sub lo envía a los suscriptores.
Los suscriptores envían una confirmación a Pub/Sub para indicar que han procesado el mensaje.
Una vez que al menos un suscriptor de cada suscripción ha confirmado la recepción del mensaje, Pub/Sub lo elimina del almacenamiento.
En primer lugar, un editor envía un mensaje sobre un tema a Pub/Sub. La capa proxy la cifra y la envía a un reenviador de publicación, que es un reenviador al que está conectado el editor. Para asegurar la entrega, el mensaje se escribe inmediatamente en el almacenamiento. El reenviador escribe inicialmente el mensaje en N clústeres (donde N es un número impar) y considera que el mensaje se ha conservado cuando se ha escrito en al menos ⌈N/2⌉ clústeres. Una vez que se ha conservado un mensaje, el reenviador de publicación confirma al editor que ha recibido el mensaje. En ese momento, Pub/Sub garantiza que el mensaje se entregará a todas las suscripciones asociadas.
En cada clúster, el mensaje se escribe en M discos independientes (donde M es un número impar), por lo que los datos deben estar en ⌈M/2⌉ discos para que se consideren persistentes en ese clúster. En total, cualquier mensaje publicado se escribirá en al menos ⌈M/2⌉ discos independientes de ⌈N/2⌉ clústeres antes de considerarse persistente y, finalmente, se replicará en N*M discos.
El reenviador de publicación tiene una lista de todas las suscripciones asociadas a un tema. Es responsable de conservar tanto los mensajes publicados como los metadatos que describen qué mensajes ha confirmado cada suscripción. El conjunto de mensajes que recibe y almacena un reenviador de publicación para un tema concreto, junto con el seguimiento de los mensajes confirmados, se denomina "fuente de mensajes de publicación". En función de los requisitos de rendimiento del tema, un solo editor puede enviar sus mensajes a varios reenviadores de publicación y almacenar mensajes en varias fuentes de mensajes de publicación. Es posible que diferentes editores del mismo tema envíen mensajes a diferentes reenviadores de publicación. Cada mensaje se envía a un único reenviador de publicación. Pub/Sub ajusta dinámicamente el número de reenviadores de publicación que reciben mensajes de un tema concreto a medida que cambia el rendimiento.
Los suscriptores reciben mensajes conectándose a los reenviadores a los que se han suscrito, que son los que permiten que los mensajes fluyan de los editores a los suscriptores. En el caso de un suscriptor de extracción, "conectarse" significa enviar una solicitud de extracción. En el caso de un suscriptor de inserción, "conectarse" significa que el endpoint de inserción está registrado en Pub/Sub. Una vez que se crea una suscripción, se garantiza que todos los mensajes publicados después de ese momento se entregarán a esa suscripción, lo que llamamos garantía de punto de sincronización.
Cada reenviador suscriptor debe solicitar mensajes de los reenviadores de publicación que tengan fuentes de mensajes de publicación para el tema. Al igual que los editores, los suscriptores pueden conectarse a más de un reenviador de suscripciones para recibir mensajes. De esta forma, no es necesario que todos los reenviadores suscritos conozcan o reciban mensajes de todas las fuentes de mensajes de publicación de un tema, lo que es una propiedad importante para que Pub/Sub pueda escalarse horizontalmente. En función del rendimiento de los mensajes que se envían a los suscriptores, Pub/Sub ajusta dinámicamente el número de reenviadores de suscripciones a través de los cuales los suscriptores reciben mensajes de un tema concreto a medida que cambia el rendimiento.
Un reenviador suscriptor envía solicitudes a uno o varios reenviadores editores que tienen fuentes de mensajes de publicación para un tema con el fin de pedir los mensajes que necesita. El reenviador de publicación envía los mensajes no confirmados al reenviador de suscripción, que reenvía los mensajes a un suscriptor.
Una vez que un suscriptor procesa un mensaje, envía una confirmación al reenviador al que se ha suscrito. El reenviador suscriptor reenvía esta confirmación al reenviador editor, que la almacena en la fuente del mensaje de publicación. Una vez que todas las suscripciones de un tema han confirmado la recepción de un mensaje, este se elimina de forma asíncrona de la fuente de mensajes de publicación y del almacenamiento.
Pueden fluir diferentes mensajes de un mismo tema y suscripción a través de muchos editores, suscriptores, reenviadores de publicación y reenviadores de suscripción. Los editores pueden publicar contenido en varios reenviadores simultáneamente y los suscriptores pueden conectarse a varios reenviadores de suscripción para recibir mensajes. Por lo tanto, el flujo de mensajes a través de las conexiones entre editores, suscriptores y reenviadores puede ser complejo. En el siguiente diagrama se muestra cómo podrían fluir los mensajes de un solo tema y una sola suscripción, donde los diferentes colores indican las diferentes rutas que pueden seguir los mensajes de los editores a los suscriptores:
Mantener Pub/Sub en funcionamiento
Para que un sistema distribuido como Pub/Sub pueda seguir funcionando y atender a todos los clientes de forma eficaz, es necesario tener una gran visibilidad y control del sistema. El mantenimiento del servicio es responsabilidad de nuestros ingenieros de fiabilidad de sitios web (SRE). En el caso de Pub/Sub, estos ingenieros se encuentran en varias ubicaciones de todo el mundo para ofrecer cobertura las 24 horas del día.
Entornos
La primera parte del mantenimiento de un sistema como Pub/Sub es poder probar el software antes de que lo usen los clientes. Para que esto sea posible, hay tres entornos de Pub/Sub: prueba, preproducción y producción. Los entornos de prueba y de preproducción no contienen tráfico de clientes, sino solo nuestras pruebas y monitorizaciones continuas, que nos ayudan a detectar cualquier problema con las versiones. Estos entornos reciben nuevas versiones del software antes que el entorno de producción. La diferencia entre las pruebas y el staging es que este último es una réplica exacta de lo que hay (o habrá en breve) en el entorno de producción, incluidas la versión del software y las marcas de la línea de comandos. Es posible que la primera tenga funciones habilitadas en las que los desarrolladores estén trabajando y que tengan previsto lanzar en el futuro.
Lanzamiento
El procedimiento para implementar y probar Pub/Sub se ha diseñado para minimizar el impacto potencial. Veamos los pasos habituales para lanzar una nueva versión de Pub/Sub:
Asegúrate de que todas las pruebas unitarias y de integración se superen.
Crea una nueva versión de todos los servidores.
Despliega los nuevos servidores en los entornos de prueba y de preproducción.
Ejecuta los servidores en el entorno de prueba y de preproducción durante varios días.
Si no hay problemas conocidos, lanza los servidores a la versión canary, un subconjunto del entorno de producción que tiene una pequeña cantidad de tráfico de clientes.
Si no se detectan problemas en la versión canary, despliega los servidores de forma progresiva en más entornos de producción durante varios días hasta que se publiquen en todas partes.
Como Pub/Sub se ha diseñado para que sea resistente a los fallos (por ejemplo, mediante la separación del plano de control y el plano de datos), los lanzamientos de nuevas versiones de los servidores son fluidos para los clientes y no deberían afectar al rendimiento que observan.
Supervisión
La clave para que Pub/Sub siga funcionando es detectar y mitigar automáticamente los problemas antes de que los usuarios finales los vean. Para ello, es necesario monitorizar el sistema de forma exhaustiva. El equipo de Site Reliability Engineering (SRE) mantiene un conjunto de indicadores de nivel de servicio (SLIs), métricas bien definidas que describen el comportamiento del sistema. Las métricas pueden incluir "el tiempo que tarda en completarse una solicitud CreateSubscription" o "la tasa de errores generados por las solicitudes Publish". Estas métricas se miden de varias formas. Algunas de ellas son estrictamente internas para nuestros remitentes y routers. Por ejemplo, miden el tiempo que se tarda en escribir mensajes en el disco.
Todas estas medidas ayudan a definir objetivos de nivel de servicio (SLOs) internos, que son objetivos específicos de los indicadores de nivel de servicio. Por ejemplo, "una solicitud CreateSubscription no debería tardar más de cinco segundos en completarse". Los ingenieros de fiabilidad del sitio reciben alertas por infracciones de los objetivos de nivel de servicio y deben atenderlas en un plazo de cinco minutos.
Un acuerdo de nivel de servicio (SLA) incluye los SLOs que definen nuestras garantías de rendimiento para los usuarios finales y las consecuencias si no los cumplimos. Puedes consultar el acuerdo de nivel de servicio de Pub/Sub.
Mantenemos un conjunto de clientes que publican y se suscriben de forma predecible. Se denominan probers. Hay sondas para el plano de datos y para el plano de control. Cada una de nuestras sondas realiza acciones específicas como lo haría un cliente y mide el tiempo que tardan las operaciones. Por ejemplo, tenemos un verificador que crea una suscripción, publica un mensaje y comprueba cuánto tiempo se ha tardado en crear la suscripción y en recibir el mensaje. Si las sondas determinan que alguna de las métricas medidas no es la esperada, se alerta a los ingenieros de fiabilidad del sitio.
Las métricas de nuestros servidores y probers se resumen en varios paneles de control internos, que son lo primero que consultan los ingenieros de fiabilidad de sitios cuando diagnostican posibles problemas. Estas páginas proporcionan acceso rápido a las estadísticas y los gráficos de todo el servicio. También se pueden desglosar por tema, centro de datos o tarea concreta.
Las métricas que más interesan a los usuarios del servicio se exponen a través de Google Cloud Monitoring.
Controles
Tenemos a nuestra disposición varios controles para ajustar el rendimiento de Pub/Sub. Algunos de estos controles están diseñados para ayudar en caso de interrupciones en centros de datos o máquinas. Podemos aplicar restricciones de enrutamiento a algunos o a todos los temas, que son reglas que especifican conjuntos de clientes que pueden o no conectarse a conjuntos de reenviadores. Usamos restricciones de enrutamiento para desviar el tráfico de tareas de reenvío concretas o de centros de datos completos que no funcionan correctamente.
Otra función que podemos ajustar es el control de flujo. Esta función nos permite maximizar el rendimiento y, al mismo tiempo, evitar la sobrecarga del servicio. El control de flujo es una forma de dar forma al tráfico por la que los picos repentinos e inesperados de carga se pueden suavizar con el tiempo para aumentar la estabilidad del servicio. El control de flujo funciona en todo el sistema o por tema o por suscriptor para limitar el número de mensajes o el número de bytes que se transfieren o están pendientes. En este caso, "pendiente" significa que se ha enviado al cliente, pero aún no se ha confirmado. Tanto el control de flujo como las restricciones de enrutamiento nos permiten optimizar el rendimiento de Pub/Sub sin que los clientes tengan que preocuparse por estos detalles de bajo nivel.
Resumen
Las ventajas de escalabilidad, disponibilidad y latencia de un servicio como Pub/Sub definen la propuesta de valor para los clientes que están pensando en migrar a servicios en la nube gestionados. Cualquier servicio de mensajería asíncrona debe crearse desde cero teniendo en cuenta estas funciones. Con más de una década de experiencia en el envío fiable de grandes cantidades de mensajes rápidamente, el equipo de Pub/Sub ha creado y mantiene un servicio que puede satisfacer las demandas de los productos más fundamentales de Google. Ahora, ese mismo servicio está disponible para todos los clientes externos que quieran enviar sus mensajes a todo el mundo sin tener que preocuparse de si su sistema de mensajería puede gestionar el doble, 10 veces o 100 veces su carga actual.
Glosario
Término | Descripción |
---|---|
clúster | Agrupación lógica de máquinas que suelen compartir el mismo dominio de errores (por ejemplo, una red local compartida y una fuente de alimentación compartida). |
Plano de control | La capa de Pub/Sub que gestiona la asignación de editores y suscriptores a servidores en el plano de datos. |
plano de datos | La capa de Pub/Sub que gestiona el movimiento de mensajes entre editores y suscriptores. |
reenviador | Un servidor del plano de datos. |
acceso a datos globales | Los clientes de editores y suscriptores de Pub/Sub no conocen la ubicación de los datos. El servicio se encarga de todo el enrutamiento y el almacenamiento de acuerdo con la política de restricción de la ubicación. |
escalable horizontalmente | Capacidad de un servicio para gestionar más carga sin problemas aumentando el número de instancias de los componentes del servicio. |
mensaje | Los datos que se mueven a través de Pub/Sub. |
Distancia de red | Una medida de la latencia de la conexión entre dos puntos. |
Prober | Una tarea que actúa como cliente y realiza de forma predecible una o varias acciones en los servidores de Pub/Sub. |
publicar la fuente del mensaje | Conjunto de mensajes recibidos y almacenados por un reenviador de publicación y conjunto de IDs de mensajes confirmados por todas las suscripciones adjuntas. |
Servicio de publicación y suscripción (Pub/Sub) | Un servicio de mensajería en el que los remitentes de los mensajes están desacoplados de los receptores de los mensajes |
editor | Un cliente de Pub/Sub que crea mensajes y los envía (publica) en un tema específico. |
router | Un servidor del plano de control. |
restricciones de ruta | Una lista de reglas que indican qué reenviadores deben o no enviar los routers a los clientes como posibles endpoints a los que conectarse. |
Acuerdo de Nivel de Servicio (ANS) | Una lista de SLOs que definen las garantías de rendimiento de un sistema para los clientes y describen las consecuencias si no se cumplen. |
Indicador de nivel de servicio (SLI) | Una métrica bien definida que describe el comportamiento del sistema. |
Objetivo de nivel de servicio (SLO) | Un objetivo específico de un indicador de nivel de servicio. |
suscriptor | Un cliente de Pub/Sub que recibe mensajes en una suscripción específica. |
suscripción | Una entidad con nombre que representa el interés en recibir todos los mensajes sobre un tema concreto. |
Garantía de punto de sincronización | Hora en la que se crea una suscripción. Todos los mensajes publicados posteriormente se enviarán a los suscriptores. |
tema | Entidad con nombre que representa un feed de mensajes. |