Idiomas: English · Nederlands · Deutsch · Español · Français · Italiano · Português · Papiamentu · Frysk

Índice / Artículos / Diseño de aplicaciones escalables sin magia

Diseño de aplicaciones escalables sin magia

Cómo aprovechar la potencia del cliente para lograr alto rendimiento con muchos usuarios

Publicado
Actualizado
(creado )
Escrito por
Willem L. Middelkoop
Temas
nube · datos · diseño · tutorial · iOS · lemmid-store · programación · servidor · smartphone · web · diseño web
Versión humana de este artículo
https://willem.com/es/2020-05-11_diseno-de-aplicaciones-escalables-sin-magia/
English
Scalable application design without magic
Nederlands
Schaalbaar applicatieontwerp zonder magie
Deutsch
Skalierbares Anwendungsdesign ohne Magie
Français
Concevoir une application scalable sans magie
Italiano
Progettare applicazioni scalabili senza magia
Português
Design de aplicações escaláveis sem magia
Papiamentu
Desèño di aplikashon eskalabel sin magia
Frysk
Skaalbere applikaasje-ûntwerp sûnder magy
Idiomas
Traducido del original en inglés por un modelo de lenguaje en dos pasadas (traducción y corrección) con un glosario y un corrector ortográfico; aún no revisado por un hablante nativo.

Resumen

Para la app de pedidos de comida online que estoy desarrollando, necesitaba diseñar una infraestructura backend escalable capaz de atender a muchísimos usuarios a la vez. La escalabilidad se considera un problema difícil. A menudo se presenta como algo mágico, obra de empresas millonarias con herramientas secretas. Pero la magia no existe... ¿o sí?

Texto completo

¿Qué es la escalabilidad?

Si estás desarrollando una app, seguramente empiezas con muy poco. Solo unos pocos usuarios (o solo tú, el desarrollador) trabajando con ella. Todo va de maravilla: la app funciona bien, es rápida y no hay problemas. (¡disfruta de esta sensación!)

Un usuario interactuando con un servidor
Un usuario interactuando con un servidor

En este primer escenario, pequeño, el único servidor que ejecuta la app puede atender al usuario que interactúa con ella. Cada vez que el usuario toca o hace clic en un botón, el servidor hace algo de trabajo. Si programas bien, esas cargas de trabajo se pueden optimizar en pequeñas tareas eficientes. Hacerlo así es un ejemplo típico de arquitectura de software monolítica.

Aunque tu proyecto o tu app sean bastante pequeños, en algún momento puede llegar una avalancha de usuarios. Si tu sistema no soporta cargas altas, tiene muchas probabilidades de fallar.

Un servidor con mucha carga atendiendo a varios usuarios a la vez
Un servidor con mucha carga atendiendo a varios usuarios a la vez

Con el diseño monolítico de la app, todos los usuarios interactúan con el mismo servidor. Toda su actividad (toques, clics, datos introducidos) la gestiona ese servidor. Con más carga, tiene que trabajar mucho más. En algún momento notarás que todo va más lento porque el servidor no puede con tanto trabajo. Eso significa que tu app no escala bien; dicho de otro modo: estás en un buen lío.

Fallar en el 'momento supremo'

No escalar bien es un problema enorme que nadie debería subestimar. La mayoría de las apps (y sus modelos de negocio) dependen de grandes volúmenes con pocos ingresos por usuario. Si quieres que tu app sea un éxito (económico), tienes que asegurarte de que funcione bien cuando el tráfico se dispare de golpe. Si tu app se cae justo cuando de repente consigue la atención de las masas, perderás una oportunidad 'única en la vida' de crecimiento (orgánico).

De alguna manera, diseñar para la escalabilidad es como llevar el cinturón abrochado en tu cohete casero con motores experimentales. Nunca sabes exactamente cuándo se encenderá, pero cuando lo haga, más te vale ir bien sujeto (¡y disfrutar del viaje!).

Formas habituales de lograr escalabilidad

Se ha escrito mucho sobre cómo crear apps escalables. Las formas habituales de mejorar la escalabilidad son:

  • Aumentar la capacidad del servidor: más memoria, más potencia de CPU, más almacenamiento. Funciona, pero solo te llevará 'hasta cierto punto'.
  • Añadir más servidores: en lugar de un único servidor que hace de cuello de botella, puedes añadir más servidores que se repartan el trabajo. Es más fácil decirlo que hacerlo, porque exige balanceo de carga y compartir datos, y eso puede ser complicado (por ejemplo, si tienes un contador de pedidos y dos servidores contando, ¿cuál decide el número siguiente?).
  • Optimizar el código: ¡usa las herramientas adecuadas! Elige un lenguaje de programación orientado al rendimiento y un software de servidor a la altura. Échale un vistazo a la programación funcional, para que tu código se ejecute de forma asíncrona en varios núcleos. Hazlo sin estado. Mídelo. Optimízalo. Cada milisegundo que ganas en una sola petición se acumula rápido cuando manejas grandes volúmenes.
  • Usar la base de datos y separarla del servidor de la aplicación: si usas una base de datos, ¡aprovecha su potencia! Saca partido de la caché de consultas, los índices y las capacidades de búsqueda. La mayoría de las bases de datos ofrecen opciones de clústeres a prueba de bombas; no intentes reinventar la rueda que otros ya han perfeccionado.

Lo mejor que puedes hacer es tener en cuenta todas estas opciones. Aunque no vayas a añadir más servidores ahora mismo, escribe tu código para poder hacerlo más adelante. Medir y optimizar tu código debería ser parte integral de tu trabajo, no algo que se hace a última hora.

