Garantizar la fiabilidad de las plataformas a gran escala

El funcionamiento de cualquier plataforma distribuida y escalable exige un compromiso con la fiabilidad, para garantizar que los clientes tengan lo que necesitan cuando lo necesitan. Las dependencias pueden ser bastante complejas, especialmente en una plataforma tan grande como Roblox. Crear servicios fiables significa que, independientemente de la complejidad y el estado de las dependencias, cualquier servicio dado no se interrumpirá (es decir, tendrá alta disponibilidad), funcionará sin fallos (es decir, será de alta calidad) y sin errores (es decir, tendrá tolerancia a fallos).
Por qué es importante la fiabilidad
Nuestro equipo de Identidad de Cuentas está comprometido con alcanzar una mayor fiabilidad, ya que los servicios de cumplimiento normativo que hemos creado son componentes fundamentales de la plataforma. El incumplimiento normativo puede tener graves consecuencias. El coste de bloquear el funcionamiento natural de Roblox es muy elevado, ya que se necesitan recursos adicionales para recuperarse tras un fallo y se ve mermada la experiencia del usuario.
El enfoque típico de la fiabilidad se centra principalmente en la disponibilidad, pero en algunos casos los términos se mezclan y se utilizan incorrectamente. La mayoría de las mediciones de disponibilidad solo evalúan si los servicios están activos y en funcionamiento, mientras que aspectos como la tolerancia a la partición y la consistencia a veces se olvidan o se malinterpretan.
De acuerdo con el teorema CAP, cualquier sistema distribuido solo puede garantizar dos de estos tres aspectos, por lo que nuestros servicios de cumplimiento sacrifican cierta consistencia para ser altamente disponibles y tolerantes a la partición. No obstante, nuestros servicios sacrificaron poco y encontraron mecanismos para lograr una buena consistencia con cambios arquitectónicos razonables que se explican a continuación.
El proceso para alcanzar una mayor fiabilidad es iterativo, con mediciones rigurosas que se combinan con un trabajo continuo para prevenir, encontrar, detectar y corregir defectos antes de que se produzcan incidentes. Nuestro equipo identificó un gran valor en las siguientes prácticas:
- Medición adecuada: crear una observabilidad completa en torno a cómo se entrega la calidad a los clientes y cómo las dependencias nos proporcionan calidad a nosotros.
- Anticipación proactiva: realizar actividades como revisiones arquitectónicas y evaluaciones de riesgos de las dependencias.
- Priorizar la corrección: prestar mayor atención a la resolución de los informes de incidentes para el servicio y las dependencias vinculadas a nuestro servicio.
Crear una mayor fiabilidad exige una cultura de calidad. Nuestro equipo ya estaba invirtiendo en el desarrollo orientado al rendimiento y sabe que el éxito de un proceso depende de su adopción. El equipo adoptó este proceso en su totalidad y aplicó las prácticas como norma. El siguiente diagrama destaca los componentes del proceso:

El poder de una medición adecuada
Antes de profundizar en las métricas, hay que hacer una breve aclaración sobre las mediciones del nivel de servicio.
- El SLO (objetivo de nivel de servicio) es el objetivo de fiabilidad al que aspira nuestro equipo (por ejemplo, el 99,999 %).
- El SLI (indicador de nivel de servicio) es la fiabilidad alcanzada en un periodo de tiempo determinado (por ejemplo, el 99,975 % el pasado mes de febrero).
- El SLA (Acuerdo de Nivel de Servicio) es la fiabilidad acordada que se debe ofrecer y que esperan nuestros usuarios en un periodo de tiempo determinado (por ejemplo, el 99,99 % a la semana).
El SLI debe reflejar la disponibilidad (sin respuestas no gestionadas o perdidas), la tolerancia a fallos (sin errores de servicio) y la calidad alcanzada (sin errores inesperados). Por lo tanto, definimos nuestro SLI como la «tasa de éxito» de las respuestas satisfactorias en comparación con el total de solicitudes enviadas a un servicio. Las respuestas satisfactorias son aquellas solicitudes que se enviaron a tiempo y en la forma adecuada, lo que significa que no se produjeron errores de conectividad, de servicio o inesperados.
Este SLI o «índice de éxito» se recopila desde el punto de vista de los consumidores (es decir, los clientes). La intención es medir la experiencia real de extremo a extremo que se ofrece a nuestros consumidores, de modo que podamos estar seguros de que se cumplen los SLA. No hacerlo crearía una falsa sensación de fiabilidad que ignoraría todas las preocupaciones relacionadas con la infraestructura para conectarnos con nuestros clientes. De forma similar al SLI de los consumidores, recopilamos el SLI de dependencia para realizar un seguimiento de cualquier riesgo potencial. En la práctica, todos los SLA de dependencia deben estar alineados con el SLA del servicio y existe una dependencia directa con ellos. El fallo de uno implica el fallo de todos. También hacemos un seguimiento y reportamos métricas del propio servicio (es decir, el servidor), pero esta no es la fuente práctica para una alta fiabilidad.
Además de los SLI, cada compilación recopila métricas de calidad que son reportadas por nuestro flujo de trabajo de CI. Esta práctica ayuda a aplicar con firmeza los controles de calidad (es decir, la cobertura del código) y a reportar otras métricas significativas, como el cumplimiento de los estándares de codificación y el análisis estático del código. Este tema ya se trató en otro artículo, «Creación de microservicios impulsados por el rendimiento». La observancia diligente de la calidad es fundamental cuando se habla de fiabilidad, ya que cuanto más invertimos en alcanzar puntuaciones excelentes, más seguros estamos de que el sistema no fallará en condiciones adversas.
Nuestro equipo cuenta con dos paneles de control. Uno ofrece una visión completa tanto del SLI de los consumidores como del SLI de las dependencias. El segundo muestra todas las métricas de calidad. Estamos trabajando para fusionar todo en un único panel de control, de modo que todos los aspectos que nos interesan queden consolidados y listos para ser reportados en cualquier periodo de tiempo dado.
Anticiparse a los fallos
Realizar revisiones arquitectónicas es una parte fundamental de la fiabilidad. En primer lugar, determinamos si existe redundancia y si el servicio tiene los medios para sobrevivir cuando las dependencias fallan. Más allá de las ideas típicas de replicación, la mayoría de nuestros servicios aplicaron técnicas mejoradas de hidratación de caché dual, estrategias de recuperación dual (como colas locales de conmutación por error) o estrategias de pérdida de datos (como el soporte transaccional). Estos temas son lo suficientemente amplios como para merecer otra entrada de blog, pero en última instancia la mejor recomendación es implementar ideas que tengan en cuenta escenarios de desastre y minimicen cualquier penalización en el rendimiento.
Otro aspecto importante a tener en cuenta es cualquier cosa que pueda mejorar la conectividad. Eso significa ser agresivos en cuanto a la baja latencia para los clientes y prepararlos para un tráfico muy alto utilizando técnicas de control de caché, sidecars y políticas de alto rendimiento para tiempos de espera, disyuntores de circuito y reintentos. Estas prácticas se aplican a cualquier cliente, incluyendo cachés, almacenes, colas y clientes interdependientes en HTTP y gRPC. También implica mejorar las señales de estado de los servicios y comprender que las comprobaciones de estado desempeñan un papel importante en toda la orquestación de contenedores. La mayoría de nuestros servicios envían mejores señales de degradación como parte de la retroalimentación de las comprobaciones de estado y verifican que todos los componentes críticos sean funcionales antes de enviar señales de estado.
Desglosar los servicios en partes críticas y no críticas ha resultado útil para centrarnos en la funcionalidad que más importa. Solíamos tener puntos de conexión exclusivos para administradores en el mismo servicio y, aunque no se usaban a menudo, afectaban a las métricas generales de latencia. Trasladarlos a su propio servicio tuvo un impacto positivo en todas las métricas.
La evaluación de riesgos de dependencia es una herramienta importante para identificar posibles problemas con las dependencias. Esto significa que identificamos las dependencias con un SLI bajo y solicitamos la alineación del SLA. Esas dependencias requieren una atención especial durante las etapas de integración, por lo que dedicamos tiempo adicional a comparar y probar si las nuevas dependencias están lo suficientemente maduras para nuestros planes. Un buen ejemplo es la adopción temprana que hicimos del almacenamiento como servicio de Roblox. La integración con este servicio requirió la creación de tickets de errores y reuniones de sincronización periódicas para comunicar los hallazgos y los comentarios. Todo este trabajo utiliza la etiqueta «fiabilidad», lo que nos permite identificar rápidamente su origen y sus prioridades. La caracterización se realizó con frecuencia hasta que tuvimos la confianza de que la nueva dependencia estaba lista para nosotros. Este trabajo adicional ayudó a llevar la dependencia al nivel de fiabilidad requerido que esperamos ofrecer, actuando juntos por un objetivo común.
Aportar estructura al caos
Nunca es deseable que se produzcan incidentes. Pero cuando ocurren, hay información significativa que recopilar y de la que aprender para ser más fiables. Nuestro equipo cuenta con un informe de incidentes propio que va más allá del típico informe a nivel de toda la empresa, por lo que nos centramos en todos los incidentes independientemente de la magnitud de su impacto. Identificamos la causa raíz y priorizamos todo el trabajo para mitigarla en el futuro. Como parte de este informe, recurrimos a otros equipos para resolver incidentes de dependencia de alta prioridad, hacemos un seguimiento de la resolución adecuada, reflexionamos y buscamos patrones que puedan aplicarse a nuestro caso.
El equipo elabora un informe mensual de fiabilidad por servicio que incluye todos los SLI explicados aquí, cualquier ticket que hayamos abierto por motivos de fiabilidad y cualquier posible incidente asociado al servicio. Estamos tan acostumbrados a generar estos informes que el siguiente paso natural es automatizar su extracción. Realizar esta actividad periódica es importante, y nos recuerda que la fiabilidad se supervisa y se tiene en cuenta constantemente en nuestro desarrollo.

