Registro y descubrimiento de servicios con Spring Cloud y Consul

Escrito por picodotdev el .
java planeta-codigo programacion spring
Enlace permanente Comentarios

Tradicionalmente el conectar un servicio con sus servicios dependientes se ha realizado por configuración, normalmente mediante un nombre de dominio y su puerto. Esta configuración estática es suficiente para unos pocos servicios y que no varían durante su funcionamiento. Con el advenimiento de los microservicios con su estado y número cambiantes en el tiempo han surgido varias herramientas para en vez de usar configuración usar descubrimiento. Una de estas herramientas Consul para la que Spring Cloud proporciona integración.

En una aplicación con una arquitectura de microservicios esta se compone de múltiples partes cambiantes. Los microservicios pueden aparecer, desaparecer, variar en número o cambiar de ubicación, la aplicación debe ser tolerante a esos cambios y seguir proporcionando su servicio. Por tanto, la configuración de red de los servicios no se puede realizar usando direcciones IP ya que no se conocen las que utilizarán los microservicios y usar nombres de dominio de DNS puede no ser viable ya que los cambios tardan en propagarse. Conocer el nombre de host y puerto reales de los microservicios es proporcionado por la funcionalidad de descubrimiento de servicios o service discovery que proporcionan algunos servicios como Eureka, Consul o Apache Zookeper.

En este artículo explicaré como usar la parte de descubrimiento de servicios de Consul usando una aplicación con Spring Boot y con Spring Cloud. Spring Cloud proporciona varias cosas comunes para aplicaciones basadas en microservicios. Si aún no conoces las herramientas en las que se basará el ejemplo puedes consultar los siguientes artículos específicos como introducción:

Consul además de descubrimiento de servicios proporciona otras funcionalidades como detección de fallos o caídas para prevenir enviar peticiones a máquinas fuera de servicio y almacenamiento básico clave/valor para configuración dinámica o activación de características. Dispone de una aplicación web en la que podemos ver el estado de los servicios, una API REST con la que comunicarse con Consul en una aplicación o en cada microservicio y un servidor de nombres DNS, podemos usar cualquiera de las dos interfaces de consulta, la basada en la API REST o la basada en DNS para obtener las direcciones IP con la ubicación de los servicios.

Instalar Consul es muy sencillo basta con descargar un binario y descargar la interfaz web si queremos tener el dashboard con la información del servicio. Descargados y descomprimidos Consul se inicia con el siguiente comando. Podemos acceder al panel dashboard con la dirección http://localhost:8500 con un navegador web. Inicialmente en el panel de servicios solo se encuentra el propio de Consul cuando aún no se ha registrado ningún servicio, aplicación o microservicio.

1
2
#!/usr/bin/env bash
consul agent -server -client=0.0.0.0 -data-dir /tmp/consul -ui-dir ./webui
consul.sh

Una aplicación que use Spring Boot y que quiera hacer pública su disponibilidad en Consul basta con que use la anotación @EnableDiscoveryClient en la clase de inicio de la aplicación junto con las dependencias adecuadas. Con la declaración de esta anotación y la dependencia spring-cloud-starter-consul-all Spring se comunicará con Consul a través de la API REST para registrar cuando se inicie la aplicación, su nombre, nombre de máquina y puerto en el que estará disponible.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package io.github.picodotdev.blogbitix.springcloud.client;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.util.List;

@SpringBootApplication
@EnableDiscoveryClient
public class Main implements CommandLineRunner {

    @Value("${config.key}")
    String key = null;

    @Autowired
    private DiscoveryClient discoveryClient;

    @Override
    public void run(String... args) {
        System.out.printf("Valor de propiedad de configuración (%s): %s%n", "config.key", key);
        System.out.println("Servicios:");
        discoveryClient.getServices().forEach(service -> {	        
            List<ServiceInstance> instances = discoveryClient.getInstances(service);
            ServiceInstance instance = instances.get(0);
            System.out.printf("%s (%d): %s:%d %s%n", service, instances.size(), instance.getHost(), instance.getPort(), instance.getUri());
        });
    }

    public static void main(String[] args) throws Exception {
        SpringApplication application = new SpringApplication(Main.class);
        application.setApplicationContextClass(AnnotationConfigApplicationContext.class);
        SpringApplication.run(Main.class, args);
    }
}
Main.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
server:
  port: ${port:8080}

