Descripción general de la arquitectura de Pub/Sub

Pub/Sub es un servicio de mensajería asíncrona diseñado para ser altamente confiable y escalable. El servicio se compila en un componente central de la infraestructura de Google del que dependieron muchos productos de Google durante más de una década. Los productos de Google, incluidos Ads, Búsqueda y Gmail, usan esta infraestructura para enviar más de 500 millones de mensajes por segundo, lo que suma más de 1 TB de datos por segundo. En este artículo, se describen las principales características de diseño que permiten a Pub/Sub proporcionar este tipo de escalamiento de manera confiable.

Evalúa el rendimiento de un servicio de mensajería

Un servicio de mensajería como Pub/Sub puede evaluarse de acuerdo con su rendimiento en tres aspectos: escalabilidad, disponibilidad y latencia. Estos tres factores a menudo están en desacuerdo entre sí, lo que requiere que se hagan concesiones en uno para mejorar los otros dos.

Los términos “escalabilidad”, “disponibilidad” y “latencia” pueden referirse a diferentes propiedades de un sistema, por lo que, en las secciones que se incluyen a continuación, se describe cómo se definen en Pub/Sub.

Escalabilidad

Un servicio escalable debe ser capaz de manejar aumentos en la carga sin que se genere un deterioro notable de la latencia o la disponibilidad. “Carga” puede referirse a varias dimensiones de uso en Pub/Sub:

  • Cantidad de temas

  • Cantidad de publicadores

  • Cantidad de suscripciones

  • Cantidad de suscriptores

  • Cantidad de mensajes

  • Tamaño de los mensajes

  • Tasa de mensajes (capacidad de procesamiento) publicados o consumidos

  • Tamaño del total de los trabajos pendientes en una suscripción determinada

Disponibilidad

En un sistema distribuido, los tipos y la gravedad de los problemas pueden variar mucho. La disponibilidad de un sistema se mide en función de qué tan bien maneja los diferentes tipos de problemas y realiza conmutaciones por error de un modo que sea imperceptible por parte de los usuarios finales. Pueden producirse fallas en el hardware (p. ej., unidades de disco que no funcionan o problemas de conectividad de red), en el software y debido a la carga. Las fallas debido a la carga pueden ocurrir cuando un aumento repentino del tráfico en el servicio (o en otros componentes del software que se ejecutan en el mismo hardware o en dependencias del software) da como resultado la escasez de recursos. Es posible que la disponibilidad también disminuya debido a un error humano, que puede consistir en errores durante la compilación o implementación de opciones de configuración o software.

Latencia

La latencia es una medida del rendimiento de un sistema basada en el tiempo. Por lo general, se busca minimizar la latencia de un servicio siempre que sea posible. Para Pub/Sub, las dos métricas de latencia más importantes son las siguientes:

  1. La cantidad de tiempo que lleva reconocer un mensaje publicado

  2. La cantidad de tiempo que lleva entregar 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 alcanza su escalabilidad y baja latencia a la vez que conserva la disponibilidad. El sistema está diseñado para que sea escalable de forma horizontal, de modo que se pueda manejar un aumento en la cantidad de temas, suscripciones o mensajes mediante el aumento de la cantidad de instancias de servidores en ejecución.

Los servidores de Pub/Sub se ejecutan en todas las regiones de Google Cloud de todo el mundo. Esto permite que el servicio ofrezca acceso rápido y global a los datos, a la vez que les brinda a los usuarios control sobre dónde se almacenan los mensajes. Cloud Pub/Sub ofrece acceso global a los datos, ya que los clientes publicadores y suscriptores no conocen la ubicación de los servidores a los que se conectan ni saben cómo esos servicios enrutan los datos.

Los mecanismos de balanceo de cargas de Pub/Sub dirigen el tráfico del publicador al centro de datos de Google Cloud más cercano en el que se permite el almacenamiento de datos, como se define en la sección Restricción de la ubicación de recursos de IAM y la Consola del administrador. Esto significa que los publicadores de varias regiones pueden publicar mensajes en un solo tema con baja latencia. Cualquier mensaje individual 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 recopila datos de todos los mensajes publicados en el tema para entregar los mensajes al cliente.