Aprovechar la potencia de cálculo del cliente

Cuando has considerado todas las formas habituales de lograr escalabilidad, queda "una cosa más".

Los smartphones (y las tabletas y los PC) se han vuelto más potentes con los años (imagen: Apple)
Los smartphones (y las tabletas y los PC) se han vuelto más potentes con los años (imagen: Apple)

Pocos desarrolladores piensan en esto: ¡el problema de escalabilidad contiene la solución! Cuando tienes 1000 usuarios, tienes 1000 ordenadores con CPU potentes y mucha memoria. Los ordenadores y los smartphones modernos son cada vez más capaces.

Solo tienes que encontrar la manera de aprovechar la potencia de cálculo del cliente. Puede sonar a algo malvado (usar la potencia de cálculo del usuario), pero le dará una experiencia mucho mejor y más rápida. Lo mejor es que su potencia de cálculo se gasta en su fantástica experiencia, y de paso resuelve tu problema de escalabilidad como un feliz efecto secundario.

Aprovechar el dispositivo del usuario: su móvil hace casi todo el trabajo que antes hacía el servidor
Aprovechar el dispositivo del usuario: su móvil hace casi todo el trabajo que antes hacía el servidor

Al aprovechar la potencia del usuario, reduces el trabajo que tiene que hacer el servidor. En lugar de que el servidor haga un poco de trabajo cada vez que el usuario toca o hace clic en un botón, ahora casi todo ese trabajo lo hace el dispositivo del usuario. Es más eficiente que comunicarse con un servidor por Wi-Fi o 4G (ahorra batería y tiempo).

Hay que pensarlo un poco de otra manera, pero este principio también se puede aplicar a las aplicaciones web. En lugar de gestionarlo todo en el servidor, puedes hacer mucho trabajo en el cliente. Cosas como buscar, explorar, filtrar, navegar e incluso añadir productos al carrito se pueden hacer con JavaScript del lado del cliente. Tú, querido desarrollador, tienes que buscar la forma de lograrlo, pero si lo consigues tendrás una escalabilidad casi infinita al alcance de la mano.

En la práctica: la app de pedidos de comida

Para la app de pedidos de comida busqué formas de aprovechar la potencia del cliente para conseguir un alto rendimiento. El principal reto de los pedidos a domicilio y para llevar es que tienen su pico a la hora de cenar. Mucha gente usa la app más o menos a la vez, y eso es una receta para tener problemas de escalabilidad.

Pedir comida online
Pedir comida online

Si piensas en pedir comida online, puedes dividir todo el proceso en pasos más pequeños:

  • 1) Abrir la página: cargar la app o la página
  • 2) Explorar las distintas opciones: ver la lista de productos, sus descripciones, precios, fotos, etc.
  • 3) Buscar algo concreto: buscar por categoría, nombre del producto, etc.
  • 4) Elegir un producto: añadirlo al pedido
  • 5) Personalizar un producto: elegir una salsa, un acompañamiento, un topping, etc.
  • 6) Introducir tus datos: nombre, número de teléfono, datos de entrega, etc.
  • 7) Pagar el pedido: elegir un método de pago, conectar con tu banco o tu tarjeta de crédito
  • 8) Cerrar la app

La mayoría de estos pasos se pueden programar de modo que el servidor no haga falta. Solo el paso 1 (cargar) y el paso 7 (pagar) requieren contacto con la infraestructura backend. Es importante tener presente que los pasos 2 a 5 se repiten varias veces, porque lo normal es que los usuarios añadan varios productos al pedido.

Separar el trabajo restante del servidor: servir productos y gestionar pedidos
Separar el trabajo restante del servidor: servir productos y gestionar pedidos

Si separas el trabajo restante por tareas, el software se puede optimizar aún más. El "servidor de productos" está optimizado para servir contenido estático (textos, precios, imágenes) con el que el cliente construye la experiencia de explorar productos. Este tipo de servidor se puede optimizar a fondo con caché, HTTP/2, compresión, etc.

Solo los usuarios que completan el proceso de pedido pasan al "servidor de pedidos", que gestiona el pago. Este se conecta con el proveedor de pagos. Cuando se completa un pago, el proveedor de pagos contacta con el servidor de pedidos para informarle del estado del pago. Es algo sobre lo que quieres tener control total (en el servidor), como cuando diseñé un sistema de pago hace un tiempo. La carga que le queda al "servidor de pedidos" es mucho menor, porque no todo el mundo hace un pedido y buena parte del procesamiento se puede hacer en segundo plano.

Gestionar mucho tráfico con computación distribuida
Gestionar mucho tráfico con computación distribuida

Para maximizar la escalabilidad puedes añadir fácilmente varios servidores (o usar una red de distribución de contenido) que sirvan el contenido estático. En la app de pedidos de comida uso un "servidor de productos" distinto para cada restaurante. Eso da un alto rendimiento y reduce los tiempos de carga. La gente nota que es rápido, algunos no se creen que sea tecnología web: es casi mágico.

Conclusión

Se puede diseñar una aplicación escalable sin magia ni presupuestos millonarios. Solo hay que pensarlo bien y buscar las oportunidades que aparecen junto con los retos.

El problema contiene la solución. Tener muchos usuarios a la vez no es solo un problema: ¡cada uno trae su propia potencia de cálculo, y esa es la solución! Solo tienes que usarla.

Formatos legibles por máquinas de esta página