Equilibrio de carga

Completado

Una estrategia eficaz para llevar a cabo un escalado que satisfaga la demanda consiste en escalar horizontalmente poniendo en línea nuevas máquinas virtuales cuando el tráfico aumenta. El hecho de que las máquinas virtuales se puedan aprovisionar rápidamente es esencial para conseguir elasticidad. De todos modos, no es útil poner en línea servidores adicionales, a menos que el tráfico se distribuya entre ellos. En general, esto ayuda a que el sistema controle el aumento de la carga. Este es el motivo por el que el equilibrio de carga es tan importante para la elasticidad, ya que puede ajustar de manera dinámica el número de recursos dedicados a una tarea.

La necesidad de equilibrio de carga deriva de dos requisitos básicos. En primer lugar, el procesamiento paralelo mejora el rendimiento. Si un solo servidor puede administrar 5000 solicitudes por unidad de tiempo, 10 servidores con un equilibrio de carga perfecto pueden controlar 50 000 solicitudes por unidad de tiempo. En segundo lugar, los recursos con equilibrio de carga producen una mayor disponibilidad. En lugar de reenviar una solicitud a un servidor que tiene dificultades para seguir el ritmo, un equilibrador de carga puede dirigir la solicitud a un servidor con una carga más ligera. Además, si un servidor se queda sin conexión y el equilibrador de carga lo reconoce, puede dirigir las solicitudes a otros servidores.

¿Qué es el equilibrio de carga?

Una forma conocida de equilibrio de carga es el DNS round robin, que emplean muchos servicios web grandes para distribuir las solicitudes entre varios servidores. En concreto, varios servidores front-end, cada uno de ellos con una dirección IP única, comparten un nombre DNS. Para equilibrar el número de solicitudes en cada servidor web, las grandes empresas como Google mantienen un grupo de direcciones IP para cada entrada DNS. Cuando un cliente realiza una solicitud (por ejemplo, a www.google.com), el DNS de Google selecciona una de las direcciones disponibles del grupo y la envía al cliente. La estrategia más sencilla empleada para enviar direcciones IP consiste en usar una cola round robin, donde después de cada respuesta DNS, la lista de direcciones se permuta.

Antes de la llegada de la nube, el equilibrio de carga de DNS era una forma sencilla de reducir la latencia de las conexiones de larga distancia. El distribuidor en el servidor DNS estaba programado para responder con la dirección IP del servidor geográficamente más cercano al cliente. La forma más fácil de hacerlo era responder con la dirección IP del grupo numéricamente más cercano a la dirección IP del cliente. Este método no era fiable, ya que las direcciones IP no se distribuyen en una jerarquía global. Las técnicas actuales son más sofisticadas y se basan en una asignación de software de direcciones IP a ubicaciones en función de asignaciones físicas de proveedores de servicios de Internet (ISP). Dado que esta asignación se implementa como una búsqueda de software costosa, este método produce mejores resultados, pero es caro de calcular. Aun así, el coste de una búsqueda lenta se amortiza, ya que la búsqueda DNS solo se produce cuando el cliente realiza la primera conexión a un servidor. Todas las comunicaciones posteriores se producen directamente entre el cliente y el servidor que posee la dirección IP enviada. En la figura 9 se muestra un ejemplo de un esquema de equilibrio de carga DNS.

Figura 9: Equilibrio de carga en un entorno de nube.

Figura 9: Equilibrio de carga en un entorno de nube.

El inconveniente de este método es que se produzca un error del servidor, ya que el cambio a una dirección IP diferente depende de la configuración del período de vida (TTL) de la memoria caché DNS. Se sabe que las entradas DNS tienen una duración prolongada y que las actualizaciones tardan más de una semana en propagarse. Esto significa que es difícil "ocultarle" rápidamente al cliente un error del servidor. Al reducir la validez (TTL) de una dirección IP en la memoria caché, esto se mejora a expensas del rendimiento y el aumento del número de búsquedas.

En la actualidad, el equilibrio de carga suele hacer referencia al uso de una instancia dedicada (o un par de instancias) para enviar las solicitudes entrantes a los servidores back-end. Para cada solicitud entrante en un puerto especificado, el equilibrador de carga redirige el tráfico a uno de los servidores back-end según una estrategia de distribución. Cuando lo hace, el equilibrador de carga mantiene los metadatos de la solicitud, incluida información como los encabezados del protocolo de aplicación (por ejemplo, los encabezados HTTP). En esta situación, la información obsoleta no supone un problema, ya que todas las solicitudes pasan a través del equilibrador de carga.

Aunque todos los tipos de equilibradores de carga de red reenvían las solicitudes junto con todo el contexto a los servidores back-end, cuando devuelven la respuesta al cliente, podrían emplear una de las dos estrategias básicas siguientes1:

  • Conexiones proxy: según este método, el equilibrador de carga recibe la respuesta del back-end y la retransmite al cliente. El equilibrador de carga se comporta como un proxy web estándar y participa en las dos partes de una transacción de red, ya que reenvía la solicitud al cliente y devuelve la respuesta.

  • Entrega TCP: según este método, la conexión TCP con el cliente se entrega al servidor back-end y este envía la respuesta directamente al cliente, sin pasar por el equilibrador de carga.

La segunda de estas estrategias está ilustrada en la figura 10.

Figura 10: Mecanismo de entrega TCP del distribuidor al servidor back-end.

Figura 10: Mecanismo de entrega TCP del distribuidor al servidor back-end.

Ventajas del equilibrio de carga

Una de las ventajas del equilibrio de carga es que ayuda a ocultar los errores de un sistema. Siempre que el cliente esté expuesto a un único punto de conexión que represente varios recursos, se le ocultarán los errores en los recursos individuales, ya que las solicitudes se atenderán mediante el uso de otros recursos. Pero entonces el propio equilibrador de carga se convertirá en un único punto de error. Si se produce un error por alguna razón, aunque todos los servidores back-end sigan funcionando, no se procesará ninguna solicitud del cliente. Por lo tanto, para lograr una alta disponibilidad, los equilibradores de carga se suelen implementar por parejas.

Y, lo que es más importante, el equilibrio de carga mejora la capacidad de respuesta al distribuir las cargas de trabajo entre varios recursos de proceso en la nube. El hecho de tener una única instancia de proceso en la nube tiene varias limitaciones. En módulos anteriores se trató el tema de la limitación física del rendimiento, cuando se requieren más recursos para aumentar las cargas de trabajo. Mediante el equilibrio de carga, las cargas de trabajo de mayor tamaño se distribuyen entre varios recursos, de modo que cada recurso pueda satisfacer sus solicitudes de forma independiente y en paralelo, lo que mejora el rendimiento de la aplicación. El equilibrio de carga también mejora los tiempos de respuesta medios, ya que hay más servidores para controlar la carga de trabajo.

Las comprobaciones de mantenimiento son fundamentales para implementar estrategias de equilibrio de carga correctas. Un equilibrador de carga debe saber cuándo deja de estar disponible un recurso, para evitar el reenvío de tráfico a ese recurso. La supervisión de eco de ping, en la que el equilibrador de carga hace ping a los servidores con solicitudes del Protocolo de mensajes de control de Internet (ICMP), es una de las tácticas más populares que se usan para comprobar el mantenimiento de recursos específicos. Además de tener en cuenta el mantenimiento de un recurso al reenviarle tráfico, algunas estrategias de equilibrio de carga toman en consideración otras métricas, como el rendimiento, la latencia y el uso de CPU.

Muchas veces, los equilibradores de carga deben garantizar una alta disponibilidad. La manera más sencilla de hacerlo consiste en crear varias instancias de equilibrio de carga (cada una de ellas con una dirección IP única) y vincularlas a una dirección DNS única. Cada vez que se produzca un error en un equilibrador de carga por cualquier motivo, se reemplazará por uno nuevo y todo el tráfico se pasará a la instancia de conmutación por error con un impacto mínimo en el rendimiento. Al mismo tiempo, se puede configurar una nueva instancia del equilibrador de carga para reemplazar el que presentó el error. Además, es necesario actualizar de inmediato los registros DNS.

Aparte de distribuir las solicitudes entre los servidores back-end, los equilibradores de carga suelen emplear mecanismos para reducir la carga en los servidores y mejorar el rendimiento general. Entre estos mecanismos se incluyen los siguientes:

  • Descarga SSL: las conexiones HTTPS conllevan un coste de rendimiento adicional, ya que el tráfico que pasa a través de ellas está cifrado. En lugar de atender todas las solicitudes a través de la Capa de sockets seguros (SSL), la conexión de cliente con el equilibrador de carga se puede realizar a través de SSL, mientras que las solicitudes de redireccionamiento a cada servidor se realizan a través de HTTP sin cifrar. Esta técnica reduce considerablemente la carga en los servidores. Además, se mantiene la seguridad, siempre y cuando las solicitudes de redireccionamiento no se realicen a través de una red abierta.

  • Almacenamiento en búfer de TCP: estrategia para descargar clientes con conexiones lentas al equilibrador de carga para aliviar los servidores que atienden las respuestas a estos clientes.

  • Almacenamiento en caché: en algunas situaciones, el equilibrador de carga puede mantener una memoria caché para las solicitudes más populares (o para las solicitudes que se pueden controlar sin recurrir a los servidores, como el contenido estático) con el fin de reducir la carga en los servidores.

  • Conformado de tráfico: un equilibrador de carga puede usar esta técnica para retrasar o volver a priorizar el flujo de paquetes a fin de optimizar el tráfico para la configuración del servidor. Esto afecta a la calidad del servicio en algunas solicitudes, pero garantiza que se pueda atender la carga entrante.

Es importante recordar que el equilibrio de carga solo funciona si el propio equilibrador de carga no se encuentra bajo una carga insuperable. De lo contrario, el equilibrador de carga se convertirá en el cuello de botella. Afortunadamente, los equilibradores de carga suelen llevar a cabo un escaso procesamiento en las solicitudes que reciben, ya que dependen de los servidores back-end para realizar el trabajo real de convertir las solicitudes en respuestas.

Distribución equitativa

En la nube, se usan varias estrategias de equilibrio de carga. Una de las más comunes es la distribución equitativa, que usa un sencillo algoritmo round robin para distribuir el tráfico de manera uniforme entre todos los nodos. No tiene en cuenta el uso de recursos individuales en el sistema ni el tiempo de ejecución de la solicitud. Este enfoque intenta mantener ocupados todos los nodos del sistema y es uno de los más sencillos de implementar.

AWS usa este enfoque en su oferta de Elastic Load Balancer (ELB). ELB aprovisiona equilibradores de carga que equilibran el tráfico entre las instancias de EC2 asociadas. Los equilibradores de carga son básicamente instancias de EC2 con un servicio para enrutar el tráfico de forma específica. A medida que se escalan horizontalmente los recursos subyacentes al equilibrador de carga, se actualizan las direcciones IP de los nuevos recursos en el registro DNS del equilibrador de carga. Este proceso tarda varios minutos en completarse, ya que requiere tiempo de supervisión y aprovisionamiento. Este período de escalado (el tiempo de espera hasta que el equilibrador de carga está listo para controlar la carga más alta) se conoce como "preparación" del equilibrador de carga.

Los equilibradores de carga de AWS también supervisan los recursos que tienen asociados para la distribución de cargas de trabajo a fin de realizar una comprobación del mantenimiento. Se usa un mecanismo de eco de ping para asegurarse de que todos los recursos se encuentren en un estado correcto. Los usuarios de ELB pueden configurar los parámetros de la comprobación de mantenimiento mediante el establecimiento de los retrasos y el número de reintentos.

Distribución basada en hash

Este enfoque intenta garantizar que las solicitudes del mismo cliente durante la ejecución de una sesión se dirijan cada vez al mismo servidor. Para ello, se aplica un algoritmo hash a los metadatos que definen cada solicitud y se usa el hash para elegir un servidor. Si la aplicación del algoritmo hash se realiza correctamente, las solicitudes se distribuyen de manera relativamente uniforme entre los servidores. Una ventaja de este enfoque es que se presta a las aplicaciones compatibles con sesiones, que pueden almacenar en memoria los datos de la sesión, en lugar de escribirlos en un almacén de datos compartido, como una base de datos o Redis Cache. Una desventaja es que se debe aplicar un algoritmo hash a todas las solicitudes, lo que introduce una pequeña cantidad de latencia.

Azure Load Balancer usa un mecanismo basado en hash para distribuir las cargas. Este mecanismo crea un hash para cada solicitud en función de la IP de origen, el puerto de origen, la dirección IP de destino, el puerto de destino y el tipo de protocolo. De esta manera, se asegura de que, en circunstancias normales, todos los paquetes de la misma sesión lleguen al mismo servidor back-end. La función hash se elige de modo que la distribución de las conexiones a los servidores sea aleatoria.

Otras estrategias de equilibrio de carga

Si un servidor determinado se vuelve más lento al procesar una solicitud (o un conjunto de solicitudes), los equilibradores de carga que usan algoritmos round robin o de distribución basada en hash le reenviarán las solicitudes de todos modos. Hay otras estrategias más sofisticadas para equilibrar las cargas entre varios recursos que tienen en cuenta la capacidad. Dos de las métricas que se usan con más frecuencia para medir la capacidad son las siguientes:

  • Tiempo de ejecución de la solicitud: las estrategias basadas en esta métrica usan un algoritmo de programación de prioridades, según el cual se usan los tiempos de ejecución de la solicitud para elegir el destino de las solicitudes individuales. El principal desafío al usar este enfoque consiste en medir con precisión los tiempos de ejecución. Un equilibrador de carga puede adivinar los tiempos de ejecución porque usa (y actualiza constantemente) una tabla en memoria que almacena las diferencias entre el momento en que se reenvía una solicitud a cada servidor y el momento en que se devuelve.

  • Uso de recursos: las estrategias basadas en esta métrica emplean el uso de CPU para equilibrar el uso entre los nodos. El equilibrador de carga mantiene una lista ordenada de recursos en función de su uso y dirige cada solicitud que recibe al recurso que experimenta la carga mínima.

Para implementar servicios en la nube escalables, es fundamental un equilibrio de carga. Sin un medio eficaz para distribuir el tráfico entre los recursos de back-end, se limita mucho la elasticidad que se consigue al crear recursos cuando son necesarios y desaprovisionarlos cuando no lo son.

Referencias

  1. Aron, Mohit; Sanders, Darren; Druschel, Peter; y Zwaenepoel, Willy (2000). "Scalable content-aware request distribution in cluster-based network servers" (Distribución de solicitudes con reconocimiento de contenido escalable en servidores de red basados en clúster). Actas de la conferencia técnica anual USENIX de 2000.