Roblox vuelve a estar operativo

Desde el 28 de octubre hasta su resolución total el 31 de octubre, Roblox sufrió una interrupción del servicio de 73 horas.¹ Cincuenta millones de jugadores utilizan Roblox a diario y, para crear la experiencia que nuestros jugadores esperan, nuestra infraestructura implica cientos de servicios internos en línea. Al igual que con cualquier servicio a gran escala, sufrimos interrupciones de vez en cuando, pero la prolongada duración de esta interrupción la hace especialmente destacable. Pedimos sinceras disculpas a nuestra comunidad por el tiempo de inactividad.
Compartimos estos detalles técnicos para que nuestra comunidad comprenda la causa raíz del problema, cómo lo abordamos y qué estamos haciendo para evitar que se repitan problemas similares en el futuro. Nos gustaría reiterar que no se produjo ninguna pérdida de datos de los usuarios ni acceso por parte de terceros no autorizados a ninguna información durante el incidente.
El equipo de ingeniería de Roblox y el personal técnico de HashiCorp unieron esfuerzos para restablecer el servicio de Roblox. Queremos expresar nuestro agradecimiento al equipo de HashiCorp, que aportó recursos increíbles y trabajó con nosotros sin descanso hasta que se resolvieron los problemas.
Resumen de la interrupción
La interrupción fue excepcional tanto por su duración como por su complejidad. El equipo tuvo que abordar una serie de retos de forma secuencial para comprender la causa raíz y restablecer el servicio.
- La interrupción duró 73 horas.
- La causa raíz se debió a dos problemas. La activación de una función de streaming relativamente nueva en Consul bajo una carga de lectura y escritura inusualmente alta provocó una contienda excesiva y un rendimiento deficiente. Además, nuestras condiciones de carga particulares desencadenaron un problema de rendimiento patológico en BoltDB. El sistema de código abierto BoltDB se utiliza dentro de Consul para gestionar los registros de escritura anticipada (WAL) para la elección de líderes y la replicación de datos.
- El hecho de que un único clúster de Consul soportara múltiples cargas de trabajo agravó el impacto de estos problemas.
- Las dificultades para diagnosticar estos dos problemas, en principio no relacionados entre sí y profundamente arraigados en la implementación de Consul, fueron en gran parte responsables del prolongado tiempo de inactividad.
- Los sistemas de monitorización críticos que habrían proporcionado una mejor visibilidad de la causa de la interrupción dependían de los sistemas afectados, como Consul. Esta combinación dificultó gravemente el proceso de clasificación.
- Fuimos reflexivos y cuidadosos en nuestro enfoque para recuperar Roblox de un estado de caída total prolongada, lo que también llevó un tiempo considerable.
- Hemos acelerado los esfuerzos de ingeniería para mejorar nuestra monitorización, eliminar las dependencias circulares en nuestra pila de observabilidad y acelerar nuestro proceso de arranque.
- Estamos trabajando para trasladarnos a múltiples zonas de disponibilidad y centros de datos.
- Estamos solucionando los problemas en Consul que fueron la causa principal de este incidente.
Preámbulo: nuestro entorno de clúster y HashiStack
La infraestructura central de Roblox se ejecuta en los centros de datos de Roblox. Implementamos y gestionamos nuestro propio hardware, así como nuestros propios sistemas de computación, almacenamiento y redes sobre ese hardware. La escala de nuestra implementación es significativa, con más de 18 000 servidores y 170 000 contenedores.
Para ejecutar miles de servidores en múltiples ubicaciones, utilizamos un conjunto de tecnologías conocido comúnmente como «HashiStack». Nomad, Consul y Vault son las tecnologías que utilizamos para gestionar servidores y servicios en todo el mundo, y que nos permiten orquestar los contenedores que dan soporte a los servicios de Roblox.
Nomad se utiliza para programar el trabajo. Decide qué contenedores se ejecutarán en qué nodos y en qué puertos serán accesibles. También valida el estado de los contenedores. Todos estos datos se transmiten a un Registro de Servicios, que es una base de datos de combinaciones de IP:Puerto. Los servicios de Roblox utilizan el Registro de Servicios para localizarse entre sí y poder comunicarse. Este proceso se denomina «descubrimiento de servicios». Utilizamos Consul para el descubrimiento de servicios, comprobaciones de estado, bloqueo de sesiones (para sistemas de alta disponibilidad construidos sobre él) y como almacén de clave-valor.
Consul se implementa como un clúster de máquinas con dos roles. Los «votantes» (5 máquinas) mantienen de forma autoritaria el estado del clúster; los «no votantes» (5 máquinas adicionales) son réplicas de solo lectura que ayudan a escalar las solicitudes de lectura. En cualquier momento dado, el clúster elige a uno de los votantes como líder. El líder es responsable de replicar los datos a los demás votantes y de determinar si los datos escritos se han confirmado por completo. Consul utiliza un algoritmo llamado Raft para la elección del líder y para distribuir el estado por todo el clúster de manera que se garantice que cada nodo del clúster esté de acuerdo con las actualizaciones. No es raro que el líder cambie varias veces a lo largo de un día mediante la elección de líder.
A continuación se muestra una captura de pantalla reciente del panel de control de Consul en Roblox tras el incidente. Muchas de las métricas operativas clave a las que se hace referencia en esta entrada del blog se muestran en niveles normales. El tiempo de aplicación de KV, por ejemplo, se considera normal si es inferior a 300 ms y en este momento es de 30,6 ms. El líder de Consul ha estado en contacto con otros servidores del clúster en los últimos 32 ms, lo cual es muy reciente.

En los meses previos al incidente de octubre, Roblox actualizó de Consul 1.9 a Consul 1.10 para aprovechar una nueva función de streaming. Esta función de streaming está diseñada para reducir significativamente la CPU y el ancho de banda de red necesarios para distribuir actualizaciones en clústeres a gran escala como el de Roblox.
Detección inicial (28/10 a las 13:37)
En la tarde del 28 de octubre, el rendimiento de Vault se vio afectado y un único servidor de Consul presentaba una elevada carga de CPU. Los ingenieros de Roblox comenzaron a investigar. En ese momento, los jugadores no se vieron afectados.
Evaluación inicial (28/10 13:37 – 29/10 02:00)
La investigación inicial sugirió que el clúster de Consul del que dependen Vault y muchos otros servicios no funcionaba correctamente. Concretamente, las métricas del clúster de Consul mostraban una latencia de escritura elevada en el almacén KV subyacente en el que Consul almacena los datos. La latencia del percentil 50 en estas operaciones solía estar por debajo de los 300 ms, pero ahora era de 2 segundos. Los problemas de hardware no son inusuales a la escala de Roblox, y Consul puede sobrevivir a un fallo de hardware. Sin embargo, si el hardware simplemente es lento en lugar de fallar, puede afectar al rendimiento general de Consul. En este caso, el equipo sospechó que la causa principal era el deterioro del rendimiento del hardware y comenzó el proceso de sustitución de uno de los nodos del clúster de Consul. Este fue nuestro primer intento de diagnosticar el incidente. Por esas fechas, el personal de HashiCorp se unió a los ingenieros de Roblox para ayudar con el diagnóstico y la corrección. Todas las referencias a «el equipo» y «el equipo de ingeniería» a partir de este momento se refieren tanto al personal de Roblox como al de HashiCorp.
A pesar del nuevo hardware, el rendimiento del clúster de Consul siguió viéndose afectado. A las 16:35, el número de jugadores en línea se redujo al 50 % de lo normal.

