La arquitectura detrás del software de navegación del Apolo: Lecciones de 1969 para tu microservicio actual

Hey devs, en esta ocasión hablaré de mi tema favorito: la ingeniería en el espacio, arrancamos!

Hoy en día nos quejamos si nuestro contenedor Docker no tiene asignados al menos 2 GB de RAM o si el microservicio tarda más de 200 milisegundos en arrancar. Ahora, viajemos mentalmente a 1969: la computadora de navegación del Apolo 11 (AGC) tenía apenas 4 kilobytes de memoria RAM y unos 72 kilobytes de memoria ROM. Su procesador corría a poco más de 1 MHz.

Con esa capacidad de cómputo (millones de veces menor que la del teléfono con el que estás leyendo esto), Margaret Hamilton y su equipo en el MIT lograron llevar al ser humano a la Luna.

No es casualidad que Margaret Hamilton popularizara el término Software Engineering. El software dejó de ser visto como un simple complemento del hardware para convertirse en un componente cuya calidad podía determinar el éxito o el fracaso de toda una misión.

¿Cómo lo hicieron sin que el sistema colapsara? Creando conceptos de arquitectura de software que hoy seguimos utilizando, pero que a menudo olvidamos simplificar.

El problema: Sobrecarga en el mar de la tranquilidad

El 20 de julio de 1969, a pocos minutos de que el módulo lunar Eagle tocara la superficie, saltaron las alarmas en la cabina: errores 1201 y 1202.

El radar de acoplamiento, que dicho sea de paso, no era necesario durante el aterrizaje, se había dejado encendido en un modo incorrecto, generando una gran cantidad de interrupciones para la computadora de navegación. El procesador terminó saturado y el planificador detectó que ya no podía completar todas las tareas dentro del tiempo disponible.

En un sistema moderno mal diseñado, esto podría traducirse en una aplicación bloqueada, una cascada de errores o incluso una caída completa del servicio. En la Luna, significaba algo mucho más serio: el riesgo de abortar la misión. Sin embargo, la computadora no se colgó, nop, hizo algo mucho más inteligente: priorizó.

La solución: Arquitectura orientada a prioridades (el "Exec")

El software de la AGC utilizaba un sistema ejecutivo en tiempo real llamado Exec, encargado de planificar las distintas tareas según su prioridad. En lugar de intentar ejecutar todo indiscriminadamente, el sistema siempre daba preferencia a las operaciones más críticas.

Algunas tareas tenían prioridad absoluta:

  • Calcular la trayectoria de aterrizaje.
  • Controlar los motores de descenso.
  • Mantener la navegación de la nave.

Mientras tanto, otras tareas, como seguir procesando la información del radar de acoplamiento, podían esperar.

Cuando ocurrió la sobrecarga, el Exec detectó que no podía atender todas las tareas a tiempo. En lugar de bloquearse, descartó trabajo no esencial, reinició determinadas tareas de baja prioridad y reservó el tiempo de CPU para aquellas indispensables para completar el aterrizaje. Gracias a esa decisión de diseño, las alarmas 1201 y 1202 informaban a los astronautas de la sobrecarga, pero el sistema seguía funcionando correctamente y la misión pudo continuar.

Lecciones para el backend moderno

Mirar al pasado nos da una buena dosis de humildad a los desarrolladores backend actuales. De la hazaña del MIT podemos extraer, en mi opinión, al menos tres principios que siguen plenamente vigentes.

Tolerancia a fallos mediante degradación elegante (Graceful Degradation)

Si tu API de pagos comienza a saturarse, ¿debe caer todo el sistema o conviene desactivar temporalmente funciones secundarias (como las recomendaciones o el historial de búsquedas) para mantener operativo el flujo principal? Tú sabes la respuesta dev.

Defiende tus recursos

La AGC trabajaba con recursos extremadamente limitados y debía decidir cuidadosamente qué tareas conservar y cuáles descartar cuando el sistema alcanzaba su límite. Diseña tus servicios con límites claros mediante rate limiting, Bulkheads, colas con tamaño máximo y mecanismos de backpressure para evitar que una avalancha de peticiones termine derribando toda la aplicación.

La simplicidad no es falta de características, es ingeniería

Esto va de acuerdo con mi artículo anterior. Léelo, crack.

El software del Apolo fue escrito principalmente en lenguaje ensamblador y probado exhaustivamente en simuladores antes de despegar. Evidentemente, los problemas de aquella época eran muy distintos a los de una aplicación distribuida moderna, pero las enormes restricciones obligaron al equipo a escribir un software extraordinariamente simple, eficiente y predecible.

En resumen...

La próxima vez que pienses en desplegar un enorme clúster de Kubernetes o incorporar tres tecnologías de mensajería distintas para resolver un problema que quizá puedas solucionar gestionando mejor las colas, las prioridades o la presión sobre tus recursos, acuérdate del Apolo 11 y todo lo genial que hizo con los recursos que tenía a mano.

La mejor arquitectura no siempre es la que añade más componentes. Muy a menudo, es la que sabe qué trabajo puede dejar de hacer para que lo realmente importante nunca deje de funcionar.

Comparte este artículo si te ha gustado, compártelo con todo tu equipo de ingeniería 💪

Créditos de imagen de portada: Foto de NASA en Unsplash

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *