Aplicaciones para “millones” de usuarios

El tema de sistemas web de alta disponibilidad me llama la atención. Especialmente porque por algún motivo el hosting siempre es un tema importante para mis clientes. No importa de que tamaño sea el proyecto en el que trabajo o que tan importante sea que no se interrumpa su servicio, todos los clientes preguntan mucho sobre las medidas que tomo cuando les ofrezco hacer hosting de sus apps. Para mi esto nunca ha sido un problema. Tal vez porque nunca he manejado un site con millones de visitas diarias, pero de todos modos me interesa aprender. Hay que estar listo para cuando inevitablemente me haga falta saber de esto.

La meta este post es documentar lo que creo tendría que hacer cuando un app ya no pueda funcionar en un solo server y requiera un upgrade al hardware, tan grande que sea más economico añadir otro server.

Este plan está basado en toda la información que he recopilado hasta hoy durante los pasados tres o cuatro años que llevo leyendo de este tema.


Primer Paso

Separar el application server y el database server. Cuando un web app comienza a ser muy lento regularmente es por culpa de la base de datos. Una vez los indices de la base de datos no caben en la memoria del server, todo se pone lento. La base de datos se ve obligada a leer el disco duro y esto es mucho más lento que si tiene la información en RAM.

Así que el primer paso sería añadir un servidor de base de datos dedicado con todo el RAM que haga sentido comparar (lo más que pueda pagar). Para hacer esto es necesario interrumpir el servicio, en lo que se importa la data a la nueva base de datos y se aplican los cambios al app para que use la base de datos del nuevo server.


Segundo Paso

Una vez un solo server de base de datos no sea suficiente es hora de pensar en añadir por lo menos uno o dos más. En este momento hay que analizar que está pasando con la aplicación y ver que es más importante leer de la base de datos o escribir a la base de datos. Muchos de los apps más comunes como un blog, un site de noticias, un foro, un site tipo digg, son primordialmente lecturas a la base de datos. En un caso como este la respuesta sería hacer “replication”. En pocas palabras, como funciona es que se establece que un servidor es el “master” (amo) y otro es “slave” (esclavo). El servidor master envía todos los cambios que hace a su slave y de esta manera ambos servidores tienen la misma data todo el tiempo, aunque con un pequeño retraso.

Una vez se tiene este arreglo de servidores hay que actualizar el app para que escriba solo en el master y lea solo del slave o de ambos servidores. Si va a leer de ambos servidores es necesario establecer algún tipo de mecánica para mantener las lecturas balanceadas entre ambas maquinas. Comúnmente a esta mecánica se le conoce como “round robin”, se alternan las peticiones de lectura entre los servidores para mantener el balance.


Tercer Paso

Si no es suficiente con dos bases de datos lo próximo sería hacer un array (multi-master) de bases de datos. El acercamiento más simple aunque no se si el más efectivo es hacer “replication” con multiples masters. Ejemplo.

En esta configuración todas las bases de datos son tanto masters como slaves. En una configuración como esta hay que hacer cambios a nuestro app para poder manejar el leer y escribir a varios servidores, pero no debe ser muy distinto a lo que ya hicimos antes.


Cuarto Paso

Añadir servidores para el app. Por lo que he leido esto es lo último que necesita ayuda. El app ya sea PHP, Ruby, Python, Java o cualquier otro lenguaje casi siempre es lo menos que se ve afectado cuando hay mucho tráfico. Cuando se llega a este punto casi siempre son buenas noticias, porque nuestro servicio le gusta a mucha gente.

Lo que debemos hacer es asegurarnos que nuestra aplicación no usa sesiones (sessions) y si los usa que es lo más probable, deben ser una implementación de sesiones que use la base de datos para almacenar la información. Si nuestras sesiones usan las nativas de lenguajes como PHP estas se guardan en el filesystem del server y esto no nos ayuda cuando tenemos más de un server y no podemos garantizar que todos las peticiones del usuario sen envíen al mismo.

Por suerte casi todos los frameworks modernos (CodeIgniter, Rails, Django) tienen support para sesiones en la base de datos.

Ahora lo que necesitamos es un Load Balancer. Esto es un server dedicado con una aplicación como haproxy que se encargar de balancear todos los requests que llegan a un dominio entre varios servidores. Cada uno de estos servidores con nuestro app.

Cuando me toque hacer esto no creo que use algo como haproxy. En estos días he jugado con el Load Balancer de Amazon EC2 y quedé muy impresionado con lo fácil que es de poner a funcionar. Con 5 o 6 clicks ya tenía una dirección pública en el web que se encargaba de enviar mis peticiones a múltiples servidores, sin problemas.


Quinto Paso

Aquí no voy a abundar mucho. Lo que se necesita hacer es añadir mas bases de datos al array, añadir más app servers y añadir otro load balancer. Para poder tener un domain que apunte a esos dos load balancers necesitamos un servicio de DNS que pueda hacer round-robin de los IP de esos load balancers.


Sexto Paso

Si todavía tienes necesidad de seguir creciendo este sistema y si no lo has hecho antes, es momento de buscar ayuda Contrata a un administrador de sistemas competente con experiencia en estas tecnologías. Un IT manager experto en Exchange no te va a ayudar mucho aquí.

¿Se me queda algo? ¿Donde metí las patas?