Pub/Sub se divide en dos partes principales: el plano de datos, en el que se manejan los mensajes en movimiento entre publicadores y suscriptores, y el plano de control, en el que se maneja la asignación de publicadores y suscriptores a los servidores del plano de datos. Los servidores del plano de datos se denominan servidores de reenvío, y los servidores del plano de control se denominan routers. Cuando los publicadores y suscriptores se conectan a sus servidores de reenvío asignados, no necesitan información proveniente de los routers (siempre y cuando dichos servidores de reenvío sigan siendo accesibles). Por lo tanto, es posible actualizar el plano de control de Pub/Sub sin afectar a los clientes que ya están conectados y que ya envían o reciben mensajes.

Plano de control

El plano de control de Pub/Sub distribuye los clientes entre los servidores de reenvío, de manera que proporciona escalabilidad, disponibilidad y baja latencia a todos los clientes. Cualquier servidor de reenvío es capaz de entregar mensajes de cualquier tema o suscripción a los clientes. Cuando un cliente se conecta a Pub/Sub, el router elige los centros de datos a los que se debe conectar el cliente en función de la distancia de red más corta, una medida de la latencia en la conexión entre dos puntos. Dentro de cualquier centro de datos determinado, el router intenta distribuir la carga general entre el conjunto de servidores de reenvío disponibles. El router debe lograr un equilibrio entre dos objetivos diferentes cuando realiza esta asignación: (a) uniformidad de cargas (es decir, lo ideal es que cada servidor de reenvío se cargue igual que el resto); y (b) estabilidad de las asignaciones (es decir, un cambio en la carga o un cambio en el conjunto de servidores de reenvío disponibles modifica la cantidad mínima de asignaciones existentes). El router usa una variante de hashing coherente desarrollado por Google Research para lograr un equilibrio ajustable entre coherencia y uniformidad. El router proporciona al cliente una lista ordenada de servidores de reenvío a los que puede considerar conectarse. Esta lista ordenada puede cambiar según la disponibilidad de los servidores de reenvío y la forma de la carga del cliente.

Un cliente toma esta lista de servidores de reenvío y se conecta a uno o más de ellos. El cliente prefiere conectarse a los servidores de reenvío que el router recomienda más, pero también considera cualquier falla que haya ocurrido. Por ejemplo, el cliente puede decidir probar los servidores de reenvío de un centro de datos diferente si fallaron varios intentos de conectarse a los más cercanos. Para que los clientes de Pub/Sub no tengan que preocuparse de estos detalles de implementación, existe un proxy de servicio entre los clientes y servidores de reenvío que realiza esta optimización de la conexión en nombre de los clientes.

Plano de datos: el ciclo de un mensaje

El plano de datos recibe mensajes de los publicadores y los envía a los clientes. Quizás la mejor manera de entender el plano de datos de Pub/Sub es observar el ciclo de un mensaje, desde el momento en el que el servicio lo recibe hasta que ya no está en él. Sigamos los pasos del procesamiento de un mensaje. Para los fines de esta sección, damos por hecho que el tema en el que se publica el mensaje cuenta con al menos una suscripción adjunta. En general, un mensaje sigue estos pasos:

  1. Un publicador envía un mensaje.

  2. El mensaje se escribe en el almacenamiento.

  3. Pub/Sub envía una confirmación al publicador de que recibió el mensaje y que garantiza su entrega a todas las suscripciones adjuntas.

  4. Al mismo tiempo que escribe el mensaje en el almacenamiento, Pub/Sub lo envía a los suscriptores.

  5. Los suscriptores envían una confirmación a Pub/Sub de que procesaron el mensaje.

  6. Una vez que al menos un suscriptor por cada suscripción confirmó la recepción del mensaje, Pub/Sub borra el mensaje del almacenamiento.

Primero, un publicador envía un mensaje sobre un tema a Pub/Sub. Está encriptado por la capa de proxy y se envía a un servidor de reenvío de publicación, que es un servidor de reenvío al que está conectado el publicador. Para garantizar la entrega, el mensaje se escribe en el almacenamiento de forma inmediata. El servidor de reenvío primero escribe el mensaje en N clústeres (aquí, N es un número impar) y considera que el mensaje se almacenó cuando se escribió en, al menos, [N/2] clústeres. Una vez que el mensaje se almacenó, el servidor de reenvío de publicación envía una confirmación de recepción del mensaje al publicador y, en ese momento, Pub/Sub garantiza que el mensaje se entregará a todas las suscripciones adjuntas. Un proceso en segundo plano escribe con regularidad los mensajes que no están en todos los N clústeres en los clústeres en los que faltan los mensajes.

