Arquitecturas Basadas en Microservicios : Spring Cloud Ribbon

Ribbon es una librería usada para la intercomunicación de procesos, desarrollada por Netflix para su uso interno, y que se integra perfectamente con Apache Feign e Apache Eureka en el que vimos en los pasados post.

Ribbon nos da las siguientes capacidades:

  • Balanceo de carga, usando varios algoritmos que luego explicaremos detalladamente
  • Tolerancia a fallos. Ribbon determina dinámicamente qué servicios están corriendo y activos, al igual que cuales están caídos
  • Soporte de protocolo múltiple (HTTP, TCP, UDP) en un modelo asincrónico y reactivo
  • Almacenamiento en caché y procesamiento por lotes
  • Integración con los servicios de autodescubrimiento, como por ejemplo Eureka o Consul

Las arquitecturas basadas en microservicios suelen tener implementación multiregional y multizona ya que así conseguimos tener disponibilidad y la resiliencia de los servicios. Por ello Ribbon nos puede ayudar a resolver estos problemas.

Configuración

Destaca por su capacidad de balanceo de carga encargado por varios algoritmos. Esta parte es totalmente configurable y existen las siguientes posibilidades:

  • RoundRobinRule: algoritmo de uso muy extendido, donde los servidores van rotando uno tras otro
  • AvailabilityFilteringRule: el balanceador de carga puede evitar una zona al elegir el servidor
  • WeightedResponseTimeRule: esta regla usa los tiempos medios de respuesta para asignar pesos a los servidores, es como usar un “Weighted Round Robin”
  • DynamicServerListLoadBalancer: tiene la capacidad de obtener la lista de servidores candidatos utilizando una fuente dinámica
  • Podemos definir nuestra propia regla custom

Además de la regla para el balanceo podemos configurar las siguientes interfaces:

  • IClientConfig: almacena la configuración del cliente para el cliente
  • ILoadBalancer: representa el balanceador
  • ServerList: define cómo obtener una lista de servidores disponibles para elegir
  • IPing: indica cómo se realizan los pings periódicos a los servidores

También el componente Cliente de Ribbon ofrece más opciones de configuración, tales como:

  • Tiempos de espera de conexión
  • Reintentos
  • Algoritmos de reintento (exponencial, límite acotado)

Ejemplo de uso

El código de nuestro ejemplo lo puedes encontrar aquí. 

Aunque Ribbon se puede usar por sí solo, nosotros aconsejamos usarlo con la integración de un autodescubridor como Eureka o Cónsul, y Feign para implementar los clientes. Si quieres saber cómo usar Ribbon sin estas integraciones te recomiendo este ejemplo y la documentación de Spring Cloud Ribbon.
Nos vamos a basar en el mismo ejemplo que en el post de Feign, ya habilitado Eureka como vimos en el post del mismo.

Para añadir Ribbon añadiremos la siguiente dependencia:

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>

Una vez hecho cambiamos nuestro cliente:

@FeignClient(name = "user-service")
interface UserClient {
	@GetMapping("/")
	List<User> getAll();
	@GetMapping("/{company}")
	List<User> getByCompany(@PathVariable("company") String company);
	@Component
	@Slf4j
	class HystrixClientFallback implements UserClient {
		@Override
		public List<User> getAll() {
			log.error("Error getAll");
			throw new RuntimeException();
		}
		@Override
		public List<User> getByCompany(String company) {
			log.error("Error getByCompany with company {}", company);
			return Collections.emptyList();
		}
	}
}

Como vemos, estamos usando el nombre del servicio en vez de la url y ya lo tendríamos, así de fácil. En el log veremos la siguiente traza en la llamada entre servicios:

2018-05-30 10:12:28.843  INFO 8841 --- [onPool-worker-1] c.n.l.DynamicServerListLoadBalancer      : DynamicServerListLoadBalancer for client user-service initialized: DynamicServerListLoadBalancer:{NFLoadBalancer:name=user-service,current list of Servers=[XXX.XXX.XXX.XXX:8080],Load balancer stats=Zone stats: {defaultzone=[Zone:defaultzone;	Instance count:1;	Active connections count: 0;	Circuit breaker tripped count: 0;	Active connections per server: 0.0;]
},Server stats: [[Server:XXX.XXX.XXX.XXX:8080;	Zone:defaultZone;	Total Requests:0;	Successive connection failure:0;	Total blackout seconds:0;	Last connection made:Thu Jan 01 01:00:00 CET 1970;	First connection made: Thu Jan 01 01:00:00 CET 1970;	Active Connections:0;	total failure count in last (1000) msecs:0;	average resp time:0.0;	90 percentile resp time:0.0;	95 percentile resp time:0.0;	min resp time:0.0;	max resp time:0.0;	stddev resp time:0.0]
]}ServerList:org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList@6fa4979d

De una manera sencilla hemos añadido Ribbon, todo ello gracias a las autoconfiguraciones de Spring Boot.

Conclusión

Como hemos visto Ribbon ofrece una manera sencilla de realizar interconexión entre nuestros microservicios totalmente configurable, además de una buena integración con todo el sistema Spring Cloud.

Referencias