domingo, 20 de noviembre de 2011

Cluster de alta disponibilidad y balanceo de carga Apache + PHP + MySQL con sólo dos máquinas (Primera parte)

Introducción

Tras poner en producción un cluster de estas características para mi empresa, decido publicar una serie de artículos que ilustrarán cómo montar una arquitectura similar y para que todo el mundo que lo desee pueda disfrutar de un aumento de rendimiento en sus aplicaciones LAMP.

Lo ideal sería separar las máquinas que ejecutan PHP y Apache de las máquinas que almacenan las páginas web y el servidor de bases de datos. Posiblemente haciendo esto se solucionen la mayoría de problemas de rendimiento que tienen la gran mayoría de las instalaciones LAMP.

¿Cómo mejoro el rendimiento en mi instalación LAMP actual?

Antes de decidir montar un cluster de alta disponibilidad y balanceo de carga tenemos que tener muy claro que no podemos sacarle mayor rendimiento a la arquitectura actual. Para ello debemos hacernos las siguientes preguntas:

¿Dónde tenemos el cuello de botella en nuestra instalación hardware?

Dependiendo de dónde esté el cuello de botella (aquél elemento que ralentiza en mayor grado la ejecución de nuestros scripts) debemos aumentar el hardware de nuestros servidores para mejorar lo máximo posible el problema.

Podemos destacar los siguientes cuellos de botella hardware:

  • CPU: Que se esté usando la CPU al 100% (nice + idle + user + system) en nuestra máquina es una buena señal ya que significa que tenemos bien dimensionada nuestra máquina en memoria y disco duro y que si no es capaz de procesar un mayor número de peticiones es por falta de potencia de procesamiento. También puede ser un indicador de que nuestros scripts PHP no están optimizados todo lo que debieran. En algunos casos es posible aumentar la CPU sin tener que cambiar el resto del hardware (placa madre, memoria, etc), pero no siempre es así. El balanceo de carga que propondremos en esta arquitectura solucionará este problema drásticamente permitiendo, a su vez, escalar tanto como deseemos la potencia de cálculo del cluster cada vez que sea necesario.
  • Memoria: Cuando los procesos agotan la memoria RAM y empiezan a hacer uso del área de intercambio el rendimiento general del servidor decae radicalmente debido a que cualquier tipo de entrada salida (búsqueda de una imagen desde el servidor web, búsqueda de datos desde el servidor MySQL, acceso a datos en disco desde un script PHP, etc) se ve ralentizado por las constantes entradas y salidas de datos de memoria a intercambio y viceversa. Generalmente podemos saber cuándo está un servidor perdiendo rendimiento debido a este motivo observando que la memoria RAM libre y la caché de disco es muy baja y, sin embargo, tanto el uso de memoria de intercambio ha aumentado como el número de procesos esperando la finalización de un proceso de entrada/salida (iowait). Aumentar la memoria RAM de un servidor suele ser mucho más sencillo y barato que aumentar la RAM y deberemos hacerlo tanto como podamos antes de montar el clustar. Usar un cluster de balanceo de carga permitirá repartir el consumo de RAM de algunos procesos PHP mientras que otros usos de memoria RAM no se podrán reducir o evitar (caché de índices, consultas, etc del servidor MySQL, por ejemplo).
  • Disco duro: Hay que tener en cuenta que una aplicación que haga uso intensivo del almacenamiento (cálculo de la firma MD5, creación o lectura de un archivo muy grande, etc) podría provocar la ralentización de todo el sistema de manera similar a cuando entramos en paginación. La diferencia radica en que un proceso que haga uso intensivo de disco tendrá un tiempo de ejecución acotado (si nuestra aplicación está bien diseñada) mientras que un estado de paginación por falta de memoria RAM se producirá durante largos periodos de tiempo. Hay que procurar que se use lo mínimo posible de manera intensiva el almacenamiento compartido (afectará al rendimiento del cluster). Como cada servidor MySQL funciona con su réplica de datos local, un uso intensivo puntual de una de las máquinas no afectará a la otra. Para mejorar el rendimiento de E/S de datos se recomienda el uso de discos de estado sólido (SSD) o el uso de RAID 5 para mejorar sensiblemente la tasa de transferencia a la vez que se agrega redundancia (es importante mantener a salvo los datos en caso de fallo de uno de los discos).

¿Qué arquitectura de cluster vamos a montar?

El objetivo de este pequeño proyecto es ofrecer los servicios de procesamiento, almacenamiento, bases de datos, etc de manera autónoma en sólo dos máquinas proporcionando alta disponibilidad sin hacer uso de servicios externos:
  • No disponemos de almacenamiento SAN (Network Attached Storage).
  • No podemos tener máquinas separadas para el servidor MySQL, servidor HTTP, servidor de archivos, etc.
Esto nos deja la siguiente propuesta de arquitectura:
  • Gestor de Recursos del Cluster (CRM): Usaremos heartbeat y pacemaker. Nos proporcionará monitorización de los recursos para mover la IP virtual de servicio a aquella máquina que esté funcional.
  • Servidor web: Usaremos un servidor apache en cada máquina sirviendo páginas web con soporte para ejecutar scripts PHP.
  • Acelerador web: Usaremos squid como acelerador web para descargar la carga del servidor web real y, a su vez, realizar la función de balanceador de carga solicitando una petición a cada servidor web real mediante un esquema de peticiones round-robin.
  • Almacenamiento compartido: Usaremos DRBD para replicar la información entre dos volúmenes lógicos, proporcionando redundancia en caso de caída de un nodo o bien fallo catastrófico de los discos duros de una de las máquinas, y OCFS2 para proporcionar un acceso concurrente a los datos de dicho dispositivo replicado.
  • Servidor de bases de datos: Usaremos MySQL por ser su uso el más extendido entre aplicaciones PHP. A su vez usaremos un esquema de replicación circular para proporcionar una mayor disponibilidad de los datos y minimizar el tiempo de recuperación de servicio en caso de caída de un nodo (aunque ello no implica consistencia como veremos más adelante en los "contras").
En la próxima entrega comenzaremos montando el sistema de archivos compartido donde alojaremos las páginas web de los usuarios.

4 comentarios:

  1. Buen articulo

    muy claro y util ya que en estos dias quiero levantar una plataforma de similares caracteristicas y estoy documentandome por el momento

    sigo atento tu blog :D

    saludos y gracias

    ResponderEliminar
  2. Perdona la tardanza... a lo largo de esta semana le daré otro empujón al tema :)

    ResponderEliminar
  3. hola, cuando seguirás con este tema?

    ResponderEliminar
  4. Disculpad el retraso. He ido encadenando los exámenes de diciembre con mi posterior paternidad, el trabajo y ahora los exámenes de mayo/junio. La semana que viene termino de entregar los trabajos que me quedan pendientes y retomo el tema. La plataforma puede considerarse madura pq aunque no la he terminado de documentar en el blog, ha estado funcionando con carga real de usuarios durante estos últimos meses (creo que lleva como mínimo unos 6 meses). En breve termino la documentación y explico ciertas modificaciones que hice a la arquitectura original para mejorar el rendimiento, aunque fue a costa de agregar una tercera máquina para centralizar el almacenamiento.

    ResponderEliminar