Dentro de cada clúster, el mensaje se escribe en M discos independientes (aquí, M es un número impar), lo que requiere que los datos estén en [M/2] discos antes de que se consideren almacenados en ese clúster. En total, cualquier mensaje publicado se escribirá en al menos ⌈M/2⌉ discos independientes en ⌈N/2⌉ clústeres antes de que se lo considere almacenado y, con el tiempo, se replicará en N*M discos.

El servidor de reenvío de publicación cuenta con una lista de todas las suscripciones que se adjuntan a un tema. Es responsable de almacenar los mensajes publicados y los metadatos que describen qué mensajes se confirmaron como recibidos por cada suscripción. El conjunto de mensajes recibidos y almacenados por un servidor de reenvío de publicación dentro de un tema en particular, junto con este seguimiento de los mensajes confirmados como recibidos, se denomina “fuente de mensajes publicados”. Según los requisitos de capacidad de procesamiento para el tema, un único publicador puede enviar sus mensajes a múltiples servidores de reenvío de publicación y almacenarlos en varias fuentes de mensajes publicados. Los distintos publicadores de un mismo tema también pueden enviar mensajes a diferentes servidores de reenvío de publicación. Cada mensaje se envía a un solo servidor de reenvío de publicación. Pub/Sub configura de forma dinámica la cantidad de servidores de reenvío de publicación que reciben mensajes de un tema en particular a medida que cambia la capacidad de procesamiento.

Los suscriptores reciben mensajes cuando se conectan con los servidores de reenvío de suscripción, a través de los que los mensajes circulan desde los publicadores hacia los suscriptores. En el caso de un suscriptor de extracción, “conectarse” significa emitir una solicitud de extracción. En el caso de un suscriptor de envío, “conectarse” significa tener el extremo de envío registrado en Pub/Sub. Una vez que se crea una suscripción, se garantiza que cualquier mensaje publicado después de ese momento se enviará a esa suscripción, lo que llamamos una garantía de punto de sincronización.

Cada servidor de reenvío de suscripción debe solicitar mensajes a los servidores de reenvío de publicación que tengan fuentes de mensajes publicados para el tema. Al igual que los publicadores, los suscriptores pueden conectarse con más de un servidor de reenvío de suscripción para recibir mensajes. De esta manera, no todos los servidores de reenvío de suscripción deben tener en cuenta o recibir los mensajes de todas las fuentes de mensajes publicados de un tema. Esto es una propiedad importante que le permite a Pub/Sub escalar de forma horizontal. En función de la capacidad de procesamiento de los mensajes que se entregan a los suscriptores, Pub/Sub configura de forma dinámica la cantidad de servidores de reenvío de suscripción a través de los que los suscriptores reciben mensajes de un tema en particular a medida que cambia la capacidad de procesamiento.

Un servidor de reenvío de suscripción realiza solicitudes a uno o más servidores de reenvío de publicación que tengan fuentes de mensajes publicados de un tema para solicitar los mensajes que necesita. El servidor de reenvío de publicación envía los mensajes sin confirmación de recepción al servidor de reenvío de suscripción, que luego retransmite los mensajes a un suscriptor.

Una vez que un suscriptor procesa un mensaje, envía una confirmación de recepción al servidor de reenvío de suscripción. El servidor de reenvío de suscripción retransmite esta confirmación de recepción al servidor de reenvío de publicación, que almacena dicha confirmación en la fuente de mensajes publicados. Una vez que todas las suscripciones de un tema confirmaron la recepción de un mensaje, el mensaje se borra de forma asíncrona de la fuente de mensajes publicados y del almacenamiento.

Diferentes mensajes para un solo tema y suscripción pueden fluir a través de muchos publicadores, suscriptores, servidores de reenvío de publicación y servidores de reenvío de suscripción. Los publicadores pueden publicar varios servidores de reenvío a la vez y los suscriptores pueden conectarse a varios servidores de reenvío de suscripciones para recibir mensajes. Por lo tanto, el flujo de mensajes a través de conexiones entre publicadores, suscriptores y servidores de reenvío puede ser complejo. El siguiente diagrama muestra cómo se pueden enviar mensajes para un solo tema y suscripción, en que los diferentes colores indican las diferentes rutas que los mensajes pueden seguir desde los publicadores hasta los suscriptores:

Los mensajes de varios publicadores se envían a los suscriptores a través de servidores de reenvío de publicación y suscripción.