Esta caída coincidió con un deterioro significativo del estado del sistema, lo que finalmente provocó una interrupción total del servicio. ¿Por qué? Cuando un servicio de Roblox quiere comunicarse con otro servicio, depende de Consul para tener información actualizada sobre la ubicación del servicio con el que quiere comunicarse. Sin embargo, si Consul no funciona correctamente, los servidores tienen dificultades para conectarse. Además, Nomad y Vault dependen de Consul, por lo que, cuando Consul no funciona correctamente, el sistema no puede programar nuevos contenedores ni recuperar los secretos de producción utilizados para la autenticación. En resumen, el sistema falló porque Consul era un punto único de fallo y no funcionaba correctamente.
En ese momento, el equipo desarrolló una nueva teoría sobre lo que estaba fallando: el aumento del tráfico. ¿Quizás Consul iba lento porque nuestro sistema había alcanzado un punto de saturación y los servidores en los que se ejecutaba Consul ya no podían soportar la carga? Este fue nuestro segundo intento de diagnosticar la causa raíz del incidente.
Dada la gravedad del incidente, el equipo decidió sustituir todos los nodos del clúster de Consul por máquinas nuevas y más potentes. Estas nuevas máquinas tenían 128 núcleos (el doble) y discos SSD NVME más nuevos y rápidos. A las 19:00, el equipo había migrado la mayor parte del clúster a las nuevas máquinas, pero el clúster seguía sin funcionar correctamente. El clúster informaba de que la mayoría de los nodos no podían seguir el ritmo de las escrituras, y la latencia del percentil 50 en las escrituras KV seguía rondando los 2 segundos, en lugar de los 300 ms habituales o menos.
Intento n.º 1 de restablecimiento del servicio (29/10, 02:00 – 04:00)
Los dos primeros intentos de devolver el clúster de Consul a un estado operativo no tuvieron éxito. Seguíamos observando una latencia elevada en las escrituras KV, así como un nuevo síntoma inexplicable que no podíamos entender: el líder de Consul se desincronizaba regularmente con los demás votantes.
El equipo decidió apagar todo el clúster de Consul y restablecer su estado utilizando una instantánea de unas horas antes, al inicio de la interrupción. Entendimos que esto podría suponer una pequeña pérdida de datos de configuración del sistema (no de datos de los usuarios). Dada la gravedad de la interrupción y nuestra confianza en que podríamos restaurar estos datos de configuración del sistema manualmente si fuera necesario, consideramos que era aceptable.
Esperábamos que la restauración a partir de una instantánea tomada cuando el sistema estaba en buen estado devolviera el clúster a un estado saludable, pero teníamos una preocupación adicional. Aunque Roblox no tenía ningún tráfico generado por los usuarios circulando por el sistema en ese momento, los servicios internos de Roblox seguían activos y se comunicaban diligentemente con Consul para conocer la ubicación de sus dependencias y actualizar su información de estado. Estas lecturas y escrituras estaban generando una carga significativa en el clúster. Nos preocupaba que esta carga pudiera volver a llevar inmediatamente al clúster a un estado no operativo, incluso si el reinicio del clúster se realizaba con éxito. Para abordar esta preocupación, configuramos iptables en el clúster para bloquear el acceso. Esto nos permitiría volver a poner en marcha el clúster de forma controlada y nos ayudaría a comprender si la carga que estábamos ejerciendo sobre Consul, independientemente del tráfico de los usuarios, formaba parte del problema.
El reinicio se llevó a cabo sin problemas y, en un principio, las métricas parecían buenas. Cuando eliminamos el bloqueo de iptables, la carga de descubrimiento de servicios y comprobación de estado de los servicios internos volvió a ser la esperada. Sin embargo, el rendimiento de Consul comenzó a degradarse de nuevo y, finalmente, volvimos al punto de partida: el percentil 50 en las operaciones de escritura KV volvió a situarse en 2 segundos. Los servicios que dependían de Consul empezaban a marcarse a sí mismos como «no operativos» y, finalmente, el sistema volvió a caer en el ya familiar estado problemático. Eran las 04:00. Estaba claro que había algo en nuestra carga sobre Consul que estaba causando problemas y, tras más de 14 horas desde el inicio del incidente, seguíamos sin saber qué era.
Segundo intento de restablecimiento del servicio (29/10 a las 04:00 – 30/10 a las 02:00)
Habíamos descartado un fallo de hardware. Un hardware más rápido no había ayudado y, como supimos más tarde, podía haber perjudicado la estabilidad. Reiniciar el estado interno de Consul tampoco había servido de nada. No había tráfico de usuarios entrando, pero Consul seguía siendo lento. Habíamos utilizado iptables para permitir que el tráfico volviera al clúster poco a poco. ¿Estaba el clúster volviendo a un estado inestable simplemente por el gran volumen de miles de contenedores que intentaban reconectarse? Este fue nuestro tercer intento de diagnosticar la causa raíz del incidente.
El equipo de ingeniería decidió reducir el uso de Consul y luego reintroducirlo de forma cuidadosa y sistemática. Para asegurarnos de tener un punto de partida limpio, también bloqueamos el tráfico externo restante. Elaboramos una lista exhaustiva de los servicios que utilizan Consul e implementamos cambios de configuración para desactivar todo uso no esencial. Este proceso llevó varias horas debido a la gran variedad de sistemas y tipos de cambios de configuración afectados. Los servicios de Roblox que normalmente tenían cientos de instancias en ejecución se redujeron a cifras de un solo dígito. La frecuencia de las comprobaciones de estado se redujo de 60 segundos a 10 minutos para dar al clúster un respiro adicional. A las 16:00 del 29 de octubre, más de 24 horas después del inicio de la interrupción del servicio, el equipo inició su segundo intento de volver a poner Roblox en línea. Una vez más, la fase inicial de este intento de reinicio parecía prometedora, pero a las 02:00 del 30 de octubre, Consul se encontraba de nuevo en un estado anómalo, esta vez con una carga significativamente menor procedente de los servicios de Roblox que dependen de él.
En ese momento, quedó claro que el uso general de Consul no era el único factor que contribuía a la degradación del rendimiento que habíamos detectado por primera vez el día 28. Ante esta constatación, el equipo volvió a cambiar de estrategia. En lugar de analizar Consul desde la perspectiva de los servicios de Roblox que dependen de él, el equipo comenzó a examinar el funcionamiento interno de Consul en busca de pistas.
Investigación sobre la contienda (30/10 02:00 – 30/10 12:00)
Durante las siguientes 10 horas, el equipo de ingeniería profundizó en los registros de depuración y en las métricas a nivel del sistema operativo. Estos datos mostraban que las escrituras KV de Consul se bloqueaban durante largos periodos de tiempo. En otras palabras, «contendencia». La causa de la contendencia no era evidente de inmediato, pero una teoría era que el cambio de servidores de 64 a 128 núcleos de CPU al inicio de la interrupción podría haber agravado el problema. Tras examinar los datos de htop y los datos de depuración del rendimiento que se muestran en las capturas de pantalla siguientes, el equipo concluyó que valía la pena volver a servidores de 64 núcleos similares a los utilizados antes de la interrupción del servicio. El equipo comenzó a preparar el hardware: se instaló Consul, se revisaron tres veces las configuraciones del sistema operativo y se prepararon las máquinas para el servicio de la forma más detallada posible. A continuación, el equipo volvió a migrar el clúster de Consul a servidores de 64 núcleos de CPU, pero este cambio no sirvió de nada. Este fue nuestro cuarto intento de diagnosticar la causa raíz del incidente.


Causas fundamentales identificadas (30/10 12:00 – 30/10 20:00)
Hace varios meses, habilitamos una nueva función de streaming de Consul en un subconjunto de nuestros servicios. Esta función, diseñada para reducir el uso de la CPU y el ancho de banda de red del clúster de Consul, funcionó según lo previsto, por lo que durante los meses siguientes la fuimos habilitando de forma gradual en más de nuestros servicios de backend. El 27 de octubre a las 14:00, un día antes de la interrupción del servicio, habilitamos esta función en un servicio de backend responsable del enrutamiento del tráfico. Como parte de esta implementación, con el fin de prepararnos para el aumento de tráfico que solemos observar a finales de año, también aumentamos en un 50 % el número de nodos que gestionan el enrutamiento del tráfico. El sistema había funcionado bien con el streaming a este nivel durante un día antes de que se produjera el incidente, por lo que inicialmente no estaba claro por qué había cambiado su rendimiento. Sin embargo, al analizar los informes de rendimiento y los gráficos de llama de los servidores Consul, observamos indicios de que las rutas de código de streaming eran las responsables de la contienda que provocaba un elevado uso de la CPU. Desactivamos la función de streaming en todos los sistemas Consul, incluidos los nodos de enrutamiento de tráfico. La propagación del cambio de configuración finalizó a las 15:51, momento en el que el percentil 50 de las escrituras de Consul KV se redujo a 300 ms. Por fin habíamos dado con la clave.
¿Por qué era un problema el streaming? HashiCorp explicó que, aunque el streaming era en general más eficiente, utilizaba menos elementos de control de concurrencia (canales Go) en su implementación que el sondeo prolongado. Bajo una carga muy alta —concretamente, tanto una carga de lectura muy alta como una carga de escritura muy alta—, el diseño del streaming agrava la cantidad de contención en un único canal Go, lo que provoca bloqueos durante las escrituras, lo que lo hace significativamente menos eficiente. Este comportamiento también explicaba el efecto de los servidores con mayor número de núcleos: esos servidores eran arquitecturas de doble socket con un modelo de memoria NUMA. La contienda adicional por los recursos compartidos empeoraba, por tanto, en esta arquitectura. Al desactivar el streaming, mejoramos drásticamente el estado del clúster de Consul.
A pesar del avance, aún no estábamos fuera de peligro. Vimos que Consul elegía de forma intermitente nuevos líderes de clúster, lo cual era normal, pero también observamos que algunos líderes presentaban los mismos problemas de latencia que habíamos visto antes de desactivar el streaming, lo cual no era normal. Sin pistas evidentes que apuntaran a la causa raíz del problema de lentitud de los líderes, y con indicios de que el clúster funcionaba correctamente siempre que ciertos servidores no fueran elegidos como líderes, el equipo tomó la decisión pragmática de solucionar el problema impidiendo que los líderes problemáticos permanecieran elegidos. Esto permitió al equipo centrarse en devolver a un estado óptimo los servicios de Roblox que dependen de Consul.
Pero, ¿qué estaba pasando con los líderes lentos? No lo averiguamos durante el incidente, pero los ingenieros de HashiCorp determinaron la causa raíz en los días posteriores a la interrupción del servicio. Consul utiliza una popular biblioteca de persistencia de código abierto llamada BoltDB para almacenar los registros de Raft. No se utiliza para almacenar el estado actual dentro de Consul, sino más bien un registro acumulativo de las operaciones que se están aplicando. Para evitar que BoltDB crezca indefinidamente, Consul realiza instantáneas periódicamente. La operación de instantánea escribe el estado actual de Consul en el disco y luego elimina las entradas de registro más antiguas de BoltDB.
Sin embargo, debido al diseño de BoltDB, incluso cuando se eliminan las entradas de registro más antiguas, el espacio que BoltDB ocupa en el disco nunca se reduce. En su lugar, todas las páginas (segmentos de 4 KB dentro del archivo) que se utilizaron para almacenar los datos eliminados se marcan como «libres» y se reutilizan para escrituras posteriores. BoltDB realiza un seguimiento de estas páginas libres en una estructura denominada «freelist». Normalmente, la latencia de escritura no se ve afectada de manera significativa por el tiempo que lleva actualizar la freelist, pero la carga de trabajo de Roblox puso de manifiesto un problema de rendimiento patológico en BoltDB que hacía que el mantenimiento de la freelist resultara extremadamente costoso.
Restauración del servicio de almacenamiento en caché (30/10 a las 20:00 – 31/10 a las 05:00)
Habían pasado 54 horas desde el inicio de la interrupción del servicio. Con el streaming desactivado y un proceso en marcha para evitar que los líderes lentos permanecieran elegidos, Consul se mostraba ahora estable de forma constante. El equipo estaba listo para centrarse en el restablecimiento del servicio.
Roblox utiliza un patrón típico de microservicios para su backend. En la base de la «pila» de microservicios se encuentran las bases de datos y las cachés. Estas bases de datos no se vieron afectadas por la interrupción del servicio, pero el sistema de almacenamiento en caché, que gestiona habitualmente 1 000 millones de solicitudes por segundo a través de sus múltiples capas durante el funcionamiento normal del sistema, no funcionaba correctamente. Dado que nuestras cachés almacenan datos transitorios que se pueden reponer fácilmente desde las bases de datos subyacentes, la forma más sencilla de devolver el sistema de almacenamiento en caché a un estado correcto era volver a implementarlo.
El proceso de reimplementación de la caché se topó con una serie de problemas:
- Probablemente debido al restablecimiento de la instantánea del clúster de Consul que se había realizado anteriormente, los datos de programación interna que el sistema de caché almacena en Consul KV eran incorrectos.
- Las implementaciones de cachés pequeñas tardaban más de lo esperado en completarse, y las de cachés grandes no llegaban a terminarse. Resultó que había un nodo defectuoso que el programador de tareas consideraba completamente abierto en lugar de defectuoso. Esto provocó que el programador de tareas intentara programar de forma agresiva tareas de caché en este nodo, lo que falló porque el nodo estaba defectuoso.
- La herramienta de implementación automatizada del sistema de caché se diseñó para admitir ajustes incrementales en implementaciones a gran escala que ya gestionaban tráfico a gran escala, no para intentos iterativos de arrancar un clúster grande desde cero.
El equipo trabajó toda la noche para identificar y resolver estos problemas, garantizar que los sistemas de caché se implementaran correctamente y verificar su corrección. A las 05:00 del 31 de octubre, 61 horas después del inicio de la interrupción, contábamos con un clúster de Consul en buen estado y un sistema de caché en buen estado. Estábamos listos para poner en marcha el resto de Roblox.
El regreso de los jugadores (31/10 05:00 – 31/10 16:00)
La fase final de restablecimiento del servicio comenzó oficialmente a las 05:00 del día 31. Al igual que con el sistema de caché, una parte significativa de los servicios en ejecución se había apagado durante la interrupción inicial o las fases de resolución de problemas. El equipo necesitaba reiniciar estos servicios con los niveles de capacidad correctos y verificar que funcionaran correctamente. Todo salió bien y, a las 10:00, estábamos listos para abrir el servicio a los jugadores.
Con las cachés vacías y un sistema del que aún no estábamos seguros, no queríamos una avalancha de tráfico que pudiera volver a poner el sistema en un estado inestable. Para evitar una avalancha, utilizamos el redireccionamiento de DNS para gestionar el número de jugadores que podían acceder a Roblox. Esto nos permitió dejar entrar a un determinado porcentaje de jugadores seleccionados al azar, mientras que los demás seguían siendo redirigidos a nuestra página de mantenimiento estática. Cada vez que aumentábamos el porcentaje, comprobábamos la carga de la base de datos, el rendimiento de la caché y la estabilidad general del sistema. El trabajo continuó durante todo el día, aumentando el acceso en incrementos de aproximadamente un 10 %. Nos encantó ver cómo algunos de nuestros jugadores más fieles descubrieron nuestro esquema de redireccionamiento de DNS y empezaron a compartir esta información en Twitter para poder obtener acceso «anticipado» a medida que restablecíamos el servicio. A las 16:45 del domingo, 73 horas después del inicio de la interrupción, el 100 % de los jugadores tenía acceso y Roblox estaba plenamente operativo.
Análisis adicional y cambios derivados de la interrupción
Aunque los jugadores pudieron volver a Roblox el 31 de octubre, Roblox y HashiCorp continuaron profundizando en su comprensión de la interrupción a lo largo de la semana siguiente. Se identificaron y aislaron problemas específicos de contención en el nuevo protocolo de streaming. Aunque HashiCorp había realizado pruebas de rendimiento del streaming a una escala similar al uso de Roblox, no había observado este comportamiento específico anteriormente, ya que se manifestaba a partir de una combinación de un gran número de transmisiones y una alta tasa de rotación. El equipo de ingeniería de HashiCorp está creando nuevas pruebas de rendimiento en laboratorio para reproducir el problema de contención específico y realizando pruebas de escalabilidad adicionales. HashiCorp también está trabajando para mejorar el diseño del sistema de streaming con el fin de evitar la contención bajo cargas extremas y garantizar un rendimiento estable en tales condiciones.
Un análisis más detallado del problema del «líder lento» también reveló la causa principal de las escrituras de datos Raft de dos segundos y los problemas de consistencia del clúster. Los ingenieros examinaron gráficos de llama como el que se muestra a continuación para comprender mejor el funcionamiento interno de BoltDB.


