Ahora que sabes como tener a Django ejecutando en un servidor simple, veamos como puedes escalar una instalación Django. Esta sección explica como puede escalar un sitio desde un servidor único a un cluster de gran escala que pueda servir millones de hits por hora.
Es importante notar, sin embargo, que cada sitio grande es grande de diferentes formas, por lo que escalar es cualquier cosa menos una operación de una solución única para todos los casos. La siguiente cobertura debe ser suficiente para mostrar el principio general, y cuando sea posible, trataremos de señalar donde se puedan elegir distintas opciones.
Primero, haremos una buena presuposición, y hablaremos exclusivamente acerca de escalamiento bajo Apache y mod_python. A pesar de que conocemos vario casos exitosos de desarrollos FastCGI medios y grandes, estamos mucho más familiarizados con Apache.
20.5.1. Ejecutando en un Servidor Único
La mayoría de los sitios empiezan ejecutando en un servidor único, con una arquitectura que se ve como en la Figura 20-1.
Esto funciona bien para sitios pequeños y medianos, y es relativamente barato — puedes instalar un servidor único diseñado para Django por menos de 3,000 dólares.
Sin embargo, a medida que el tráfico se incremente, caerás rápidamente en contención de recursos entre las diferentes piezas de software. Los servidores de base de datos y los servidores Web adoran tener el servidor entero para ellos, y cuando corren en el mismo servidos siempre terminan "peleando" por los mismos recursos (RAM, CPU) que prefieren monopolizar.
Esto se resuelve fácilmente moviendo el servidor de base de datos a una segunda máquina, como se explica en la siguiente sección.
20.5.2. Separando el Servidor de Bases de Datos
En lo que tiene que ver con Django, el proceso de separar el servidor de bases
de datos es extremadamente sencillo: simplemente necesitas cambiar la
configuración de DATABASE_HOST
a la IP o nombre DNS de tu servidor.
Probablemente sea una buena idea usar la IP si es posible, ya que depender de
la DNS para la conexión entre el servidor Web y el servidor de bases de datos
no se recomienda.
Con un servidor de base de datos separado, nuestra arquitectura ahora se ve como en la Figura 20-2.
Aquí es donde empezamos a movernos hacia lo que normalmente se llama arquitectura n-tier. No te asustes por la terminología — sólo se refiere al hecho de que diferentes "tiers" de la pila Web separadas en diferentes máquinas físicas.
A esta altura, si anticipas que en algún momento vas a necesitar crecer más allá de un servidor de base de datos único, probablemente sea una buena idea empezar a pensar en pooling de conexiones y/o replicación de bases de datos. Desafortunadamente, no hay suficiente espacio para hacerle justicia a estos temas en este libro, así que vas a necesitar consultar la documentación y/o a la comunidad de tu base de datos para más información.
20.5.3. Ejecutando un Servidor de Medios Separado
Aún tenemos un gran problema por delante desde la configuración del servidor único: el servicio de medios desde la misma caja que maneja el contenido dinámico.
Estas dos actividades tienen su mejor rendimiento bajo distintas circunstancias, y encerrándolas en la misma caja terminarás con que ninguna de las dos tendrá particularmente buen rendimiento. Así que el siguiente paso es separar los medios — esto es, todo lo que no es generado por una vista de Django — a un servidor dedicado (ver Figura 20-3).
Idealmente, este servidor de medios debería correr un servidor Web desnudo, optimizado para la entrega de medios estáticos. lighttpd y tux (http://www.djangoproject.com/r/tux/) son dos excelentes elecciones aquí, pero un servidor Apache bien 'pelado' también puede funcionar.
Para sitios pesados en contenidos estáticos (fotos, videos, etc.), moverse a un servidor de medios separado es doblemente importante y debería ser el primer paso en el escalamiento hacia arriba.
De todos modos, este paso puede ser un poco delicado. El administrador de
Django necesita poder escribir medios 'subidos' en el servidor de medios. (la
configuración de MEDIA_ROOT
controla donde se escriben estos medios). Si un
medio habita en otro servidor, de todas formas necesitas organizar una forma de
que esa escritura se pueda hacer a través de la red.
La manera más fácil de hacer esto es usar el NFS para montar los directorios de
medios del servidor de medios en el servidor Web (o los servidores Web). Si los
montas en la misma ubicación apuntada por MEDIA_ROOT
, el uploading de
medios Simplemente Funciona.
20.5.4. Implementando Balance de Carga y Redundancia
A esta altura, ya hemos separado las cosas todo lo posible. Esta configuración de tres servers debería manejar una cantidad muy grande de tráfico — nosotros servimos alrededor de 10 millones de hits por día con una arquitectura de este tipo — así que si creces más allá, necesitarás empezar a agregar redundancia.
En realidad, esto es algo bueno. Una mirada a la Figura 20-3 te permitirá ver que si falla aunque sea uno solo de los servidores, el sitio entero se cae. Así que a medida que agregas servidores redundantes, no sólo incrementas capacidad, sino también confiabilidad.
Para este ejemplo, asumamos que el primero que se ve superado en capacidad es el servidor Web. Es fácil tener múltiples copias de un sitio Django ejecutando en diferente hardware — simplemente copia el código en varias máquinas, y inicia Apache en cada una de ellas.
Sin embargo, necesitas otra pieza de software para distribuir el tráfico entre los servidores: un balanceador de carga. Puedes comprar balanceadores de carga por hardware caros y propietarios, pero existen algunos balanceadores de carga por software de alta calidad que son open source.
mod_proxy
de Apache es una opción, pero hemos encontrado que Perlbal
(http://www.djangoproject.com/r/perlbal/) es simplemente fantástico. Es un
balanceador de carga y proxy inverso escrito por las mismas personas que
escribieron memcached
(ver Capítulo 13
_).
Nota Puedes realizar este mismo paso distribución y balance de carga separando los servidores Web front-end y los procesos FastCGI back-end en diferentes máquinas. El servidor front-end se convierte esencialmente en el balanceador de carga, y los procesos FastCGI back-end reemplaza a los servidores Apache/mod_python/Django.
Con los servidores Web en cluster, nuestra arquitectura en evolución empieza a verse más compleja, como se ve en la Figura 20-4.
Observar que en el diagrama nos referimos a los servidores web como "el cluster" para indicar que el número de servidores básicamente es variable. Una vez que tienes un balanceador de carga, puedes agregar y eliminar servidores sin afectar al sitio o aplicación web.
20.5.5. Vamos a lo grande
En este punto, los siguientes pasos son derivaciones del último:
- A medida que necesites más rendimiento en la base de datos, necesitarás agregar servidores de base de datos relicados. MySQL tiene replicación incorporada; los usuarios de PostgreSQL deberían mirar a Slony (http://www.djangoproject.com/r/slony/) y pgpool (http://www.djangoproject.com/r/pgpool/) para replicación y pooling de conexiones, respectivamente.
- Si un solo balanceador de carga no es suficiente, puedes agregar más máquinas balanceadoras de carga y distribuir entre ellas usando DNS round-robin.
- Si un servidor único de medios no es suficiente, puedes agregar más servidores de medios y distribuir la carga con tu cluster de balanceadores de carga.
- Si necesitas más almacenamiento cache, puedes agregar servidores de cache dedicados.
- En cualquier etapa, si un cluster no tiene buen rendimiento, puedes agregar más servidores al cluster.
Después de algunas de estas iteraciones, una arquitectura de gran escala debe verse como en la Figura 20-5.
A pesar de que mostramos solo dos o tres servidores en cada nivel, no hay un límite fundamental a cuantos puedes agregar.
Una vez que haz llegado a este nivel, te quedan pocas opciones. El Apéndice A tiene alguna información proveniente de desarrolladores responsables de algunas instalaciones Django de gran escala. Si estás planificando un sitio Django de alto tráfico, es una lectura recomendada.