Cómo escalar de 1 a 100 usuarios

Muchas startups han pasado por esto: cada día se registran multitudes de nuevos usuarios y el equipo de desarrollo lucha por mantener el servicio en funcionamiento.

Es un buen problema, pero hay poca información clara en la web sobre cómo escalar cuidadosamente una aplicación web desde cero hasta cientos de miles de usuarios. Normalmente existen soluciones contra incendios o soluciones para cuellos de botella (y a menudo ambas). Por lo tanto, la gente utiliza técnicas bastante clichés para convertir su proyecto amateur en algo realmente serio.

Intentemos filtrar la información y anotar la fórmula básica. Vamos a ampliar nuestro nuevo sitio para compartir fotos, Graminsta, paso a paso, de 1 a 100 usuarios.

Anotemos qué acciones específicas se deben tomar cuando la audiencia aumente a 10, 100, 1000, 10 y 000 personas.

1 usuario: 1 máquina

Casi todas las aplicaciones, ya sea un sitio web o una aplicación móvil, tienen tres componentes clave:

  • API
  • base de datos
  • cliente (aplicación móvil en sí o sitio web)

La base de datos almacena datos persistentes. La API atiende solicitudes hacia y alrededor de estos datos. El cliente transmite datos al usuario.

Llegué a la conclusión de que es mucho más fácil hablar de escalar una aplicación si, desde un punto de vista arquitectónico, las entidades cliente y API están completamente separadas.

Cuando comenzamos a crear una aplicación por primera vez, los tres componentes se pueden ejecutar en el mismo servidor. En cierto modo, esto es similar a nuestro entorno de desarrollo: un ingeniero ejecuta la base de datos, la API y el cliente en la misma máquina.

En teoría, podríamos implementarlo en la nube en una única instancia de DigitalOcean Droplet o AWS EC2, como se muestra a continuación:
Cómo escalar de 1 a 100 usuarios
Dicho esto, si habrá más de un usuario en un sitio, casi siempre tiene sentido dedicar una capa de base de datos.

10 usuarios: mover la base de datos a un nivel separado

Dividir la base de datos en servicios administrados como Amazon RDS o Digital Ocean Managed Database nos será de gran utilidad durante mucho tiempo. Es un poco más caro que el autohospedaje en una sola máquina o en una instancia EC2, pero con estos servicios obtienes muchas extensiones útiles listas para usar que te serán útiles en el futuro: copia de seguridad multirregional, réplicas de lectura, automática. copias de seguridad y más.

Así es como se ve el sistema ahora:
Cómo escalar de 1 a 100 usuarios

100 usuarios: mover el cliente a un nivel separado

Afortunadamente, a nuestros primeros usuarios les gustó mucho nuestra aplicación. El tráfico se vuelve más estable, por lo que es hora de trasladar al cliente a un nivel separado. se debe notar que separación entidades es un aspecto clave en la creación de una aplicación escalable. A medida que una parte del sistema recibe más tráfico, podemos dividirla para controlar cómo escala el servicio en función de patrones de tráfico específicos.

Por eso me gusta pensar que el cliente está separado de la API. Esto hace que sea muy fácil pensar en desarrollar para múltiples plataformas: web, web móvil, iOS, Android, aplicaciones de escritorio, servicios de terceros, etc. Todos son solo clientes que utilizan la misma API.

Por ejemplo, ahora nuestros usuarios solicitan con mayor frecuencia lanzar una aplicación móvil. Si separa las entidades cliente y API, esto resulta más fácil.

Así es como se ve dicho sistema:

Cómo escalar de 1 a 100 usuarios

1000 usuarios: agregar balanceador de carga

Las cosas están mejorando. Los usuarios de Graminsta suben cada vez más fotos. El número de inscripciones también está creciendo. Nuestro único servidor API está teniendo dificultades para mantenerse al día con todo el tráfico. ¡Necesita más hierro!

El equilibrador de carga es un concepto muy poderoso. La idea clave es que colocamos un equilibrador de carga delante de la API y este distribuye el tráfico a instancias de servicio individuales. Así es como escalamos horizontalmente, lo que significa que agregamos más servidores con el mismo código, aumentando la cantidad de solicitudes que podemos procesar.

Vamos a colocar balanceadores de carga separados frente al cliente web y frente a la API. Esto significa que puede ejecutar varias instancias ejecutando código API y código de cliente web. El equilibrador de carga dirigirá las solicitudes al servidor que esté menos cargado.

Aquí obtenemos otra ventaja importante: la redundancia. Cuando una instancia falla (quizás sobrecargada o bloqueada), nos quedan otras que continúan respondiendo a las solicitudes entrantes. Si solo hubiera una instancia funcionando, en caso de falla, todo el sistema fallaría.

El equilibrador de carga también proporciona escalado automático. Podemos configurarlo para aumentar la cantidad de instancias antes de la carga máxima y disminuirla cuando todos los usuarios estén durmiendo.

Con un balanceador de carga, el nivel de API se puede escalar casi indefinidamente, simplemente agregando nuevas instancias a medida que aumenta la cantidad de solicitudes.

Cómo escalar de 1 a 100 usuarios

Nota. En este momento, nuestro sistema es muy similar a lo que ofrecen empresas PaaS como Heroku o Elastic Beanstalk en AWS de forma inmediata (razón por la cual son tan populares). Heroku coloca la base de datos en un host separado, administra un equilibrador de carga de escalado automático y le permite alojar el cliente web por separado de la API. Esta es una gran razón para usar Heroku para proyectos en etapa inicial o nuevas empresas: obtienes todos los servicios básicos listos para usar.

10 usuarios: CDN

Quizás deberíamos haberlo hecho desde el principio. Procesar solicitudes y aceptar nuevas fotos está empezando a ejercer demasiada presión sobre nuestros servidores.

En esta etapa, debe utilizar un servicio en la nube para almacenar contenido estático: imágenes, videos y mucho más (AWS S3 o Digital Ocean Spaces). En general, nuestra API debe evitar manejar cosas como servir imágenes y cargar imágenes en el servidor.

Otra ventaja del alojamiento en la nube es la CDN (AWS llama a este complemento Cloudfront, pero muchos proveedores de almacenamiento en la nube lo ofrecen listo para usar). La CDN almacena automáticamente en caché nuestras imágenes en varios centros de datos de todo el mundo.

Aunque nuestro centro de datos principal puede estar ubicado en Ohio, si alguien solicita una imagen de Japón, el proveedor de la nube hará una copia y la almacenará en su centro de datos japonés. La próxima persona que solicite esta imagen en Japón la recibirá mucho más rápido. Esto es importante cuando trabajamos con archivos grandes, como fotos o vídeos, que tardan mucho en descargarse y transmitirse por todo el planeta.

Cómo escalar de 1 a 100 usuarios

100 usuarios: escalando la capa de datos

CDN ha ayudado mucho: el tráfico está creciendo a toda velocidad. El famoso video blogger Mavid Mobrick acaba de registrarse con nosotros y publicó su “historia”, como dicen. Gracias al balanceador de carga, el uso de CPU y memoria en los servidores API se mantiene bajo (diez instancias API en ejecución), pero estamos empezando a tener muchos tiempos de espera en las solicitudes... ¿de dónde vienen estos retrasos?

Profundizando un poco en las métricas, vemos que la CPU en el servidor de la base de datos está cargada entre un 80% y un 90%. Estamos al límite.

Escalar la capa de datos es probablemente la parte más difícil de la ecuación. Los servidores API atienden solicitudes sin estado, por lo que simplemente agregamos más instancias de API. Nariz por mayoría las bases de datos no pueden hacer esto. Hablaremos sobre sistemas populares de gestión de bases de datos relacionales (PostgreSQL, MySQL, etc.).

almacenamiento en caché

Una de las formas más sencillas de aumentar el rendimiento de nuestra base de datos es introducir un nuevo componente: la capa de caché. El método de almacenamiento en caché más común es un almacén de registros de valores clave en memoria, como Redis o Memcached. La mayoría de las nubes tienen una versión administrada de estos servicios: Elasticache en AWS y Memorystore en Google Cloud.

Un caché es útil cuando un servicio realiza muchas llamadas repetidas a la base de datos para recuperar la misma información. Básicamente, accedemos a la base de datos solo una vez, almacenamos la información en el caché y no la volvemos a tocar.

Por ejemplo, en nuestro servicio Graminsta, cada vez que alguien visita la página de perfil de la estrella Mobrik, el servidor API consulta la base de datos en busca de información de su perfil. Esto sucede una y otra vez. Dado que la información del perfil de Mobrik no cambia con cada solicitud, es excelente para el almacenamiento en caché.

Almacenaremos en caché los resultados de la base de datos en Redis por clave. user:id con un período de validez de 30 segundos. Ahora, cuando alguien accede al perfil de Mobrik, primero verificamos Redis y, si los datos están allí, simplemente los transferimos directamente desde Redis. Ahora las solicitudes al perfil más popular del sitio prácticamente no cargan nuestra base de datos.

Otra ventaja de la mayoría de los servicios de almacenamiento en caché es que son más fáciles de escalar que los servidores de bases de datos. Redis tiene un modo Redis Cluster incorporado. Similar a un balanceador de carga1, le permite distribuir su caché de Redis en varias máquinas (en miles de servidores si es necesario).

Casi todas las aplicaciones a gran escala utilizan el almacenamiento en caché; es una parte absolutamente integral de una API rápida. Un procesamiento de consultas más rápido y un código más productivo son importantes, pero sin un caché es casi imposible escalar un servicio a millones de usuarios.

Leer réplicas

Cuando la cantidad de consultas a la base de datos ha aumentado considerablemente, una cosa más que podemos hacer es agregar réplicas de lectura en el sistema de administración de la base de datos. Con los servicios administrados descritos anteriormente, esto se puede hacer con un solo clic. La réplica de lectura permanecerá actualizada en la base de datos principal y estará disponible para declaraciones SELECT.

Aquí está nuestro sistema ahora:

Cómo escalar de 1 a 100 usuarios

Pasos siguientes

A medida que la aplicación siga escalando, continuaremos separando los servicios para escalarlos de forma independiente. Por ejemplo, si comenzamos a usar Websockets, entonces tiene sentido extraer el código de procesamiento de Websockets en un servicio separado. Podemos colocarlo en nuevas instancias detrás de nuestro propio balanceador de carga, que puede escalar hacia arriba y hacia abajo según las conexiones Websockets abiertas e independientemente de la cantidad de solicitudes HTTP.

También seguiremos luchando contra las restricciones a nivel de la base de datos. Es en esta etapa cuando llega el momento de estudiar la partición y fragmentación de la base de datos. Ambos enfoques requieren una sobrecarga adicional, pero permiten escalar la base de datos casi indefinidamente.

También queremos instalar un servicio de seguimiento y análisis como New Relic o Datadog. Esto le ayudará a identificar consultas lentas y comprender dónde es necesario mejorar. A medida que escalamos, queremos centrarnos en encontrar obstáculos y eliminarlos, a menudo utilizando algunas de las ideas de las secciones anteriores.

fuentes

Esta publicación está inspirada en uno de mis publicaciones favoritas sobre alta escalabilidad. Quería hacer el artículo un poco más específico para las etapas iniciales de los proyectos y desvincularlo de un proveedor. No dejes de leer si estás interesado en este tema.

Notas al pie

  1. Aunque es similar en términos de distribución de carga entre múltiples instancias, la implementación subyacente de un clúster de Redis es muy diferente de la de un balanceador de carga. [devolver]

Cómo escalar de 1 a 100 usuarios

Fuente: habr.com

Añadir un comentario