Mantén Pub/Sub en funcionamiento

Garantizar que un sistema distribuido como Pub/Sub pueda permanecer en funcionamiento y entregar mensajes con eficiencia a todos los clientes requiere una gran visibilidad y un control del sistema. El mantenimiento del servicio es responsabilidad de nuestros ingenieros de confiabilidad de sitios (SRE). En el caso de Pub/Sub, estos ingenieros están asentados en varias ubicaciones por todo el mundo para proporcionar cobertura las 24 horas, todos los días.

Entornos

La primera parte del mantenimiento de un sistema como Pub/Sub consiste en tener la capacidad de probar el software antes de que lo usen los clientes. Para que esto sea posible, existen tres entornos de Pub/Sub: prueba, etapa de pruebas y producción. En los entornos de prueba y etapa de pruebas, no hay tráfico de clientes. En ellos solo se incluyen nuestras pruebas y supervisión en ejecución continua que ayudan a detectar cualquier problema con las versiones. Estos entornos reciben versiones nuevas del software antes de la producción. La diferencia entre los entornos de prueba y de etapa de pruebas es que este último es una réplica exacta de lo que hay (o habrá pronto) en el entorno de producción, incluidas la versión de software y las marcas de línea de comandos. El entorno de prueba puede tener funciones habilitadas en las que los desarrolladores están trabajando en la actualidad y que planean lanzar en el futuro.

Implementación

El procedimiento de lanzamiento y prueba de Pub/Sub está diseñado para minimizar el posible impacto. Veamos los pasos típicos del lanzamiento de una versión nueva de Pub/Sub:

  1. Asegúrate de que todas las pruebas de unidades y pruebas de integración se aprueben.

  2. Crea una versión nueva de todos los servidores.

  3. Implementa los servidores nuevos en los entornos de prueba y etapa de pruebas.

  4. Ejecuta los servidores en los entornos de prueba y etapa de pruebas durante varios días.

  5. Si no surgen problemas, lanza servidores a canary, un subconjunto del entorno de producción que tiene una cantidad pequeña de tráfico de clientes.

  6. Si no se detectan problemas en canary, despliega de manera progresiva los servidores a más producción durante varios días hasta que se publiquen en todas partes.

Dado que Pub/Sub está diseñado para resistir fallas, por ejemplo, mediante la separación del plano de control y el plano de datos, los lanzamientos de versiones nuevas de servidores son perfectos para los clientes y no deberían afectar el rendimiento que ellos perciben.

Supervisión

La clave para mantener Pub/Sub en funcionamiento es detectar y mitigar los problemas de forma automática antes de que sean visibles para los usuarios finales. Para lograr esto, se requiere una supervisión exhaustiva del sistema. El equipo de ingeniería de confiabilidad de sitios (SRE) mantiene un conjunto de indicadores de nivel de servicio (SLI), métricas bien definidas que describen el comportamiento del sistema. Las métricas pueden incluir “la cantidad de tiempo que tarda en completarse una solicitud CreateSubscription” o “la tasa de errores generados por las solicitudes de Publish”. Estas métricas se miden de diversas maneras. Algunas de ellas son estrictamente internas de nuestros servidores de reenvío y routers. Por ejemplo, miden cuánto tiempo lleva escribir los mensajes en el disco.

Todas estas medidas ayudan a definir objetivos de nivel de servicio (SLO) internos, objetivos específicos para los SLI. Por ejemplo, "una solicitud CreateSubscription no debería tardar más de cinco segundos en completarse". Los SRE reciben alertas por incumplimientos de los SLO y deben atender las alertas en un plazo de cinco minutos.

Un Acuerdo de Nivel de Servicio (ANS) enumera los SLO que definen nuestras garantías de rendimiento para los usuarios finales y las consecuencias si no los cumplimos. Puedes leer el ANS de Pub/Sub.

Mantenemos un conjunto de clientes que publican contenido y se suscriben de forma predecible. Estos se denominan sondeadores. Los sondeos existen tanto para el plano de datos como para el plano de control. Cada uno de nuestros sistemas de sondeo realiza acciones específicas tal como lo haría un cliente y mide el tiempo que tardan las operaciones. Por ejemplo, tenemos un sistema de sondeo que crea una suscripción nueva, publica un mensaje y observa cuánto tiempo llevó crear la suscripción y recibir el mensaje. Si los sondeadores determinan que alguna de las métricas medidas no es lo que se espera, se alerta a los SRE.