El resultado del comando anterior nos indica varias cosas:
- Este almacén de registros de 4,2 GB solo contiene 489 MB de datos reales (incluidos todos los datos internos del índice). 3,8 GB son espacio «vacío».
- La lista de espacio libre ocupa 7,8 MB, ya que contiene casi un millón de identificadores de páginas libres.
Esto significa que, por cada anexión al registro (cada escritura Raft tras algún procesamiento por lotes), también se escribía en el disco una nueva lista libre de 7,8 MB, aunque los datos brutos reales que se anexaban fueran de 16 kB o menos.
La contrapresión en estas operaciones también llenaba los búferes TCP y contribuía a tiempos de escritura de 2-3 s en líderes en mal estado. La imagen siguiente muestra la investigación sobre TCP Zero Windows durante el incidente.

HashiCorp y Roblox han desarrollado e implementado un proceso que utiliza las herramientas existentes de BoltDB para «compactar» la base de datos, lo que ha resuelto los problemas de rendimiento.
Mejoras recientes y próximos pasos
Han pasado dos meses y medio desde la interrupción del servicio. ¿En qué hemos estado trabajando? Hemos aprovechado este tiempo para aprender todo lo posible de la interrupción del servicio, ajustar las prioridades de ingeniería en función de lo aprendido y reforzar de forma agresiva nuestros sistemas. Uno de los valores de Roblox es «Respetar a la comunidad» y, aunque podríamos haber publicado una entrada antes para explicar lo sucedido, sentíamos que os debíamos a vosotros, nuestra comunidad, lograr avances significativos en la mejora de la fiabilidad de nuestros sistemas antes de publicar nada.
La lista completa de mejoras de fiabilidad completadas y en curso es demasiado larga y detallada para este artículo, pero estos son los puntos clave:
Mejoras en la telemetría
Existía una dependencia circular entre nuestros sistemas de telemetría y Consul, lo que significaba que, cuando Consul no funcionaba correctamente, carecíamos de los datos de telemetría que nos habrían facilitado la tarea de averiguar qué fallaba. Hemos eliminado esta dependencia circular. Nuestros sistemas de telemetría ya no dependen de los sistemas que están configurados para supervisar.
Hemos ampliado nuestros sistemas de telemetría para ofrecer una mejor visibilidad del rendimiento de Consul y BoltDB. Ahora recibimos alertas muy específicas si hay indicios de que el sistema se está acercando al estado que provocó esta interrupción del servicio. También hemos ampliado nuestros sistemas de telemetría para ofrecer más visibilidad de los patrones de tráfico entre los servicios de Roblox y Consul. Esta visibilidad adicional del comportamiento y el rendimiento de nuestro sistema a múltiples niveles ya nos ha ayudado durante las actualizaciones del sistema y las sesiones de depuración.
Expansión a múltiples zonas de disponibilidad y centros de datos
Ejecutar todos los servicios de backend de Roblox en un único clúster de Consul nos dejó expuestos a una interrupción de este tipo. Ya hemos construido los servidores y la red para un centro de datos adicional, geográficamente distinto, que alojará nuestros servicios de backend. Estamos trabajando para trasladarnos a múltiples zonas de disponibilidad dentro de estos centros de datos; hemos realizado modificaciones importantes en nuestra hoja de ruta de ingeniería y en nuestros planes de dotación de personal con el fin de acelerar estos esfuerzos.
Actualizaciones de Consul y fragmentación
Roblox sigue creciendo rápidamente, por lo que, incluso con múltiples clústeres de Consul, queremos reducir la carga que ejercemos sobre Consul. Hemos revisado cómo nuestros servicios utilizan el almacén KV y las comprobaciones de estado de Consul, y hemos dividido algunos servicios críticos en sus propios clústeres dedicados, reduciendo la carga sobre nuestro clúster central de Consul a un nivel más seguro.
Algunos servicios básicos de Roblox utilizan el almacén KV de Consul directamente como un lugar conveniente para almacenar datos, a pesar de que contamos con otros sistemas de almacenamiento que probablemente sean más adecuados. Estamos en proceso de migrar estos datos a un sistema de almacenamiento más adecuado. Una vez completada la migración, esto también reducirá la carga sobre Consul.
Descubrimos una gran cantidad de datos clave-valor obsoletos. La eliminación de estos datos obsoletos mejoró el rendimiento de Consul.
Estamos trabajando en estrecha colaboración con HashiCorp para implementar una nueva versión de Consul que sustituya a BoltDB por un sucesor llamado bbolt, que no presenta el mismo problema de crecimiento ilimitado de la lista libre. Aplazamos intencionadamente esta iniciativa hasta el nuevo año para evitar una actualización compleja durante nuestro pico de tráfico de fin de año. La actualización se está probando ahora y se completará en el primer trimestre.
Mejoras en los procedimientos de arranque y la gestión de la configuración
El esfuerzo de restablecimiento del servicio se vio ralentizado por varios factores, entre ellos la implementación y el calentamiento de las cachés necesarias para los servicios de Roblox. Estamos desarrollando nuevas herramientas y procesos para que este proceso sea más automatizado y menos propenso a errores. En concreto, hemos rediseñado nuestros mecanismos de implementación de cachés para garantizar que podamos poner en marcha rápidamente nuestro sistema de cachés desde cero. La implementación de esto está en marcha.
Hemos colaborado con HashiCorp para identificar varias mejoras de Nomad que nos facilitarán la puesta en marcha de trabajos de gran envergadura tras un largo periodo de indisponibilidad. Estas mejoras se implementarán como parte de nuestra próxima actualización de Nomad, prevista para finales de este mes.
Hemos desarrollado e implementado mecanismos para acelerar los cambios en la configuración de las máquinas.
Reintroducción del streaming
Inicialmente implementamos el streaming para reducir el uso de la CPU y el ancho de banda de red del clúster de Consul. Una vez que se haya probado una nueva implementación a nuestra escala con nuestra carga de trabajo, esperamos reintroducirla cuidadosamente en nuestros sistemas.
Una nota sobre la nube pública
Tras una interrupción del servicio como esta, es natural preguntarse si Roblox consideraría trasladarse a la nube pública y dejar que un tercero gestionara nuestros servicios básicos de computación, almacenamiento y redes.
Otro de nuestros valores en Roblox es «Take The Long View» (Adoptar una visión a largo plazo), y este valor influye en gran medida en nuestra toma de decisiones. Construimos y gestionamos nuestra propia infraestructura básica de forma local porque, a nuestra escala actual y, lo que es más importante, a la escala que sabemos que alcanzaremos a medida que crezca nuestra plataforma, creemos que es la mejor manera de respaldar nuestro negocio y nuestra comunidad. En concreto, al construir y gestionar nuestros propios centros de datos para los servicios de backend y de perímetro de red, hemos podido controlar significativamente los costes en comparación con la nube pública. Estos ahorros influyen directamente en la cantidad que podemos pagar a los creadores de la plataforma. Además, ser propietarios de nuestro propio hardware y construir nuestra propia infraestructura de perímetro nos permite minimizar las variaciones de rendimiento y gestionar cuidadosamente la latencia de nuestros jugadores en todo el mundo. Un rendimiento constante y una baja latencia son fundamentales para la experiencia de nuestros jugadores, que no se encuentran necesariamente cerca de los centros de datos de los proveedores de nube pública.
Cabe señalar que no estamos ideológicamente aferrados a ningún enfoque en particular: utilizamos la nube pública para los casos de uso en los que tiene más sentido para nuestros jugadores y desarrolladores. Por ejemplo, utilizamos la nube pública para la capacidad de picos de tráfico, gran parte de nuestros flujos de trabajo de DevOps y la mayor parte de nuestros análisis internos. En general, consideramos que la nube pública es una buena herramienta para aplicaciones en las que el rendimiento y la latencia no son críticos, y que se ejecutan a una escala limitada. Sin embargo, para nuestras cargas de trabajo más críticas en cuanto a rendimiento y latencia, hemos optado por construir y gestionar nuestra propia infraestructura local. Tomamos esta decisión sabiendo que requiere tiempo, dinero y talento, pero también sabiendo que nos permitirá construir una plataforma mejor. Esto es coherente con nuestro valor «Adoptar una visión a largo plazo».
Estabilidad del sistema desde la interrupción
Roblox suele recibir un aumento repentino de tráfico a finales de diciembre. Nos queda mucho trabajo por hacer en materia de fiabilidad, pero nos complace informar de que Roblox no sufrió ni un solo incidente significativo en producción durante el pico de diciembre, y que el rendimiento y la estabilidad tanto de Consul como de Nomad durante este pico fueron excelentes. Parece que nuestras mejoras inmediatas en fiabilidad ya están dando sus frutos, y a medida que nuestros proyectos a más largo plazo vayan concluyéndose, esperamos resultados aún mejores.
Reflexiones finales
Queremos agradecer a nuestra comunidad global de Roblox su comprensión y apoyo. Otro de nuestros valores en Roblox es «Asumir la responsabilidad», y asumimos toda la responsabilidad por lo ocurrido. Nos gustaría expresar una vez más nuestro más sincero agradecimiento al equipo de HashiCorp. Sus ingenieros se pusieron manos a la obra para ayudarnos desde el inicio de esta interrupción sin precedentes y no nos abandonaron en ningún momento. Incluso ahora, dos meses después de la interrupción, los ingenieros de Roblox y HashiCorp siguen colaborando estrechamente para garantizar que, entre todos, hacemos todo lo posible para evitar que vuelva a ocurrir una interrupción similar.
Por último, queremos dar las gracias a nuestros compañeros de Roblox por demostrar por qué este es un lugar increíble para trabajar. En Roblox creemos en la cortesía y el respeto. Es fácil ser cortés y respetuoso cuando las cosas van bien, pero la verdadera prueba es cómo nos tratamos unos a otros cuando las cosas se ponen difíciles. En algún momento durante una interrupción de 73 horas, con el reloj corriendo y el estrés aumentando, no habría sido de extrañar que alguien perdiera los nervios, dijera algo irrespetuoso o se preguntara en voz alta de quién era la culpa de todo esto. Pero eso no fue lo que ocurrió. Nos apoyamos mutuamente y trabajamos juntos como un solo equipo sin descanso hasta que el servicio volvió a funcionar correctamente. Por supuesto, no estamos orgullosos de esta interrupción del servicio ni del impacto que tuvo en nuestra comunidad, pero sí estamos orgullosos de cómo nos unimos como equipo para devolverle la vida a Roblox, y de cómo nos tratamos unos a otros con civismo y respeto en cada paso del camino.
Hemos aprendido muchísimo de esta experiencia y estamos más comprometidos que nunca con hacer de Roblox una plataforma más sólida y fiable en el futuro.
Gracias de nuevo.
¹ Ten en cuenta que todas las fechas y horas de esta entrada del blog están en hora estándar del Pacífico (PST).


