Spring Cloud Series: Balanceo de carga en el cliente (client side load balancing) usando Ribbon

Miguel Doctor Yuste
6 min readMar 11, 2020

En el post anterior (consultar) explicamos cómo implementar un microservicio muy básico (echoService) que obtenía su configuración de nuestro Spring Cloud Config (consultar), que se registraba como cliente en nuestro servicio de registro y descubrimiento Eureka (consultar) y que era accedido a través de nuestro servicio Gateway basado en Spring Netflix Zuul.

En este post vamos a hablar sobre qué es el balanceo de carga y cómo puede implementarse con ayuda de la plataforma Spring Cloud, concretamente mediante el uso y configuración del componente Spring Cloud Ribbon. Por último, utilizaremos nuestro servicio Gateway basado en Zuul en combinación Ribbon para acceder a diferentes instancias de nuestro servicio echo-service.

Qué es Ribbon y cómo se integra con otros componentes de la plataforma Spring Cloud?

Spring Cloud Ribbon es un librería que permite la comunicación entre diferentes procesos cuya principal característica es proporcionar diferentes algoritmos para realizar balanceo de carga desde el lado del cliente (client-side load balancing). Además de client-side load balancing, Ribbon proporciona otras funciones de gran utilidad, algunas de las cuales vamos a comentar a continuación.

  • Integración con Eureka: Ribbon permite realizar tareas de balanceo de carga entre servicios desplegados en entornos distribuidos/cloud. Concretamente permite obtener información de los servicios registrados en Eureka y realizar el balanceo de carga entre ellos. También permite definir una lista de servicios de manera explícita, tal y como explicaremos más adelante en este artículo.
  • Tolerancia a fallos (Fault Tolerance): Una de las grandes ventajas que proporciona Ribbon, es que permite determinar qué servicios están activos o caídos de manera dinámica y así actuar en consecuencia para garantizar el servicio.
  • Estrategias de balanceo de carga estándar y a medida: Ribbon proporciona varias estrategias para el balanceo de carga, tales como RoundRobinRule, AvailabilityFilteringRule o WeightedResponseTimeRule. Además, en caso de necesitar algún tipo de estrategia ajustada a necesidades particulares, Ribbon permite crear las clases que permitan definirla.

Ribbon se integra perfectamente con otros componentes de la plataforma Spring Cloud, como por ejemplo Zuul, el cual lo utiliza para obtener información de los servicios registrados en Eureka.

En este post vamos a ver un pequeña introducción sobre cómo utilizar Ribbon para realizar un balanceo de carga entre dos servicios que son accesibles mediante nuestro Gateway basado en Zuul.

Entorno

El tutorial paso a paso está escrito usando el siguiente entorno:

  • Sistema Operativo: Mac OS Sierra 10.12.6
  • Maven — Versión: 3.3.9
  • Java — Versión: 1.8.0_131-b11
  • IntelliJ IDEA — Community 2018.2
  • Spring Boot — Versión: 2.1.3.RELEASE
  • Spring Cloud — Versión: Greenwich.SR1
  • Spring Cloud Config Server — Servicio desarrollado en un post anterior (aquí)
  • Servicio de Registro y Descubrimiento basado en Eureka — Servicio desarrollado en un post anterior y modificado en branch chapter 3 (aquí)
  • Servicio Gateway Zuul — Servicio desarrollado en un post anterior (aquí)
  • Servicio Echo-service — Servicio desarrollado en el post anterior (aquí)

Modificación del servicio cliente “EchoService”

Para ilustrar el funcionamiento del balanceo de carga vamos a realizar una serie de modificaciones en los componentes de la plataforma que venimos desarrollando en esta serie sobre Spring Cloud.

En primer lugar vamos modificar el servidor EchoService desarrollado en el post anterior (aquí).

En primer lugar editaremos el archivo EchoServiceController.java tal y cómo se indica a continuación, añadiendo el atributo port y modificando el String devuelto incluyendo dicho puerto en la salida a las llamadas get ofrecidas por el controller.

@RestController
public class EchoServiceController {

@Value("${server.port}")
private String port;

@RequestMapping(value = "/")
public String echoService(){
return "Echo Service " + "from port "+port;
}

@GetMapping("/{id}")
public String echoService(@PathVariable String id){
return id + " from port "+port;
}
}

A continuación debemos modificar el archivo de configuración de nuestro servicio EchoService. El fichero de configuración se llama echo-service.yml y se encuentra en el repositorio de Github gestionado a través de nuestro servicio Spring Cloud Config. La modificación consiste en indicar que el puerto en el que se va a ejecutar el servicio puede ser pasado cómo parámetro a la hora de arrancar el servidor. La siguiente imagen muestra cómo debe quedar dicho archivo.

Archivo echo-service.yml con el valor ${port:8091} para la propiedad port

Una vez modificado el archivo de configuración vamos comprobar que el servicio echo-service se ejecuta sin problemas en diferentes puertos para así poder configurar el balanceo de carga de Zuul usando Ribbon. Para ello arrancamos (si no lo hemos hecho ya) el servidor Spring Cloud Config, el servicio de descubrimiento Eureka y el servicio Gateway Zuul. Una vez, estén dichos servicios funcionando, procedemos a arrancar dos instancias del servicio echo-service en los puertos 8091 y 8092. Para ello, podemos utilizar el terminal o cualquier IDE que utilicemos. En nuestro caso usaremos el terminal y ejecutaremos las siguientes instrucciones desde el directorio del proyecto del servicio echo-service:

$ mvn spring-boot:run -Dspring-boot.run.arguments=--port=8091$ mvn spring-boot:run -Dspring-boot.run.arguments=--port=8092

Para comprobar que ambos servicios están funcionando correctamente, vamos a acceder a nuestro servidor de registro Eureka (http://localhost:8761/) y debemos comprobar que hay 2 instancias del servicio echo-service registradas, tal y como se muestra en la siguiente imagen.

Servidor Eureka mostrando los servicios registrados

Configuración de Zuul para realizar balanceo de carga usando Ribbon

El siguiente paso consiste en configurar Zuul para que haga uso de Ribbon y realice balanceo de carga entre una lista de servicios (en nuestro caso los servicios echo-service corriendo en los puertos 8091 y 8092. Para ello vamos a nuestro repositorio de Github que contiene los archivos de configuración utilizados por nuestro servidor Spring Cloud Config. En dicho repositorio, localizamos el archivo zuul-server.yml, que creamos y explicamos en un post anterior (aquí).

Ahora debemos modificar el archivo tal y como se muestra a continuación:

https://gist.github.com/migueldoctor/3201be2493ea20f71f8baf70ad5b9dc7

Y ahí especificamos la lista de instancias con las urls y los puertos en los que están los microservicios entre los que se realizará el balanceo de carga con Ribbon.

Comprobamos que funciona!

Para comprobar que nuestro gateway basado en Zuul con balanceo de carga usando Ribbon ha sido configurado correctamente, debemos arrancar los servicios SpringCloudConfig, Eureka, Gateway Zuul y por último dos instancias de EchoService tal y como hicimos antes. Una vez todos los servicios están funcionando abrimos nuestro navegador web y accedemos al servidor Zuul (puerto 8080) con el path /echo/. El servidor Zuul enviará la petición al servicio echoService correspondiente alternando entre los servicios configurados usando una estrategia Round Robin. Para comprobarlo refrescaremos varias veces y veremos como la respuesta nos viene proporcionada por servicios en diferentes puertos, tal y como vemos en la imagen.

Balanceo de carga del Servicio Echo usando de Zuul y Ribbon

Por supuesto podemos cambiar la estrategia de balanceo de carga, pero eso queda fuera del objetivo de este post.

En el siguiente artículo…

En Github puedes encontrar como siempre el código de ejemplo implementado.

  • Spring Cloud Config Server (aquí)
  • Servicio de Registro y Descubrimiento basado en Eureka. Modificado en branch chapter 3 (aquí)
  • Servicio Gateway Zuul (aquí)
  • Servicio EchoService. Modificado en branch chapter 5(aquí)
  • Archivo de configuración externo para Zuul (aquí)

En siguientes post seguiremos hablando de algunos componentes ya comentados como Ribbon e introduciendo nuevos componentes de la plataforma Spring Cloud, tales como Feign (que permite comunicar diferentes microservicios de manera fácil y declarativa), Hystrix (para implementar el patrón circuit breaker) o Sleuth y Zipkin (que nos ayudan a diagnosticar problemas en nuestra plataforma).

Con esto hemos llegado al final del artículo, en caso de duda puedes usar la sección de comentarios e intentaré responderte cuanto antes. Recuerda aplaudir el artículo si te ha resultado útil.

--

--

Miguel Doctor Yuste

Ph.D, AI Data Scientist, Software Engineer, Cloud Architect, Systems Engineer, happy father and happy husband :)