Las métricas de nuestros servidores y sondeadores se resumen en varios paneles internos, el primer lugar en el que se observan los SRE 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 individual.

Las métricas que son más interesantes para los usuarios del servicio se exponen a través de Google Cloud Monitoring.

Controles

Tenemos a nuestra disposición varios controles que ayudan a ajustar el rendimiento de Pub/Sub. Algunos de estos controles están diseñados para ayudar en caso de interrupciones de los centros de datos o de las máquinas. Podemos establecer restricciones de enrutamiento en algunos temas o en todos ellos. Se trata de reglas que especifican los conjuntos de clientes que pueden y los que no pueden conectarse a conjuntos de servidores de reenvío. Usamos las restricciones de enrutamiento para desviar el tráfico de las tareas de servidores de reenvío individuales o de los centros de datos que no funcionan como deberían.

Otra función que se puede configurar es el control de flujo. Esta función nos permite maximizar la capacidad de procesamiento a la vez que se evita la sobrecarga en el servicio. El control de flujo es una forma de determinar por tráfico mediante la que, a lo largo del tiempo, se pueden mitigar los picos inesperados y repentinos en la carga para lograr una mayor estabilidad del servicio. El control de flujo funciona en todo el sistema y, también, a nivel de tema o de suscriptor para limitar la cantidad de mensajes o de bytes que se transfieren o están pendientes. En este caso, “pendiente” significa entregado al cliente, pero aún sin confirmación de recepción. El control de flujo y 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 en escalabilidad, disponibilidad y latencia que brinda un servicio como Pub/Sub definen la propuesta de valor para los clientes que están considerando pasar a servicios en la nube administrados. Cualquier servicio de mensajería asíncrona debe compilarse desde cero con estas funciones en mente. Con más de una década de experiencia en la entrega de un gran volumen de mensajes con rapidez y confiabilidad, el equipo de Pub/Sub compiló y mantiene un servicio capaz de satisfacer las demandas de los productos más fundamentales de Google. Ahora ese mismo servicio está disponible para todos los clientes externos que deseen enviar sus mensajes a cualquier parte del mundo sin tener que preocuparse por la capacidad de su sistema de mensajería de soportar dos, diez o cien veces su carga actual.

Glosario

Término Descripción
clúster Una agrupación lógica de máquinas que, por lo general, comparten el mismo dominio con fallas (p. ej., una red local compartida y energía compartida).
plano de control La capa de Pub/Sub que maneja la asignación de publicadores y suscriptores a servidores en el plano de datos.
plano de datos La capa de Pub/Sub que maneja los mensajes en movimiento entre publicadores y suscriptores.
servidor de reenvío Un servidor en el plano de datos.
acceso a datos a nivel global Los clientes publicadores y suscriptores de Pub/Sub desconocen la ubicación de los datos. El enrutamiento y almacenamiento los realiza el propio servicio en su totalidad, de acuerdo con la política de restricción de ubicación.
escalable de forma horizontal La capacidad de un servicio de manejar sin problemas más carga mediante el aumento de la cantidad de instancias de componentes del servicio.
mensaje Los datos que se mueven a través de Pub/Sub.
distancia de red Una medida de la latencia en la conexión entre dos puntos.
sondeador Una tarea que actúa como un cliente y realiza una o más acciones de forma predecible en los servidores de Pub/Sub.
fuente de mensajes publicados Un conjunto de mensajes recibidos y almacenados por un servidor de reenvío de publicación, y el conjunto de ID de mensajes confirmados como recibidos 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 mensajes se separan de los destinatarios.
publicador Un cliente de Pub/Sub que crea mensajes y los envía (publica) en un tema específico.
router Un servidor en el plano de control.
restricciones de enrutamiento Una lista de reglas que indican qué servidores de reenvío deben o no enviar los routers a los clientes como extremos posibles para conectarse.
acuerdo de nivel de servicio (ANS) Una lista de SLO que define las garantías de rendimiento de un sistema para los clientes y describe las consecuencias que tendrán lugar si estas 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 denominada que representa un interés en recibir todos los mensajes sobre un tema en particular.
garantía de punto de sincronización La hora en la que se crea una suscripción, en la que se entregarán a los suscriptores todos los mensajes posteriores publicados.
tema Una entidad denominada que representa un feed de mensajes.