Nuestra instrumentación incluye métricas personalizadas y alertas mejoradas para que se nos avise lo antes posible cuando se produzcan problemas conocidos y previstos. Todas las alertas, incluidas las falsas positivas, se revisan cada semana. En este punto, es importante pulir toda la documentación para que nuestros usuarios sepan qué esperar cuando se activan las alertas y cuando se producen errores, y así todos sepan qué hacer (por ejemplo, los manuales de procedimientos y las directrices de integración se armonizan y actualizan con frecuencia).
En última instancia, la adopción de la calidad en nuestra cultura es el factor más crítico y decisivo para alcanzar una mayor fiabilidad. Podemos observar cómo estas prácticas, aplicadas a nuestro trabajo diario, ya están dando sus frutos. Nuestro equipo está obsesionado con la fiabilidad y este es nuestro logro más importante. Hemos aumentado nuestra conciencia sobre el impacto que podrían tener los posibles defectos y cuándo podrían introducirse. Los servicios que han implementado estas prácticas han alcanzado de forma constante sus SLO y SLA. Los informes de fiabilidad que nos ayudan a hacer un seguimiento de todo el trabajo que hemos estado realizando son un testimonio del trabajo que ha realizado nuestro equipo y constituyen lecciones inestimables para informar e influir en otros equipos. Así es como la cultura de la fiabilidad afecta a todos los componentes de nuestra plataforma.
El camino hacia una mayor fiabilidad no es fácil, pero es necesario si se quiere construir una plataforma de confianza que reimagine la forma en que las personas se relacionan.
Alberto es ingeniero de software principal en el equipo de Identidad de Cuentas de Roblox. Lleva mucho tiempo en la industria de los videojuegos, con créditos en muchos títulos de videojuegos AAA y plataformas de redes sociales, con un fuerte enfoque en arquitecturas altamente escalables. Ahora está ayudando a Roblox a alcanzar el crecimiento y la madurez mediante la aplicación de las mejores prácticas de desarrollo.