spring:
  cloud:
    consul:
      discovery:
        instanceId: ${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}

config:
  key: prod
application.yml

Spring Cloud proporciona además un servicio que podemos usar para conocer los servicios registrados en Consul, con la clase DiscoveryClient podemos conocer los nombres de los servicios, su nombre de máquina y puerto desde una aplicación Java. En el método run de la clase Main se usa en este ejemplo para imprimir en la salida el listado de servicios registrados en Consul. Uno de esos servicios esta aplicación de ejemplo, ya que se registra en Consul cuando se inicia.

Servicios registrados en Consul

Consul para conocer que los servicios siguen en funcionamiento hace una petición HTTP cada ciertos segundos a una ruta de la aplicación, Spring Boot proporciona una dependencia, spring-boot-starter-actuator, que usada provee del endpoint /health para que Consul monitorice el estado del servicio.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
plugins {
    id 'application'
    id 'org.springframework.boot' version '1.4.4.RELEASE'
}

mainClassName = 'io.github.picodotdev.blogbitix.springcloud.client.Main'

dependencies {
	compile 'org.springframework:spring-context:4.3.6.RELEASE'
	compile('org.springframework.boot:spring-boot-starter:1.4.4.RELEASE') { exclude(group: 'ch.qos.logback') }
	compile('org.springframework.boot:spring-boot-starter-web:1.4.4.RELEASE') { exclude(group: 'ch.qos.logback') }
	compile('org.springframework.boot:spring-boot-starter-actuator:1.4.4.RELEASE') { exclude(group: 'ch.qos.logback') }
	compile('org.springframework.cloud:spring-cloud-starter-consul-all:1.1.2.RELEASE') { exclude(group: 'ch.qos.logback') }
}
build.gradle

Endpoint de estado de servicio

Esta es la salida en la consola listando los servicios disponibles, siendo uno de ellos esta aplicación.

1
2
3
4
Valor de propiedad de configuración (config.key): prod
Servicios:
consul (1): 192.168.1.2:8300 http://192.168.1.2:8300
springcloudclient (1): 192.168.1.2:8080 http://192.168.1.2:8080
System.out

El código fuente completo del ejemplo puedes descargarlo del repositorio de ejemplos de Blog Bitix alojado en GitHub y probarlo en tu equipo ejecutando siguiente comando:
./consul/consul.sh y ./gradlew run

Este artículo forma parte de la serie spring-cloud:

  1. Datos de sesión externalizados con Spring Session
  2. Aplicación Java autocontenida con Spring Boot
  3. Configuración de una aplicación en diferentes entornos con Spring Cloud Config
  4. Información y métricas de la aplicación con Spring Boot Actuator
  5. Registro y descubrimiento de servicios con Spring Cloud y Consul
  6. Aplicaciones basadas en microservicios
  7. Registro y descubrimiento de servicios con Spring Cloud Netflix
  8. Servicio de configuración para microservicios con Spring Cloud Config
  9. Recargar sin reiniciar la configuración de una aplicación Spring Boot con Spring Cloud Config
  10. Almacenar cifrados los valores de configuración sensibles en Spring Cloud Config
  11. Tolerancia a fallos en un cliente de microservicio con Spring Cloud Netflix y Hystrix
  12. Balanceo de carga y resilencia en un microservicio con Spring Cloud Netflix y Ribbon
  13. Proxy para microservicios con Spring Cloud Netflix y Zuul
  14. Monitorizar una aplicación Java de Spring Boot con Micrometer, Prometheus y Grafana
  15. Exponer las métricas de Hystrix en Grafana con Prometheus de una aplicación Spring Boot
  16. Servidor OAuth, gateway y servicio REST utilizando tokens JWT con Spring
  17. Trazabilidad en microservicios con Spring Cloud Sleuth
  18. Implementar tolerancia a fallos con Resilience4j
  19. Iniciar una aplicación de Spring Boot en un puerto aleatorio
  20. Utilizar credenciales de conexión a la base de datos generadas por Vault en una aplicación de Spring
  21. Microservicios con Spring Cloud, Consul, Nomad y Traefik
Comparte el artículo: